diff --git a/Cargo.lock b/Cargo.lock index 1b60668c..01109ef5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2600,6 +2600,7 @@ dependencies = [ [[package]] name = "libunbound" version = "0.1.0" +source = "git+https://github.com/KumoCorp/libunbound-rs.git?rev=5913110316a5c7f4a5fc928b542b2ba053b5cc2a#5913110316a5c7f4a5fc928b542b2ba053b5cc2a" dependencies = [ "libc", "libunbound-sys", @@ -2612,6 +2613,7 @@ dependencies = [ [[package]] name = "libunbound-sys" version = "0.1.0" +source = "git+https://github.com/KumoCorp/libunbound-rs.git?rev=5913110316a5c7f4a5fc928b542b2ba053b5cc2a#5913110316a5c7f4a5fc928b542b2ba053b5cc2a" dependencies = [ "cc", "openssl-sys", diff --git a/Cargo.toml b/Cargo.toml index 57dd5675..e982d251 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ members = [ "crates/throttle", "crates/traffic-gen", "crates/tsa-daemon", - "crates/libunbound-sys", "crates/validate-shaping", "crates/version-info", ] @@ -32,6 +31,7 @@ axum-server = "0.5" data-encoding = "2.4" ed25519-dalek = "2.0" futures = "0.3.28" +libunbound = {git="https://github.com/KumoCorp/libunbound-rs.git", rev="5913110316a5c7f4a5fc928b542b2ba053b5cc2a"} mlua = "0.8" once_cell = "1.17" openssl = { version="0.10.57" } diff --git a/crates/dns-resolver/Cargo.toml b/crates/dns-resolver/Cargo.toml index 24a8aafe..0e320a23 100644 --- a/crates/dns-resolver/Cargo.toml +++ b/crates/dns-resolver/Cargo.toml @@ -19,7 +19,7 @@ anyhow = "1.0" arc-swap = "1.6" kumo-log-types = {path="../kumo-log-types"} lazy_static = "1.4" -libunbound = {path="../libunbound"} +libunbound = {workspace=true} lruttl = {path="../lruttl"} serde = {version="1.0", features=["derive"]} tokio = {workspace=true} diff --git a/crates/libunbound-sys/Cargo.toml b/crates/libunbound-sys/Cargo.toml deleted file mode 100644 index a15ea8bf..00000000 --- a/crates/libunbound-sys/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "libunbound-sys" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] - -[build-dependencies] -cc = {version="1.0", features = ["parallel"]} -tempfile = {workspace=true} - -[target.'cfg(not(any(windows, target_os="macos")))'.dependencies] -openssl-sys = {workspace=true} - -[target.'cfg(any(windows, target_os="macos"))'.dependencies] -openssl-sys = { workspace=true, features=["vendored"] } diff --git a/crates/libunbound-sys/build.rs b/crates/libunbound-sys/build.rs deleted file mode 100644 index 35ee428b..00000000 --- a/crates/libunbound-sys/build.rs +++ /dev/null @@ -1,482 +0,0 @@ -use std::collections::HashSet; -use std::path::PathBuf; - -fn new_build() -> cc::Build { - let mut cfg = cc::Build::new(); - cfg.warnings(false); - cfg.extra_warnings(false); - cfg.flag_if_supported("-Wno-deprecated-declarations"); - - println!("cargo:rerun-if-env-changed=DEP_OPENSSL_INCLUDE"); - if let Some(path) = std::env::var_os("DEP_OPENSSL_INCLUDE") { - if let Some(path) = std::env::split_paths(&path).next() { - if let Some(path) = path.to_str() { - if !path.is_empty() { - cfg.include(path); - } - } - } - } - - if let Some(lib_root) = std::env::var_os("DEP_OPENSSL_ROOT") { - println!( - "cargo:rustc-link-search=native={}", - PathBuf::from(lib_root).join("lib").to_str().unwrap() - ); - } - - cfg -} - -struct Probed { - defined: HashSet, -} - -impl Probed { - fn new() -> Self { - Self { - defined: HashSet::new(), - } - } - - fn try_compile(&self, code: &str) -> std::io::Result { - let temp = tempfile::TempDir::new()?; - let main_c = temp.path().join("main.c"); - std::fs::write(&main_c, format!("{code}"))?; - - let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false); - if let Some(path) = std::env::var_os("DEP_OPENSSL_INCLUDE") { - eprintln!("DEP_OPENSSL_INCLUDE is {path:?}"); - if let Some(path) = std::env::split_paths(&path).next() { - if let Some(path) = path.to_str() { - if !path.is_empty() { - eprintln!("adding {path} to includes"); - cfg.include(path); - } - } - } - } - - let mut cmd = cfg.get_compiler().to_command(); - cmd.current_dir(temp.path()); - - // Source file first - cmd.arg(&main_c); - - // then libraries - if let Ok(lib_root) = std::env::var("DEP_OPENSSL_ROOT") { - eprintln!("DEP_OPENSSL_ROOT is {lib_root:?}"); - cmd.arg(&format!("-L{lib_root}/lib")); - } - cmd.arg("-lssl"); - cmd.arg("-lcrypto"); - - cmd.stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .map(|o| o.status.success()) - } - - fn check_header(&mut self, cfg: &mut cc::Build, name: &str) -> std::io::Result<()> { - let def = name.to_uppercase().replace(".", "_").replace("/", "_"); - let def = format!("HAVE_{def}"); - eprintln!("checking for <{name}>"); - if self.try_compile(&format!( - r#" -#include <{name}> -int main(void) {{ - return 0; -}} -"# - ))? { - eprintln!("defining {def}"); - cfg.define(&def, Some("1")); - self.defined.insert(def); - } - - Ok(()) - } - - fn check_type(&mut self, cfg: &mut cc::Build, name: &str, header: &str) -> std::io::Result<()> { - let def = name.to_uppercase().replace(".", "_").replace("/", "_"); - let def = format!("HAVE_{def}"); - eprintln!("checking for <{name}>"); - if self.try_compile(&format!( - r#" -#include <{header}> -int main(void) {{ - return sizeof({name}); -}} -"# - ))? { - eprintln!("defining {def}"); - cfg.define(&def, Some("1")); - self.defined.insert(def); - } - - Ok(()) - } - - fn check_func(&mut self, cfg: &mut cc::Build, func: &str) -> std::io::Result { - let def = func.to_uppercase(); - let def = format!("HAVE_{def}"); - eprintln!("checking for function {func}"); - if self.try_compile(&format!( - r#" -extern int {func}(); -int main(void) {{ - return {func}(); -}} -"# - ))? { - eprintln!("defining {def}"); - cfg.define(&def, Some("1")); - self.defined.insert(def); - Ok(true) - } else { - Ok(false) - } - } -} - -fn unbound() { - let mut cfg = new_build(); - for f in [ - "services/cache/dns.c", - "services/cache/infra.c", - "services/cache/rrset.c", - "util/as112.c", - "util/data/dname.c", - "util/data/msgencode.c", - "util/data/msgparse.c", - "util/data/msgreply.c", - "util/data/packed_rrset.c", - "iterator/iterator.c", - "iterator/iter_delegpt.c", - "iterator/iter_donotq.c", - "iterator/iter_fwd.c", - "iterator/iter_hints.c", - "iterator/iter_priv.c", - "iterator/iter_resptype.c", - "iterator/iter_scrub.c", - "iterator/iter_utils.c", - "services/listen_dnsport.c", - "services/localzone.c", - "services/mesh.c", - "services/modstack.c", - "services/view.c", - "services/rpz.c", - "util/rfc_1982.c", - "services/outbound_list.c", - "services/outside_network.c", - "util/alloc.c", - "util/config_file.c", - "util/configlexer.c", - "util/configparser.c", - // "util/shm_side/shm_main.c", - "services/authzone.c", - "util/fptr_wlist.c", - "util/locks.c", - "util/log.c", - "util/mini_event.c", - "util/module.c", - "util/netevent.c", - "util/net_help.c", - "util/random.c", - "util/rbtree.c", - "util/regional.c", - "util/rtt.c", - "util/siphash.c", - "util/edns.c", - "util/storage/dnstree.c", - "util/storage/lookup3.c", - "util/storage/lruhash.c", - "util/storage/slabhash.c", - "util/tcp_conn_limit.c", - "util/timehist.c", - "util/tube.c", - "util/proxy_protocol.c", - "util/timeval_func.c", - "util/winsock_event.c", - "validator/autotrust.c", - "validator/val_anchor.c", - "validator/validator.c", - "validator/val_kcache.c", - "validator/val_kentry.c", - "validator/val_neg.c", - "validator/val_nsec3.c", - "validator/val_nsec.c", - "validator/val_secalgo.c", - "validator/val_sigcrypt.c", - "validator/val_utils.c", - "dns64/dns64.c", - /* subnet option - "edns-subnet/edns-subnet.c", - "edns-subnet/subnetmod.c", - "edns-subnet/addrtree.c", - "edns-subnet/subnet-whitelist.c", - */ - "respip/respip.c", - "libunbound/context.c", - "libunbound/libunbound.c", - "libunbound/libworker.c", - "util/ub_event_pluggable.c", - "sldns/keyraw.c", - "sldns/sbuffer.c", - "sldns/wire2str.c", - "sldns/parse.c", - "sldns/parseutil.c", - "sldns/rrdef.c", - "sldns/str2wire.c", - "compat/arc4_lock.c", - "compat/arc4random.c", - "compat/arc4random_uniform.c", - // "compat/fake-rfc2553.c", - //"compat/malloc.c", - //"compat/memcmp.c", - //"compat/memmove.c", - //"compat/reallocarray.c", - "compat/sha512.c", - ] { - cfg.file(&format!("unbound/{f}")); - } - - let mut probe = Probed::new(); - - for hdr in &[ - "TargetConditionals.h", - "arpa/inet.h", - "bsd/stdlib.h", - "bsd/string.h", - "dlfcn.h", - "endian.h", - "event.h", - "expat.h", - "getopt.h", - "glob.h", - "grp.h", - "hiredis/hiredis.h", - "ifaddrs.h", - "inttypes.h", - "iphlpapi.h", - "libkern/OSByteOrder.h", - "linux/net_tstamp.h", - "login_cap.h", - "memory.h", - "net/if.h", - "netdb.h", - "netinet/in.h", - "netinet/tcp.h", - "netioapi.h", - "nettle/dsa-compat.h", - "nettle/eddsa.h", - "nghttp2/nghttp2.h", - "openssl/bn.h", - "openssl/conf.h", - "openssl/core_names.h", - "openssl/dh.h", - "openssl/dsa.h", - "openssl/engine.h", - "openssl/err.h", - "openssl/param_build.h", - "openssl/rand.h", - "openssl/rsa.h", - "openssl/ssl.h", - "poll.h", - "pwd.h", - "stdarg.h", - "stdbool.h", - "stdint.h", - "stdlib.h", - "string.h", - "strings.h", - "sys/endian.h", - "sys/ipc.h", - "sys/param.h", - "sys/resource.h", - "sys/select.h", - "sys/sha2.h", - "sys/shm.h", - "sys/socket.h", - "sys/stat.h", - "sys/sysctl.h", - "sys/types.h", - "sys/uio.h", - "sys/un.h", - "sys/wait.h", - "syslog.h", - "time.h", - "unistd.h", - "vfork.h", - "windows.h", - "winsock2.h", - "ws2tcpip.h", - ] { - probe.check_header(&mut cfg, hdr).unwrap(); - } - - for func in &[ - "BIO_set_callback_ex", - "CRYPTO_THREADID_set_callback", - "CRYPTO_cleanup_all_ex_data", - "DSA_SIG_set0", - "ENGINE_cleanup", - "ERR_free_strings", - "ERR_load_crypto_strings", - "EVP_DigestVerify", - "EVP_EncryptInit_ex", - "EVP_MAC_CTX_set_params", - "EVP_MD_CTX_new", - "EVP_aes_256_cbc", - "EVP_cleanup", - "EVP_default_properties_is_fips_enabled", - "EVP_dss1", - "EVP_sha1", - "EVP_sha256", - "EVP_sha512", - "FIPS_mode", - "HMAC_Init_ex", - "OPENSSL_config", - "OPENSSL_init_crypto", - "OPENSSL_init_ssl", - "OSSL_PARAM_BLD_new", - "OpenSSL_add_all_digests", - "RAND_cleanup", - "SHA512_Update", - "SSL_CTX_set_alpn_protos", - "SSL_CTX_set_alpn_select_cb", - "SSL_CTX_set_ciphersuites", - "SSL_CTX_set_security_level", - "SSL_CTX_set_tlsext_ticket_key_evp_cb", - "SSL_get0_alpn_selected", - "SSL_get0_peername", - "SSL_get1_peer_certificate", - "SSL_set1_host", - "X509_VERIFY_PARAM_set1_host", - "_beginthreadex", - "accept4", - "be64toh", - "chown", - "chroot", - "daemon", - "endprotoent", - "endpwent", - "endservent", - "ev_default_loop", - "ev_loop", - "event_assign", - "event_base_free", - "event_base_get_method", - "event_base_new", - "event_base_once", - "fcntl", - "fork", - "fsync", - "getaddrinfo", - "getauxval", - "getentropy", - "getifaddrs", - "getpwnam", - "getrlimit", - "gettid", - "glob", - "htobe64", - "if_nametoindex", - "ioctlsocket", - "initgroups", - "kill", - "localtime_r", - "memmove", - "poll", - "reallocarray", - "random", - "recvmsg", - "sendmsg", - "setregid", - "setresgid", - "setresuid", - "malloc", - "setreuid", - "setrlimit", - "setsid", - "setusercontext", - "shmget", - "sigprocmask", - "sleep", - "socketpair", - "srandom", - "strftime", - "strptime", - "tzset", - "usleep", - "vfork", - "writev", - ] { - probe.check_func(&mut cfg, func).unwrap(); - } - - if cfg!(target_os = "macos") { - cfg.define("HAVE_ISBLANK", Some("1")); - } else { - if !probe.check_func(&mut cfg, "isblank").unwrap() { - cfg.file(&format!("unbound/compat/isblank.c")); - } - } - - for func in &[ - //"arc4random", - //"arc4random_uniform", - "ctime_r", - "gmtime_r", - "explicit_bzero", - "strlcat", - "strlcpy", - "inet_ntop", - "inet_pton", - "inet_aton", - "malloc", - "memcmp", - "memmove", - "reallocarray", - "strsep", - "snprintf", - "strptime", - ] { - if !probe.check_func(&mut cfg, func).unwrap() { - cfg.file(&format!("unbound/compat/{func}.c")); - } - } - - for t in &["pthread_rwlock_t", "pthread_spinlock_t"] { - probe.check_type(&mut cfg, t, "pthread.h").unwrap(); - } - - if !probe.defined.contains("HAVE_GETENTROPY") { - let name = if cfg!(target_os = "macos") { - "compat/getentropy_osx.c" - } else { - "compat/getentropy_linux.c" - }; - //"compat/getentropy_freebsd.c", - //"compat/getentropy_solaris.c", - //"compat/getentropy_win.c", - cfg.file(&format!("unbound/{name}")); - } - - let ptr_width_bits: usize = std::env::var("CARGO_CFG_TARGET_POINTER_WIDTH") - .unwrap() - .parse() - .unwrap(); - let ptr_width_bytes = format!("{}", ptr_width_bits / 8); - cfg.define("SIZEOF_SIZE_T", Some(ptr_width_bytes.as_str())); - cfg.define("SIZEOF_TIME_T", Some(ptr_width_bytes.as_str())); - cfg.include("."); - cfg.include("unbound"); - - cfg.compile("unbound"); -} - -fn main() { - unbound(); -} diff --git a/crates/libunbound-sys/config.h b/crates/libunbound-sys/config.h deleted file mode 100644 index b3b12c48..00000000 --- a/crates/libunbound-sys/config.h +++ /dev/null @@ -1,929 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* apply the noreturn attribute to a function that exits the program */ -#define ATTR_NORETURN __attribute__((__noreturn__)) - -/* apply the weak attribute to a symbol */ -#define ATTR_WEAK __attribute__((weak)) - -/* Directory to chroot to */ -#define CHROOT_DIR "/usr/local/etc/unbound" - -/* Define this to enable client subnet option. */ -/* #undef CLIENT_SUBNET */ - -/* Do sha512 definitions in config.h */ -/* #undef COMPAT_SHA512 */ - -/* Command line arguments used with configure */ -#define CONFCMDLINE "" - -/* Pathname to the Unbound configuration file */ -#define CONFIGFILE "/usr/local/etc/unbound/unbound.conf" - -/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work - */ -/* #undef DARWIN_BROKEN_SETREUID */ - -/* Whether daemon is deprecated */ -/* #undef DEPRECATED_DAEMON */ - -/* Deprecate RSA 1024 bit length, makes that an unsupported key */ -/* #undef DEPRECATE_RSA_1024 */ - -/* Define this to enable kernel based UDP source port randomization. */ -/* #undef DISABLE_EXPLICIT_PORT_RANDOMISATION */ - -/* default dnstap socket path */ -/* #undef DNSTAP_SOCKET_PATH */ - -/* Define if you want to use debug lock checking (slow). */ -/* #undef ENABLE_LOCK_CHECKS */ - -/* Define this if you enabled-allsymbols from libunbound to link binaries to - it for smaller install size, but the libunbound export table is polluted by - internal symbols */ -/* #undef EXPORT_ALL_SYMBOLS */ - -/* Whether the C compiler accepts the "format" attribute */ -#define HAVE_ATTR_FORMAT 1 - -/* Whether the C compiler accepts the "noreturn" attribute */ -#define HAVE_ATTR_NORETURN 1 - -/* Whether the C compiler accepts the "unused" attribute */ -#define HAVE_ATTR_UNUSED 1 - -/* Whether the C compiler accepts the "weak" attribute */ -#define HAVE_ATTR_WEAK 1 - -/* Define to 1 if you have the declaration of `arc4random', and to 0 if you - don't. */ -/* #undef HAVE_DECL_ARC4RANDOM */ - -/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 - if you don't. */ -/* #undef HAVE_DECL_ARC4RANDOM_UNIFORM */ - -/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you - don't. */ -#define HAVE_DECL_INET_NTOP 1 - -/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you - don't. */ -#define HAVE_DECL_INET_PTON 1 - -/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you - don't. */ -#define HAVE_DECL_NID_ED25519 1 - -/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you - don't. */ -#define HAVE_DECL_NID_ED448 1 - -/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you - don't. */ -#define HAVE_DECL_NID_SECP384R1 1 - -/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 - if you don't. */ -#define HAVE_DECL_NID_X9_62_PRIME256V1 1 - -/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you - don't. */ -#define HAVE_DECL_REALLOCARRAY 1 - -/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you - don't. */ -/* #undef HAVE_DECL_REDISCONNECT */ - -/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 - if you don't. */ -#define HAVE_DECL_SK_SSL_COMP_POP_FREE 1 - -/* Define to 1 if you have the declaration of - `SSL_COMP_get_compression_methods', and to 0 if you don't. */ -#define HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 1 - -/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to - 0 if you don't. */ -#define HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1 - -/* Define to 1 if you have the declaration of `strlcat', and to 0 if you - don't. */ -/* #undef HAVE_DECL_STRLCAT */ - -/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you - don't. */ -/* #undef HAVE_DECL_STRLCPY */ - -/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if - you don't. */ -#define HAVE_DECL_XML_STOPPARSER 1 - -/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ -#define HAVE_FSEEKO 1 - -/* Use portable libbsd functions */ -/* #undef HAVE_LIBBSD */ - -/* Define if we have LibreSSL */ -/* #undef HAVE_LIBRESSL */ - -/* Use libnettle for crypto */ -/* #undef HAVE_NETTLE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETTLE_DSA_COMPAT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETTLE_EDDSA_H */ - -/* Define this to use nghttp2 client. */ -/* #undef HAVE_NGHTTP2 */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NGHTTP2_NGHTTP2_H */ - -/* Use libnss for crypto */ -/* #undef HAVE_NSS */ - -/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */ -/* #undef HAVE_OPENSSL_ADD_ALL_DIGESTS */ - -/* Define if you have POSIX threads libraries and header files. */ -#define HAVE_PTHREAD 1 - -/* Have PTHREAD_PRIO_INHERIT. */ -//#define HAVE_PTHREAD_PRIO_INHERIT 1 - -/* Define to 1 if the system has the type `pthread_rwlock_t'. */ -//#define HAVE_PTHREAD_RWLOCK_T 1 - -/* Define to 1 if the system has the type `pthread_spinlock_t'. */ -//#define HAVE_PTHREAD_SPINLOCK_T 1 - -/* Define if you have Python libraries and header files. */ -/* #undef HAVE_PYTHON */ - -/* Define to 1 if you have the `RAND_cleanup' function. */ -/* #undef HAVE_RAND_CLEANUP */ - -/* Using Solaris threads */ -/* #undef HAVE_SOLARIS_THREADS */ - -/* Define if you have the SSL libraries installed. */ -#define HAVE_SSL /**/ - -/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ -#define HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST 1 - -/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ -/* #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - -/* Define to 1 if `fork' works. */ -#define HAVE_WORKING_FORK 1 - -/* Define to 1 if `vfork' works. */ -#define HAVE_WORKING_VFORK 1 - -/* Define to 1 if you have the `writev' function. */ -#define HAVE_WRITEV 1 - -/* If HMAC_Init_ex() returns void */ -/* #undef HMAC_INIT_EX_RETURNS_VOID */ - -/* if lex has yylex_destroy */ -#define LEX_HAS_YYLEX_DESTROY 1 - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#define LT_OBJDIR ".libs/" - -/* Define to the maximum message length to pass to syslog. */ -#define MAXSYSLOGMSGLEN 10240 - -/* Define if memcmp() does not compare unsigned bytes */ -/* #undef MEMCMP_IS_BROKEN */ - -/* Define if mkdir has one argument. */ -/* #undef MKDIR_HAS_ONE_ARG */ - -/* Define if the network stack does not fully support nonblocking io (causes - lower performance). */ -/* #undef NONBLOCKING_IS_BROKEN */ - -/* Put -D_ALL_SOURCE define in config.h */ -/* #undef OMITTED__D_ALL_SOURCE */ - -/* Put -D_BSD_SOURCE define in config.h */ -/* #undef OMITTED__D_BSD_SOURCE */ - -/* Put -D_DEFAULT_SOURCE define in config.h */ -/* #undef OMITTED__D_DEFAULT_SOURCE */ - -/* Put -D_GNU_SOURCE define in config.h */ -#define OMITTED__D_GNU_SOURCE 1 - -/* Put -D_LARGEFILE_SOURCE=1 define in config.h */ -/* #undef OMITTED__D_LARGEFILE_SOURCE_1 */ - -/* Put -D_POSIX_C_SOURCE=200112 define in config.h */ -/* #undef OMITTED__D_POSIX_C_SOURCE_200112 */ - -/* Put -D_XOPEN_SOURCE=600 define in config.h */ -/* #undef OMITTED__D_XOPEN_SOURCE_600 */ - -/* Put -D_XOPEN_SOURCE_EXTENDED=1 define in config.h */ -/* #undef OMITTED__D_XOPEN_SOURCE_EXTENDED_1 */ - -/* Put -D__EXTENSIONS__ define in config.h */ -/* #undef OMITTED__D__EXTENSIONS__ */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "unbound" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "unbound 1.18.1" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "unbound" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.18.1" - -/* default pidfile location */ -#define PIDFILE "/usr/local/etc/unbound/unbound.pid" - -/* Define to necessary symbol if this constant uses a non-standard name on - your system. */ -/* #undef PTHREAD_CREATE_JOINABLE */ - -/* Return type of signal handlers, but autoconf 2.70 says 'your code may - safely assume C89 semantics that RETSIGTYPE is void.' */ -#define RETSIGTYPE void - -/* if REUSEPORT is enabled by default */ -#define REUSEPORT_DEFAULT 1 - -/* default rootkey location */ -#define ROOT_ANCHOR_FILE "/usr/local/etc/unbound/root.key" - -/* default rootcert location */ -#define ROOT_CERT_FILE "/usr/local/etc/unbound/icannbundle.pem" - -/* version number for resource files */ -#define RSRC_PACKAGE_VERSION 1,18,1,0 - -/* Directory to chdir to */ -#define RUN_DIR "/usr/local/etc/unbound" - -/* Shared data */ -#define SHARE_DIR "/usr/local/etc/unbound" - -/* The size of `pthread_t', as computed by sizeof. */ -//#define SIZEOF_PTHREAD_T 8 - -/* The size of `size_t', as computed by sizeof. */ -//#define SIZEOF_SIZE_T 8 - -/* The size of `time_t', as computed by sizeof. */ -//#define SIZEOF_TIME_T 8 - -/* The size of `unsigned long', as computed by sizeof. */ -//#define SIZEOF_UNSIGNED_LONG 8 - -/* define if (v)snprintf does not return length needed, (but length used) */ -/* #undef SNPRINTF_RET_BROKEN */ - -/* Define to 1 if libsodium supports sodium_set_misuse_handler */ -/* #undef SODIUM_MISUSE_HANDLER */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* use default strptime. */ -#define STRPTIME_WORKS 1 - -/* Use win32 resources and API */ -/* #undef UB_ON_WINDOWS */ - -/* the SYSLOG_FACILITY to use, default LOG_DAEMON */ -#define UB_SYSLOG_FACILITY LOG_DAEMON - -/* default username */ -#define UB_USERNAME "unbound" - -/* use to enable lightweight alloc assertions, for debug use */ -/* #undef UNBOUND_ALLOC_LITE */ - -/* use malloc not regions, for debug use */ -/* #undef UNBOUND_ALLOC_NONREGIONAL */ - -/* use statistics for allocs and frees, for debug use */ -/* #undef UNBOUND_ALLOC_STATS */ - -/* define this to enable debug checks. */ -/* #undef UNBOUND_DEBUG */ - -/* Define to 1 to use cachedb support */ -/* #undef USE_CACHEDB */ - -/* Define to 1 to enable dnscrypt support */ -/* #undef USE_DNSCRYPT */ - -/* Define to 1 to enable dnscrypt with xchacha20 support */ -/* #undef USE_DNSCRYPT_XCHACHA20 */ - -/* Define to 1 to enable dnstap support */ -/* #undef USE_DNSTAP */ - -/* Define this to enable DSA support. */ -/* #undef USE_DSA */ - -/* Define this to enable ECDSA support. */ -#define USE_ECDSA 1 - -/* Define this to enable an EVP workaround for older openssl */ -/* #undef USE_ECDSA_EVP_WORKAROUND */ - -/* Define this to enable ED25519 support. */ -#define USE_ED25519 1 - -/* Define this to enable ED448 support. */ -#define USE_ED448 1 - -/* Define this to enable GOST support. */ -/* #undef USE_GOST */ - -/* Define to 1 to use ipsecmod support. */ -/* #undef USE_IPSECMOD */ - -/* Define to 1 to use ipset support */ -/* #undef USE_IPSET */ - -/* Define if you enable libevent */ -/* #undef USE_LIBEVENT */ - -/* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a - default outgoing port range. This is only for the libunbound on Linux and - does not affect unbound resolving daemon itself. This may severely limit - the number of available outgoing ports and thus decrease randomness. Define - this only when the target system restricts (e.g. some of SELinux enabled - distributions) the use of non-ephemeral ports. */ -/* #undef USE_LINUX_IP_LOCAL_PORT_RANGE */ - -/* Define if you want to use internal select based events */ -#define USE_MINI_EVENT 1 - -/* Define this to enable client TCP Fast Open. */ -/* #undef USE_MSG_FASTOPEN */ - -/* Define this to enable client TCP Fast Open. */ -/* #undef USE_OSX_MSG_FASTOPEN */ - -/* Define this to use hiredis client. */ -/* #undef USE_REDIS */ - -/* Define this to enable SHA1 support. */ -#define USE_SHA1 1 - -/* Define this to enable SHA256 and SHA512 support. */ -#define USE_SHA2 1 - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# define _ALL_SOURCE 1 -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# define _TANDEM_SOURCE 1 -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 -#endif - - -/* Define this to enable server TCP Fast Open. */ -/* #undef USE_TCP_FASTOPEN */ - -/* Whether the windows socket API is used */ -/* #undef USE_WINSOCK */ - -/* the version of the windows API enabled */ -#define WINVER 0x0502 - -/* Define if you want dynlib module. */ -/* #undef WITH_DYNLIBMODULE */ - -/* Define if you want Python module. */ -/* #undef WITH_PYTHONMODULE */ - -/* Define if you want PyUnbound. */ -/* #undef WITH_PYUNBOUND */ - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -/* #undef YYTEXT_POINTER */ - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ -/* #undef _LARGEFILE_SOURCE */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Enable for compile on Minix */ -/* #undef _NETBSD_SOURCE */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* defined to use gcc ansi snprintf and sscanf that understands %lld when - compiled for windows. */ -/* #undef __USE_MINGW_ANSI_STDIO */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `int' if doesn't define. */ -/* #undef gid_t */ - -/* in_addr_t */ -/* #undef in_addr_t */ - -/* in_port_t */ -/* #undef in_port_t */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `short' if does not define. */ -/* #undef int16_t */ - -/* Define to `int' if does not define. */ -/* #undef int32_t */ - -/* Define to `long long' if does not define. */ -/* #undef int64_t */ - -/* Define to `signed char' if does not define. */ -/* #undef int8_t */ - -/* Define if replacement function should be used. */ -/* #undef malloc */ - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `int' if does not define. */ -/* #undef pid_t */ - -/* Define to 'int' if not defined */ -/* #undef rlim_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define to 'int' if not defined */ -/* #undef socklen_t */ - -/* Define to `int' if does not define. */ -/* #undef ssize_t */ - -/* Define to 'unsigned char if not defined */ -/* #undef u_char */ - -/* Define to `int' if doesn't define. */ -/* #undef uid_t */ - -/* Define to `unsigned short' if does not define. */ -/* #undef uint16_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef uint32_t */ - -/* Define to `unsigned long long' if does not define. */ -/* #undef uint64_t */ - -/* Define to `unsigned char' if does not define. */ -/* #undef uint8_t */ - -/* Define as `fork' if `vfork' does not work. */ -/* #undef vfork */ - -#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE) -#define _DEFAULT_SOURCE 1 -#endif - -#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__) -#define __EXTENSIONS__ 1 -#endif - -#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED) -#define _XOPEN_SOURCE_EXTENDED 1 -#endif - -#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE) -#define _ALL_SOURCE 1 -#endif - -#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE) -#define _LARGEFILE_SOURCE 1 -#endif - - - - -#ifndef _OPENBSD_SOURCE -#define _OPENBSD_SOURCE 1 -#endif - -#ifndef UNBOUND_DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -#endif - -/** Use small-ldns codebase */ -#define USE_SLDNS 1 -#ifdef HAVE_SSL -# define LDNS_BUILD_CONFIG_HAVE_SSL 1 -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -#include -#include -#endif - -#ifdef HAVE_STDARG_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - -#include - -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO) -#define ARG_LL "%ll" -#else -#define ARG_LL "%I64" -#endif - -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif - - - -#ifdef HAVE_ATTR_FORMAT -# define ATTR_FORMAT(archetype, string_index, first_to_check) \ - __attribute__ ((format (archetype, string_index, first_to_check))) -#else /* !HAVE_ATTR_FORMAT */ -# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ -#endif /* !HAVE_ATTR_FORMAT */ - - -#if defined(DOXYGEN) -# define ATTR_UNUSED(x) x -#elif defined(__cplusplus) -# define ATTR_UNUSED(x) -#elif defined(HAVE_ATTR_UNUSED) -# define ATTR_UNUSED(x) x __attribute__((unused)) -#else /* !HAVE_ATTR_UNUSED */ -# define ATTR_UNUSED(x) x -#endif /* !HAVE_ATTR_UNUSED */ - - -#ifndef HAVE_FSEEKO -#define fseeko fseek -#define ftello ftell -#endif /* HAVE_FSEEKO */ - - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 256 -#endif - -#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) -#define snprintf snprintf_unbound -#define vsnprintf vsnprintf_unbound -#include -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#endif /* HAVE_SNPRINTF or SNPRINTF_RET_BROKEN */ - -#ifndef HAVE_INET_PTON -#define inet_pton inet_pton_unbound -int inet_pton(int af, const char* src, void* dst); -#endif /* HAVE_INET_PTON */ - - -#ifndef HAVE_INET_NTOP -#define inet_ntop inet_ntop_unbound -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - - -#ifndef HAVE_INET_ATON -#define inet_aton inet_aton_unbound -int inet_aton(const char *cp, struct in_addr *addr); -#endif - - -#ifndef HAVE_MEMMOVE -#define memmove memmove_unbound -void *memmove(void *dest, const void *src, size_t n); -#endif - - -#ifndef HAVE_STRLCAT -#define strlcat strlcat_unbound -size_t strlcat(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_STRLCPY -#define strlcpy strlcpy_unbound -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_GMTIME_R -#define gmtime_r gmtime_r_unbound -struct tm *gmtime_r(const time_t *timep, struct tm *result); -#endif - - -#ifndef HAVE_REALLOCARRAY -#define reallocarray reallocarrayunbound -void* reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - - -#if !defined(HAVE_SLEEP) || defined(HAVE_WINDOWS_H) -#define sleep(x) Sleep((x)*1000) /* on win32 */ -#endif /* HAVE_SLEEP */ - - -#ifndef HAVE_USLEEP -#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ -#endif /* HAVE_USLEEP */ - - -#ifndef HAVE_RANDOM -#define random rand /* on win32, for tests only (bad random) */ -#endif /* HAVE_RANDOM */ - - -#ifndef HAVE_SRANDOM -#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ -#endif /* HAVE_SRANDOM */ - - -/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ -#ifdef HAVE_WINSOCK2_H -#define FD_SET_T (u_int) -#else -#define FD_SET_T -#endif - - -#ifndef IPV6_MIN_MTU -#define IPV6_MIN_MTU 1280 -#endif /* IPV6_MIN_MTU */ - - -#ifdef MEMCMP_IS_BROKEN -#include "compat/memcmp.h" -#define memcmp memcmp_unbound -int memcmp(const void *x, const void *y, size_t n); -#endif - - - -#ifndef HAVE_CTIME_R -#define ctime_r unbound_ctime_r -char *ctime_r(const time_t *timep, char *buf); -#endif - -#ifndef HAVE_STRSEP -#define strsep unbound_strsep -char *strsep(char **stringp, const char *delim); -#endif - -#ifndef HAVE_ISBLANK -#define isblank unbound_isblank -int isblank(int c); -#endif - -#ifndef HAVE_EXPLICIT_BZERO -#define explicit_bzero unbound_explicit_bzero -void explicit_bzero(void* buf, size_t len); -#endif - -#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - -#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON -int inet_pton(int af, const char* src, void* dst); -#endif - -#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) -#define strptime unbound_strptime -struct tm; -char *strptime(const char *s, const char *format, struct tm *tm); -#endif - -#if !HAVE_DECL_REALLOCARRAY -void *reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - -#ifdef HAVE_LIBBSD -#include -#include -#endif - -#ifdef HAVE_LIBRESSL -# if !HAVE_DECL_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_ARC4RANDOM && defined(HAVE_ARC4RANDOM) -uint32_t arc4random(void); -# endif -# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM) -uint32_t arc4random_uniform(uint32_t upper_bound); -# endif -#endif /* HAVE_LIBRESSL */ -#ifndef HAVE_ARC4RANDOM -int getentropy(void* buf, size_t len); -uint32_t arc4random(void); -void arc4random_buf(void* buf, size_t n); -void _ARC4_LOCK(void); -void _ARC4_UNLOCK(void); -void _ARC4_LOCK_DESTROY(void); -#endif -#ifndef HAVE_ARC4RANDOM_UNIFORM -uint32_t arc4random_uniform(uint32_t upper_bound); -#endif -#ifdef COMPAT_SHA512 -#ifndef SHA512_DIGEST_LENGTH -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA512_CTX; -#endif /* SHA512_DIGEST_LENGTH */ -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, void*, size_t); -void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); -#endif /* COMPAT_SHA512 */ - - - -#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) - /* using version of libevent that is not threadsafe. */ -# define LIBEVENT_SIGNAL_PROBLEM 1 -#endif - -#ifndef CHECKED_INET6 -# define CHECKED_INET6 -# ifdef AF_INET6 -# define INET6 -# else -# define AF_INET6 28 -# endif -#endif /* CHECKED_INET6 */ - -#ifndef HAVE_GETADDRINFO -struct sockaddr_storage; -#include "compat/fake-rfc2553.h" -#endif - -#ifdef UNBOUND_ALLOC_STATS -# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) -# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) -# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) -# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) -void *unbound_stat_malloc(size_t size); -void *unbound_stat_calloc(size_t nmemb, size_t size); -void unbound_stat_free(void *ptr); -void *unbound_stat_realloc(void *ptr, size_t size); -void *unbound_stat_malloc_log(size_t size, const char* file, int line, - const char* func); -void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, - int line, const char* func); -void unbound_stat_free_log(void *ptr, const char* file, int line, - const char* func); -void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, - int line, const char* func); -#elif defined(UNBOUND_ALLOC_LITE) -# include "util/alloc.h" -#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ - -/** default port for DNS traffic. */ -#define UNBOUND_DNS_PORT 53 -/** default port for DNS over TLS traffic. */ -#define UNBOUND_DNS_OVER_TLS_PORT 853 -/** default port for DNS over HTTPS traffic. */ -#define UNBOUND_DNS_OVER_HTTPS_PORT 443 -/** default port for unbound control traffic, registered port with IANA, - ub-dns-control 8953/tcp unbound dns nameserver control */ -#define UNBOUND_CONTROL_PORT 8953 -/** the version of unbound-control that this software implements */ -#define UNBOUND_CONTROL_VERSION 1 diff --git a/crates/libunbound-sys/import-unbound.sh b/crates/libunbound-sys/import-unbound.sh deleted file mode 100755 index f5f488d2..00000000 --- a/crates/libunbound-sys/import-unbound.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# Sync the vendored sources from a URL -# eg: -# wget 'https://nlnetlabs.nl/downloads/unbound/unbound-1.18.0.tar.gz' -# import-unbound.sh path/to/unbound-1.18.0.tar.gz -set -x -TARBALL=$1 - -rm -rf unbound -tar xf $TARBALL -mv unbound-* unbound -rm -rf unbound/{testdata,pythonmod,testcode,winrc,contrib,configure,aclocal.m4,ltmain.sh,install-sh,config.guess,smallapp,doc,.git*,*.m4} - -echo > unbound/dnscrypt/dnscrypt_config.h -echo > unbound/dnstap/dnstap_config.h diff --git a/crates/libunbound-sys/regenerate.sh b/crates/libunbound-sys/regenerate.sh deleted file mode 100755 index c1776f93..00000000 --- a/crates/libunbound-sys/regenerate.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -bindgen unbound/libunbound/unbound.h -o src/lib.rs \ - --no-layout-tests \ - --raw-line "#![allow(non_snake_case)]" \ - --raw-line "#![allow(non_camel_case_types)]" \ - --raw-line "#![allow(non_upper_case_globals)]" \ - --raw-line "#![allow(clippy::unreadable_literal)]" \ - --raw-line "#![allow(clippy::upper_case_acronyms)]" \ - --raw-line "#![allow(rustdoc::broken_intra_doc_links)]" \ - --generate=functions,types,vars \ diff --git a/crates/libunbound-sys/src/lib.rs b/crates/libunbound-sys/src/lib.rs deleted file mode 100644 index 22cb50ec..00000000 --- a/crates/libunbound-sys/src/lib.rs +++ /dev/null @@ -1,486 +0,0 @@ -/* automatically generated by rust-bindgen 0.66.1 */ - -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] -#![allow(clippy::unreadable_literal)] -#![allow(clippy::upper_case_acronyms)] -#![allow(rustdoc::broken_intra_doc_links)] - -pub const UB_STATS_QTYPE_NUM: u32 = 256; -pub const UB_STATS_QCLASS_NUM: u32 = 256; -pub const UB_STATS_RCODE_NUM: u32 = 16; -pub const UB_STATS_OPCODE_NUM: u32 = 16; -pub const UB_STATS_BUCKET_NUM: u32 = 40; -pub const UB_STATS_RPZ_ACTION_NUM: u32 = 10; -#[doc = " The validation context is created to hold the resolver status,\n validation keys and a small cache (containing messages, rrsets,\n roundtrip times, trusted keys, lameness information).\n\n Its contents are internally defined."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_ctx { - _unused: [u8; 0], -} -#[doc = " The validation and resolution results.\n Allocated by the resolver, and need to be freed by the application\n with ub_resolve_free()."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_result { - #[doc = " The original question, name text string."] - pub qname: *mut ::std::os::raw::c_char, - #[doc = " the type asked for"] - pub qtype: ::std::os::raw::c_int, - #[doc = " the class asked for"] - pub qclass: ::std::os::raw::c_int, - #[doc = " a list of network order DNS rdata items, terminated with a\n NULL pointer, so that data[0] is the first result entry,\n data[1] the second, and the last entry is NULL.\n If there was no data, data[0] is NULL."] - pub data: *mut *mut ::std::os::raw::c_char, - #[doc = " the length in bytes of the data items, len[i] for data[i]"] - pub len: *mut ::std::os::raw::c_int, - #[doc = " canonical name for the result (the final cname).\n zero terminated string.\n May be NULL if no canonical name exists."] - pub canonname: *mut ::std::os::raw::c_char, - #[doc = " DNS RCODE for the result. May contain additional error code if\n there was no data due to an error. 0 (NOERROR) if okay."] - pub rcode: ::std::os::raw::c_int, - #[doc = " The DNS answer packet. Network formatted. Can contain DNSSEC types."] - pub answer_packet: *mut ::std::os::raw::c_void, - #[doc = " length of the answer packet in octets."] - pub answer_len: ::std::os::raw::c_int, - #[doc = " If there is any data, this is true.\n If false, there was no data (nxdomain may be true, rcode can be set)."] - pub havedata: ::std::os::raw::c_int, - #[doc = " If there was no data, and the domain did not exist, this is true.\n If it is false, and there was no data, then the domain name\n is purported to exist, but the requested data type is not available."] - pub nxdomain: ::std::os::raw::c_int, - #[doc = " True, if the result is validated securely.\n False, if validation failed or domain queried has no security info.\n\n It is possible to get a result with no data (havedata is false),\n and secure is true. This means that the non-existence of the data\n was cryptographically proven (with signatures)."] - pub secure: ::std::os::raw::c_int, - #[doc = " If the result was not secure (secure==0), and this result is due\n to a security failure, bogus is true.\n This means the data has been actively tampered with, signatures\n failed, expected signatures were not present, timestamps on\n signatures were out of date and so on.\n\n If !secure and !bogus, this can happen if the data is not secure\n because security is disabled for that domain name.\n This means the data is from a domain where data is not signed."] - pub bogus: ::std::os::raw::c_int, - #[doc = " If the result is bogus this contains a string (zero terminated)\n that describes the failure. There may be other errors as well\n as the one described, the description may not be perfectly accurate.\n Is NULL if the result is not bogus."] - pub why_bogus: *mut ::std::os::raw::c_char, - #[doc = " If the query or one of its subqueries was ratelimited. Useful if\n ratelimiting is enabled and answer to the client is SERVFAIL as a\n result."] - pub was_ratelimited: ::std::os::raw::c_int, - #[doc = " TTL for the result, in seconds. If the security is bogus, then\n you also cannot trust this value."] - pub ttl: ::std::os::raw::c_int, -} -#[doc = " Callback for results of async queries.\n The readable function definition looks like:\n void my_callback(void* my_arg, int err, struct ub_result* result);\n It is called with\n\tvoid* my_arg: your pointer to a (struct of) data of your choice,\n\t\tor NULL.\n\tint err: if 0 all is OK, otherwise an error occurred and no results\n\t are forthcoming.\n\tstruct result: pointer to more detailed result structure.\n\t\tThis structure is allocated on the heap and needs to be\n\t\tfreed with ub_resolve_free(result);"] -pub type ub_callback_type = ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut ::std::os::raw::c_void, - arg2: ::std::os::raw::c_int, - arg3: *mut ub_result, - ), ->; -#[doc = " no error"] -pub const ub_ctx_err_UB_NOERROR: ub_ctx_err = 0; -#[doc = " socket operation. Set to -1, so that if an error from _fd() is\n passed (-1) it gives a socket error."] -pub const ub_ctx_err_UB_SOCKET: ub_ctx_err = -1; -#[doc = " alloc failure"] -pub const ub_ctx_err_UB_NOMEM: ub_ctx_err = -2; -#[doc = " syntax error"] -pub const ub_ctx_err_UB_SYNTAX: ub_ctx_err = -3; -#[doc = " DNS service failed"] -pub const ub_ctx_err_UB_SERVFAIL: ub_ctx_err = -4; -#[doc = " fork() failed"] -pub const ub_ctx_err_UB_FORKFAIL: ub_ctx_err = -5; -#[doc = " cfg change after finalize()"] -pub const ub_ctx_err_UB_AFTERFINAL: ub_ctx_err = -6; -#[doc = " initialization failed (bad settings)"] -pub const ub_ctx_err_UB_INITFAIL: ub_ctx_err = -7; -#[doc = " error in pipe communication with async bg worker"] -pub const ub_ctx_err_UB_PIPE: ub_ctx_err = -8; -#[doc = " error reading from file (resolv.conf)"] -pub const ub_ctx_err_UB_READFILE: ub_ctx_err = -9; -#[doc = " error async_id does not exist or result already been delivered"] -pub const ub_ctx_err_UB_NOID: ub_ctx_err = -10; -#[doc = " The error constants"] -pub type ub_ctx_err = ::std::os::raw::c_int; -extern "C" { - #[doc = " Create a resolving and validation context.\n The information from /etc/resolv.conf and /etc/hosts is not utilised by\n default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.\n @return a new context. default initialisation.\n \treturns NULL on error."] - pub fn ub_ctx_create() -> *mut ub_ctx; -} -extern "C" { - #[doc = " Destroy a validation context and free all its resources.\n Outstanding async queries are killed and callbacks are not called for them.\n @param ctx: context to delete."] - pub fn ub_ctx_delete(ctx: *mut ub_ctx); -} -extern "C" { - #[doc = " Set an option for the context.\n @param ctx: context.\n @param opt: option name from the unbound.conf config file format.\n\t(not all settings applicable). The name includes the trailing ':'\n\tfor example ub_ctx_set_option(ctx, \"logfile:\", \"mylog.txt\");\n \tThis is a power-users interface that lets you specify all sorts\n \tof options.\n \tFor some specific options, such as adding trust anchors, special\n \troutines exist.\n @param val: value of the option.\n @return: 0 if OK, else error."] - pub fn ub_ctx_set_option( - ctx: *mut ub_ctx, - opt: *const ::std::os::raw::c_char, - val: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Get an option from the context.\n @param ctx: context.\n @param opt: option name from the unbound.conf config file format.\n\t(not all settings applicable). The name excludes the trailing ':'\n\tfor example ub_ctx_get_option(ctx, \"logfile\", &result);\n \tThis is a power-users interface that lets you specify all sorts\n \tof options.\n @param str: the string is malloced and returned here. NULL on error.\n \tThe caller must free() the string. In cases with multiple\n \tentries (auto-trust-anchor-file), a newline delimited list is\n \treturned in the string.\n @return 0 if OK else an error code (malloc failure, syntax error)."] - pub fn ub_ctx_get_option( - ctx: *mut ub_ctx, - opt: *const ::std::os::raw::c_char, - str_: *mut *mut ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " setup configuration for the given context.\n @param ctx: context.\n @param fname: unbound config file (not all settings applicable).\n \tThis is a power-users interface that lets you specify all sorts\n \tof options.\n \tFor some specific options, such as adding trust anchors, special\n \troutines exist.\n @return: 0 if OK, else error."] - pub fn ub_ctx_config( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Set machine to forward DNS queries to, the caching resolver to use.\n IP4 or IP6 address. Forwards all DNS requests to that machine, which\n is expected to run a recursive resolver. If the proxy is not\n DNSSEC-capable, validation may fail. Can be called several times, in\n that case the addresses are used as backup servers.\n\n To read the list of nameservers from /etc/resolv.conf (from DHCP or so),\n use the call ub_ctx_resolvconf.\n\n @param ctx: context.\n\tAt this time it is only possible to set configuration before the\n\tfirst resolve is done.\n @param addr: address, IP4 or IP6 in string format.\n \tIf the addr is NULL, forwarding is disabled.\n @return 0 if OK, else error."] - pub fn ub_ctx_set_fwd( - ctx: *mut ub_ctx, - addr: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Use DNS over TLS to send queries to machines set with ub_ctx_set_fwd().\n\n @param ctx: context.\n\tAt this time it is only possible to set configuration before the\n\tfirst resolve is done.\n @param tls: enable or disable DNS over TLS\n @return 0 if OK, else error."] - pub fn ub_ctx_set_tls(ctx: *mut ub_ctx, tls: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add a stub zone, with given address to send to. This is for custom\n root hints or pointing to a local authoritative dns server.\n For dns resolvers and the 'DHCP DNS' ip address, use ub_ctx_set_fwd.\n This is similar to a stub-zone entry in unbound.conf.\n\n @param ctx: context.\n\tIt is only possible to set configuration before the\n\tfirst resolve is done.\n @param zone: name of the zone, string.\n @param addr: address, IP4 or IP6 in string format.\n \tThe addr is added to the list of stub-addresses if the entry exists.\n \tIf the addr is NULL the stub entry is removed.\n @param isprime: set to true to set stub-prime to yes for the stub.\n \tFor local authoritative servers, people usually set it to false,\n \tFor root hints it should be set to true.\n @return 0 if OK, else error."] - pub fn ub_ctx_set_stub( - ctx: *mut ub_ctx, - zone: *const ::std::os::raw::c_char, - addr: *const ::std::os::raw::c_char, - isprime: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Read list of nameservers to use from the filename given.\n Usually \"/etc/resolv.conf\". Uses those nameservers as caching proxies.\n If they do not support DNSSEC, validation may fail.\n\n Only nameservers are picked up, the searchdomain, ndots and other\n settings from resolv.conf(5) are ignored.\n\n @param ctx: context.\n\tAt this time it is only possible to set configuration before the\n\tfirst resolve is done.\n @param fname: file name string. If NULL \"/etc/resolv.conf\" is used.\n @return 0 if OK, else error."] - pub fn ub_ctx_resolvconf( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Read list of hosts from the filename given.\n Usually \"/etc/hosts\".\n These addresses are not flagged as DNSSEC secure when queried for.\n\n @param ctx: context.\n\tAt this time it is only possible to set configuration before the\n\tfirst resolve is done.\n @param fname: file name string. If NULL \"/etc/hosts\" is used.\n @return 0 if OK, else error."] - pub fn ub_ctx_hosts( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add a trust anchor to the given context.\n The trust anchor is a string, on one line, that holds a valid DNSKEY or\n DS RR.\n @param ctx: context.\n\tAt this time it is only possible to add trusted keys before the\n\tfirst resolve is done.\n @param ta: string, with zone-format RR on one line.\n \t[domainname] [TTL optional] [type] [class optional] [rdata contents]\n @return 0 if OK, else error."] - pub fn ub_ctx_add_ta( - ctx: *mut ub_ctx, - ta: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add trust anchors to the given context.\n Pass name of a file with DS and DNSKEY records (like from dig or drill).\n @param ctx: context.\n\tAt this time it is only possible to add trusted keys before the\n\tfirst resolve is done.\n @param fname: filename of file with keyfile with trust anchors.\n @return 0 if OK, else error."] - pub fn ub_ctx_add_ta_file( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add trust anchor to the given context that is tracked with RFC5011\n automated trust anchor maintenance. The file is written to when the\n trust anchor is changed.\n Pass the name of a file that was output from eg. unbound-anchor,\n or you can start it by providing a trusted DNSKEY or DS record on one\n line in the file.\n @param ctx: context.\n\tAt this time it is only possible to add trusted keys before the\n\tfirst resolve is done.\n @param fname: filename of file with trust anchor.\n @return 0 if OK, else error."] - pub fn ub_ctx_add_ta_autr( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add trust anchors to the given context.\n Pass the name of a bind-style config file with trusted-keys{}.\n @param ctx: context.\n\tAt this time it is only possible to add trusted keys before the\n\tfirst resolve is done.\n @param fname: filename of file with bind-style config entries with trust\n \tanchors.\n @return 0 if OK, else error."] - pub fn ub_ctx_trustedkeys( - ctx: *mut ub_ctx, - fname: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Set debug output (and error output) to the specified stream.\n Pass NULL to disable. Default is stderr.\n @param ctx: context.\n @param out: FILE* out file stream to log to.\n \tType void* to avoid stdio dependency of this header file.\n @return 0 if OK, else error."] - pub fn ub_ctx_debugout( - ctx: *mut ub_ctx, - out: *mut ::std::os::raw::c_void, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Set debug verbosity for the context\n Output is directed to stderr.\n @param ctx: context.\n @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,\n\tand 3 is lots.\n @return 0 if OK, else error."] - pub fn ub_ctx_debuglevel(ctx: *mut ub_ctx, d: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Set a context behaviour for asynchronous action.\n @param ctx: context.\n @param dothread: if true, enables threading and a call to resolve_async()\n\tcreates a thread to handle work in the background.\n\tIf false, a process is forked to handle work in the background.\n\tChanges to this setting after async() calls have been made have\n\tno effect (delete and re-create the context to change).\n @return 0 if OK, else error."] - pub fn ub_ctx_async(ctx: *mut ub_ctx, dothread: ::std::os::raw::c_int) - -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Poll a context to see if it has any new results\n Do not poll in a loop, instead extract the fd below to poll for readiness,\n and then check, or wait using the wait routine.\n @param ctx: context.\n @return: 0 if nothing to read, or nonzero if a result is available.\n \tIf nonzero, call ctx_process() to do callbacks."] - pub fn ub_poll(ctx: *mut ub_ctx) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Wait for a context to finish with results. Calls ub_process() after\n the wait for you. After the wait, there are no more outstanding\n asynchronous queries.\n @param ctx: context.\n @return: 0 if OK, else error."] - pub fn ub_wait(ctx: *mut ub_ctx) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Get file descriptor. Wait for it to become readable, at this point\n answers are returned from the asynchronous validating resolver.\n Then call the ub_process to continue processing.\n This routine works immediately after context creation, the fd\n does not change.\n @param ctx: context.\n @return: -1 on error, or file descriptor to use select(2) with."] - pub fn ub_fd(ctx: *mut ub_ctx) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Call this routine to continue processing results from the validating\n resolver (when the fd becomes readable).\n Will perform necessary callbacks.\n @param ctx: context\n @return: 0 if OK, else error."] - pub fn ub_process(ctx: *mut ub_ctx) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Perform resolution and validation of the target name.\n @param ctx: context.\n\tThe context is finalized, and can no longer accept config changes.\n @param name: domain name in text format (a zero terminated text string).\n @param rrtype: type of RR in host order, 1 is A (address).\n @param rrclass: class of RR in host order, 1 is IN (for internet).\n @param result: the result data is returned in a newly allocated result\n \tstructure. May be NULL on return, return value is set to an error\n \tin that case (out of memory).\n @return 0 if OK, else error."] - pub fn ub_resolve( - ctx: *mut ub_ctx, - name: *const ::std::os::raw::c_char, - rrtype: ::std::os::raw::c_int, - rrclass: ::std::os::raw::c_int, - result: *mut *mut ub_result, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Perform resolution and validation of the target name.\n Asynchronous, after a while, the callback will be called with your\n data and the result.\n @param ctx: context.\n\tIf no thread or process has been created yet to perform the\n\twork in the background, it is created now.\n\tThe context is finalized, and can no longer accept config changes.\n @param name: domain name in text format (a string).\n @param rrtype: type of RR in host order, 1 is A.\n @param rrclass: class of RR in host order, 1 is IN (for internet).\n @param mydata: this data is your own data (you can pass NULL),\n \tand is passed on to the callback function.\n @param callback: this is called on completion of the resolution.\n \tIt is called as:\n \tvoid callback(void* mydata, int err, struct ub_result* result)\n \twith mydata: the same as passed here, you may pass NULL,\n \twith err: is 0 when a result has been found.\n \twith result: a newly allocated result structure.\n\t\tThe result may be NULL, in that case err is set.\n\n \tIf an error happens during processing, your callback will be called\n \twith error set to a nonzero value (and result==NULL).\n @param async_id: if you pass a non-NULL value, an identifier number is\n\treturned for the query as it is in progress. It can be used to\n\tcancel the query.\n @return 0 if OK, else error."] - pub fn ub_resolve_async( - ctx: *mut ub_ctx, - name: *const ::std::os::raw::c_char, - rrtype: ::std::os::raw::c_int, - rrclass: ::std::os::raw::c_int, - mydata: *mut ::std::os::raw::c_void, - callback: ub_callback_type, - async_id: *mut ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Cancel an async query in progress.\n Its callback will not be called.\n\n @param ctx: context.\n @param async_id: which query to cancel.\n @return 0 if OK, else error.\n This routine can return an error if the async_id passed does not exist\n or has already been delivered. If another thread is processing results\n at the same time, the result may be delivered at the same time and the\n cancel fails with an error. Also the cancel can fail due to a system\n error, no memory or socket failures."] - pub fn ub_cancel(ctx: *mut ub_ctx, async_id: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Free storage associated with a result structure.\n @param result: to free"] - pub fn ub_resolve_free(result: *mut ub_result); -} -extern "C" { - #[doc = " Convert error value to a human readable string.\n @param err: error code from one of the libunbound functions.\n \tThe error codes are from the type enum ub_ctx_err.\n @return pointer to constant text string, zero terminated."] - pub fn ub_strerror(err: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char; -} -extern "C" { - #[doc = " Debug routine. Print the local zone information to debug output.\n @param ctx: context. Is finalized by the routine.\n @return 0 if OK, else error."] - pub fn ub_ctx_print_local_zones(ctx: *mut ub_ctx) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add a new zone with the zonetype to the local authority info of the\n library.\n @param ctx: context. Is finalized by the routine.\n @param zone_name: name of the zone in text, \"example.com\"\n\tIf it already exists, the type is updated.\n @param zone_type: type of the zone (like for unbound.conf) in text.\n @return 0 if OK, else error."] - pub fn ub_ctx_zone_add( - ctx: *mut ub_ctx, - zone_name: *const ::std::os::raw::c_char, - zone_type: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Remove zone from local authority info of the library.\n @param ctx: context. Is finalized by the routine.\n @param zone_name: name of the zone in text, \"example.com\"\n\tIf it does not exist, nothing happens.\n @return 0 if OK, else error."] - pub fn ub_ctx_zone_remove( - ctx: *mut ub_ctx, - zone_name: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Add localdata to the library local authority info.\n Similar to local-data config statement.\n @param ctx: context. Is finalized by the routine.\n @param data: the resource record in text format, for example\n\t\"www.example.com IN A 127.0.0.1\"\n @return 0 if OK, else error."] - pub fn ub_ctx_data_add( - ctx: *mut ub_ctx, - data: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Remove localdata from the library local authority info.\n @param ctx: context. Is finalized by the routine.\n @param data: the name to delete all data from, like \"www.example.com\".\n @return 0 if OK, else error."] - pub fn ub_ctx_data_remove( - ctx: *mut ub_ctx, - data: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[doc = " Get a version string from the libunbound implementation.\n @return a static constant string with the version number."] - pub fn ub_version() -> *const ::std::os::raw::c_char; -} -#[doc = " Some global statistics that are not in struct stats_info,\n this struct is shared on a shm segment (shm-key in unbound.conf)"] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_shm_stat_info { - pub num_threads: ::std::os::raw::c_int, - pub time: ub_shm_stat_info__bindgen_ty_1, - pub mem: ub_shm_stat_info__bindgen_ty_2, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_shm_stat_info__bindgen_ty_1 { - pub now_sec: ::std::os::raw::c_longlong, - pub now_usec: ::std::os::raw::c_longlong, - pub up_sec: ::std::os::raw::c_longlong, - pub up_usec: ::std::os::raw::c_longlong, - pub elapsed_sec: ::std::os::raw::c_longlong, - pub elapsed_usec: ::std::os::raw::c_longlong, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_shm_stat_info__bindgen_ty_2 { - pub msg: ::std::os::raw::c_longlong, - pub rrset: ::std::os::raw::c_longlong, - pub val: ::std::os::raw::c_longlong, - pub iter: ::std::os::raw::c_longlong, - pub subnet: ::std::os::raw::c_longlong, - pub ipsecmod: ::std::os::raw::c_longlong, - pub respip: ::std::os::raw::c_longlong, - pub dnscrypt_shared_secret: ::std::os::raw::c_longlong, - pub dnscrypt_nonce: ::std::os::raw::c_longlong, - pub dynlib: ::std::os::raw::c_longlong, -} -#[doc = " per worker statistics."] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_server_stats { - #[doc = " number of queries from clients received."] - pub num_queries: ::std::os::raw::c_longlong, - #[doc = " number of queries that have been dropped/ratelimited by ip."] - pub num_queries_ip_ratelimited: ::std::os::raw::c_longlong, - #[doc = " number of queries with a valid DNS Cookie."] - pub num_queries_cookie_valid: ::std::os::raw::c_longlong, - #[doc = " number of queries with only the client part of the DNS Cookie."] - pub num_queries_cookie_client: ::std::os::raw::c_longlong, - #[doc = " number of queries with invalid DNS Cookie."] - pub num_queries_cookie_invalid: ::std::os::raw::c_longlong, - #[doc = " number of queries that had a cache-miss."] - pub num_queries_missed_cache: ::std::os::raw::c_longlong, - #[doc = " number of prefetch queries - cachehits with prefetch"] - pub num_queries_prefetch: ::std::os::raw::c_longlong, - #[doc = " number of queries which are too late to process"] - pub num_queries_timed_out: ::std::os::raw::c_longlong, - #[doc = " the longest wait time in the queue"] - pub max_query_time_us: ::std::os::raw::c_longlong, - #[doc = " Sum of the querylistsize of the worker for\n every query that missed cache. To calculate average."] - pub sum_query_list_size: ::std::os::raw::c_longlong, - #[doc = " max value of query list size reached."] - pub max_query_list_size: ::std::os::raw::c_longlong, - #[doc = " Extended stats below (bool)"] - pub extended: ::std::os::raw::c_int, - #[doc = " qtype stats"] - pub qtype: [::std::os::raw::c_longlong; 256usize], - #[doc = " bigger qtype values not in array"] - pub qtype_big: ::std::os::raw::c_longlong, - #[doc = " qclass stats"] - pub qclass: [::std::os::raw::c_longlong; 256usize], - #[doc = " bigger qclass values not in array"] - pub qclass_big: ::std::os::raw::c_longlong, - #[doc = " query opcodes"] - pub qopcode: [::std::os::raw::c_longlong; 16usize], - #[doc = " number of queries over TCP"] - pub qtcp: ::std::os::raw::c_longlong, - #[doc = " number of outgoing queries over TCP"] - pub qtcp_outgoing: ::std::os::raw::c_longlong, - #[doc = " number of outgoing queries over UDP"] - pub qudp_outgoing: ::std::os::raw::c_longlong, - #[doc = " number of queries over (DNS over) TLS"] - pub qtls: ::std::os::raw::c_longlong, - #[doc = " number of queries over (DNS over) HTTPS"] - pub qhttps: ::std::os::raw::c_longlong, - #[doc = " number of queries over IPv6"] - pub qipv6: ::std::os::raw::c_longlong, - #[doc = " number of queries with QR bit"] - pub qbit_QR: ::std::os::raw::c_longlong, - #[doc = " number of queries with AA bit"] - pub qbit_AA: ::std::os::raw::c_longlong, - #[doc = " number of queries with TC bit"] - pub qbit_TC: ::std::os::raw::c_longlong, - #[doc = " number of queries with RD bit"] - pub qbit_RD: ::std::os::raw::c_longlong, - #[doc = " number of queries with RA bit"] - pub qbit_RA: ::std::os::raw::c_longlong, - #[doc = " number of queries with Z bit"] - pub qbit_Z: ::std::os::raw::c_longlong, - #[doc = " number of queries with AD bit"] - pub qbit_AD: ::std::os::raw::c_longlong, - #[doc = " number of queries with CD bit"] - pub qbit_CD: ::std::os::raw::c_longlong, - #[doc = " number of queries with EDNS OPT record"] - pub qEDNS: ::std::os::raw::c_longlong, - #[doc = " number of queries with EDNS with DO flag"] - pub qEDNS_DO: ::std::os::raw::c_longlong, - #[doc = " answer rcodes"] - pub ans_rcode: [::std::os::raw::c_longlong; 16usize], - #[doc = " answers with pseudo rcode 'nodata'"] - pub ans_rcode_nodata: ::std::os::raw::c_longlong, - #[doc = " answers that were secure (AD)"] - pub ans_secure: ::std::os::raw::c_longlong, - #[doc = " answers that were bogus (withheld as SERVFAIL)"] - pub ans_bogus: ::std::os::raw::c_longlong, - #[doc = " rrsets marked bogus by validator"] - pub rrset_bogus: ::std::os::raw::c_longlong, - #[doc = " number of queries that have been ratelimited by domain recursion."] - pub queries_ratelimited: ::std::os::raw::c_longlong, - #[doc = " unwanted traffic received on server-facing ports"] - pub unwanted_replies: ::std::os::raw::c_longlong, - #[doc = " unwanted traffic received on client-facing ports"] - pub unwanted_queries: ::std::os::raw::c_longlong, - #[doc = " usage of tcp accept list"] - pub tcp_accept_usage: ::std::os::raw::c_longlong, - #[doc = " expired answers served from cache"] - pub ans_expired: ::std::os::raw::c_longlong, - #[doc = " histogram data exported to array\n if the array is the same size, no data is lost, and\n if all histograms are same size (is so by default) then\n adding up works well."] - pub hist: [::std::os::raw::c_longlong; 40usize], - #[doc = " number of message cache entries"] - pub msg_cache_count: ::std::os::raw::c_longlong, - #[doc = " number of rrset cache entries"] - pub rrset_cache_count: ::std::os::raw::c_longlong, - #[doc = " number of infra cache entries"] - pub infra_cache_count: ::std::os::raw::c_longlong, - #[doc = " number of key cache entries"] - pub key_cache_count: ::std::os::raw::c_longlong, - #[doc = " maximum number of collisions in the msg cache"] - pub msg_cache_max_collisions: ::std::os::raw::c_longlong, - #[doc = " maximum number of collisions in the rrset cache"] - pub rrset_cache_max_collisions: ::std::os::raw::c_longlong, - #[doc = " number of queries that used dnscrypt"] - pub num_query_dnscrypt_crypted: ::std::os::raw::c_longlong, - #[doc = " number of queries that queried dnscrypt certificates"] - pub num_query_dnscrypt_cert: ::std::os::raw::c_longlong, - #[doc = " number of queries in clear text and not asking for the certificates"] - pub num_query_dnscrypt_cleartext: ::std::os::raw::c_longlong, - #[doc = " number of malformed encrypted queries"] - pub num_query_dnscrypt_crypted_malformed: ::std::os::raw::c_longlong, - #[doc = " number of queries which did not have a shared secret in cache"] - pub num_query_dnscrypt_secret_missed_cache: ::std::os::raw::c_longlong, - #[doc = " number of dnscrypt shared secret cache entries"] - pub shared_secret_cache_count: ::std::os::raw::c_longlong, - #[doc = " number of queries which are replays"] - pub num_query_dnscrypt_replay: ::std::os::raw::c_longlong, - #[doc = " number of dnscrypt nonces cache entries"] - pub nonce_cache_count: ::std::os::raw::c_longlong, - #[doc = " number of queries for unbound's auth_zones, upstream query"] - pub num_query_authzone_up: ::std::os::raw::c_longlong, - #[doc = " number of queries for unbound's auth_zones, downstream answers"] - pub num_query_authzone_down: ::std::os::raw::c_longlong, - #[doc = " number of times neg cache records were used to generate NOERROR\n responses."] - pub num_neg_cache_noerror: ::std::os::raw::c_longlong, - #[doc = " number of times neg cache records were used to generate NXDOMAIN\n responses."] - pub num_neg_cache_nxdomain: ::std::os::raw::c_longlong, - #[doc = " number of queries answered from edns-subnet specific data"] - pub num_query_subnet: ::std::os::raw::c_longlong, - #[doc = " number of queries answered from edns-subnet specific data, and\n the answer was from the edns-subnet cache."] - pub num_query_subnet_cache: ::std::os::raw::c_longlong, - #[doc = " number of queries served from cachedb"] - pub num_query_cachedb: ::std::os::raw::c_longlong, - #[doc = " number of bytes in the stream wait buffers"] - pub mem_stream_wait: ::std::os::raw::c_longlong, - #[doc = " number of bytes in the HTTP2 query buffers"] - pub mem_http2_query_buffer: ::std::os::raw::c_longlong, - #[doc = " number of bytes in the HTTP2 response buffers"] - pub mem_http2_response_buffer: ::std::os::raw::c_longlong, - #[doc = " number of TLS connection resume"] - pub qtls_resume: ::std::os::raw::c_longlong, - #[doc = " RPZ action stats"] - pub rpz_action: [::std::os::raw::c_longlong; 10usize], -} -#[doc = " Statistics to send over the control pipe when asked\n This struct is made to be memcopied, sent in binary.\n shm mapped with (number+1) at num_threads+1, with first as total"] -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ub_stats_info { - #[doc = " the thread stats"] - pub svr: ub_server_stats, - #[doc = " mesh stats: current number of states"] - pub mesh_num_states: ::std::os::raw::c_longlong, - #[doc = " mesh stats: current number of reply (user) states"] - pub mesh_num_reply_states: ::std::os::raw::c_longlong, - #[doc = " mesh stats: number of reply states overwritten with a new one"] - pub mesh_jostled: ::std::os::raw::c_longlong, - #[doc = " mesh stats: number of incoming queries dropped"] - pub mesh_dropped: ::std::os::raw::c_longlong, - #[doc = " mesh stats: replies sent"] - pub mesh_replies_sent: ::std::os::raw::c_longlong, - #[doc = " mesh stats: sum of waiting times for the replies"] - pub mesh_replies_sum_wait_sec: ::std::os::raw::c_longlong, - #[doc = " mesh stats: sum of waiting times for the replies"] - pub mesh_replies_sum_wait_usec: ::std::os::raw::c_longlong, - #[doc = " mesh stats: median of waiting times for replies (in sec)"] - pub mesh_time_median: f64, -} diff --git a/crates/libunbound-sys/unbound/LICENSE b/crates/libunbound-sys/unbound/LICENSE deleted file mode 100644 index 1859c095..00000000 --- a/crates/libunbound-sys/unbound/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2007, NLnet Labs. All rights reserved. - -This software is open source. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -Neither the name of the NLNET LABS nor the names of its contributors may -be used to endorse or promote products derived from this software without -specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/crates/libunbound-sys/unbound/Makefile.in b/crates/libunbound-sys/unbound/Makefile.in deleted file mode 100644 index 0a2e7f9b..00000000 --- a/crates/libunbound-sys/unbound/Makefile.in +++ /dev/null @@ -1,1625 +0,0 @@ -# Copyright 2007 NLnet Labs -# See the file LICENSE for the license - -SHELL=@SHELL@ -VERSION=@PACKAGE_VERSION@ -srcdir=@srcdir@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -sbindir=@sbindir@ -mandir=@mandir@ -libdir=@libdir@ -# datarootdir is here to please some checkers, use datadir. -datarootdir=@datarootdir@ -datadir=@datadir@ -includedir=@includedir@ -doxygen=@doxygen@ -libtool=@libtool@ -staticexe=@staticexe@ -EXEEXT=@EXEEXT@ -configfile=@ub_conf_file@ -CHECKLOCK_SRC=testcode/checklocks.c -CHECKLOCK_OBJ=@CHECKLOCK_OBJ@ -DNSTAP_SRC=@DNSTAP_SRC@ -DNSTAP_OBJ=@DNSTAP_OBJ@ -DNSCRYPT_SRC=@DNSCRYPT_SRC@ -DNSCRYPT_OBJ=@DNSCRYPT_OBJ@ -WITH_DYNLIBMODULE=@WITH_DYNLIBMODULE@ -WITH_PYTHONMODULE=@WITH_PYTHONMODULE@ -WITH_PYUNBOUND=@WITH_PYUNBOUND@ -PY_MAJOR_VERSION=@PY_MAJOR_VERSION@ -PYTHON_SITE_PKG=@PYTHON_SITE_PKG@ -PYTHONMOD_INSTALL=@PYTHONMOD_INSTALL@ -PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@ -PYUNBOUND_INSTALL=@PYUNBOUND_INSTALL@ -PYUNBOUND_UNINSTALL=@PYUNBOUND_UNINSTALL@ -UNBOUND_EVENT_INSTALL=@UNBOUND_EVENT_INSTALL@ -UNBOUND_EVENT_UNINSTALL=@UNBOUND_EVENT_UNINSTALL@ -UNBOUND_VERSION_MAJOR=@UNBOUND_VERSION_MAJOR@ -UNBOUND_VERSION_MINOR=@UNBOUND_VERSION_MINOR@ -UNBOUND_VERSION_MICRO=@UNBOUND_VERSION_MICRO@ -ALLTARGET=@ALLTARGET@ -INSTALLTARGET=@INSTALLTARGET@ -SSLLIB=@SSLLIB@ - -# _unbound.la if pyunbound enabled. -PYUNBOUND_TARGET=@PYUNBOUND_TARGET@ - -# override $U variable which is used by autotools for deansification (for -# K&R C compilers), but causes problems if $U is defined in the env). -U= - -PROTOC_C=@PROTOC_C@ -SWIG=@SWIG@ -YACC=@YACC@ -LEX=@LEX@ -STRIP=@STRIP@ -CC=@CC@ -CPPFLAGS=-I. @CPPFLAGS@ -PYTHON_CPPFLAGS=-I. -I$(srcdir) @PYTHON_CPPFLAGS@ -CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@ -LDFLAGS=@LDFLAGS@ -LIBS=@LIBS@ -PYTHON_LIBS=@PYTHON_LIBS@ -LIBOBJS=@LIBOBJS@ -# filter out ctime_r from compat obj. -LIBOBJ_WITHOUT_CTIME=@LIBOBJ_WITHOUT_CTIME@ -LIBOBJ_WITHOUT_CTIMEARC4=@LIBOBJ_WITHOUT_CTIMEARC4@ -RUNTIME_PATH=@RUNTIME_PATH@ -DEPFLAG=@DEPFLAG@ -DATE=@CONFIG_DATE@ -LIBTOOL=$(libtool) -BUILD=build/ -UBSYMS=@UBSYMS@ -EXTRALINK=@EXTRALINK@ - -WINDRES=@WINDRES@ -LINT=splint -LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list -formatcode -#-Dglob64=glob -Dglobfree64=globfree -# compat with openssl linux edition. -LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" -D"ECDSA_SIG=DSA_SIG" -# compat with NetBSD -LINTFLAGS+=@NETBSD_LINTFLAGS@ -# compat with OpenBSD -LINTFLAGS+="-Dsigset_t=long" -# FreeBSD -LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list" "-D__uint32_t=uint32_t" "-D_Alignof(x)=x" "-D__aligned(x)=" "-D__requires_exclusive(x)=" "-D__requires_unlocked(x)=" "-D__locks_exclusive(x)=" "-D__trylocks_exclusive(x)=" "-D__unlocks(x)=" "-D__locks_shared(x)=" "-D__trylocks_shared(x)=" -# GCC Docker -LINTFLAGS+=@GCC_DOCKER_LINTFLAGS@ - -INSTALL=$(SHELL) $(srcdir)/install-sh - -DYNLIBMOD_SRC=dynlibmod/dynlibmod.c -DYNLIBMOD_OBJ=@DYNLIBMOD_OBJ@ -DYNLIBMOD_HEADER=@DYNLIBMOD_HEADER@ -DYNLIBMOD_EXTRALIBS=@DYNLIBMOD_EXTRALIBS@ - - -#pythonmod.c is not here, it is mentioned by itself in its own rules, -#makedepend fails on missing interface.h otherwise. -PYTHONMOD_SRC=pythonmod/pythonmod_utils.c -# pythonmod.lo pythonmod_utils.lo if python mod enabled. -PYTHONMOD_OBJ=@PYTHONMOD_OBJ@ -PYTHONMOD_HEADER=@PYTHONMOD_HEADER@ -# libunbound/python/libunbound_wrap.c is dealt with by its own rules. -PYUNBOUND_SRC= -# libunbound_wrap.lo if python libunbound wrapper enabled. -PYUNBOUND_OBJ=@PYUNBOUND_OBJ@ -SUBNET_SRC=edns-subnet/edns-subnet.c edns-subnet/subnetmod.c edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c -SUBNET_OBJ=@SUBNET_OBJ@ -SUBNET_HEADER=@SUBNET_HEADER@ -IPSECMOD_SRC=ipsecmod/ipsecmod.c ipsecmod/ipsecmod-whitelist.c -IPSECMOD_OBJ=@IPSECMOD_OBJ@ -IPSECMOD_HEADER=@IPSECMOD_HEADER@ -CACHEDB_SRC=@CACHEDB_SRC@ -CACHEDB_OBJ=@CACHEDB_OBJ@ -COMMON_SRC=services/cache/dns.c services/cache/infra.c services/cache/rrset.c \ -util/as112.c util/data/dname.c util/data/msgencode.c util/data/msgparse.c \ -util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \ -iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \ -iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \ -iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \ -services/localzone.c services/mesh.c services/modstack.c services/view.c \ -services/rpz.c util/rfc_1982.c \ -services/outbound_list.c services/outside_network.c util/alloc.c \ -util/config_file.c util/configlexer.c util/configparser.c \ -util/shm_side/shm_main.c services/authzone.c \ -util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \ -util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \ -util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \ -util/storage/lruhash.c util/storage/slabhash.c util/tcp_conn_limit.c \ -util/timehist.c util/tube.c util/proxy_protocol.c util/timeval_func.c \ -util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \ -validator/autotrust.c validator/val_anchor.c validator/validator.c \ -validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \ -validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \ -validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \ -edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \ -edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \ -$(CACHEDB_SRC) respip/respip.c $(CHECKLOCK_SRC) \ -$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC) -COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \ -as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \ -iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \ -iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo view.lo \ -outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \ -fptr_wlist.lo siphash.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \ -random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \ -slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \ -autotrust.lo val_anchor.lo rpz.lo rfc_1982.lo proxy_protocol.lo \ -validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \ -val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \ -$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \ -$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.lo -COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \ -outside_network.lo -COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo -# set to $COMMON_OBJ or to "" if --enableallsymbols -COMMON_OBJ_ALL_SYMBOLS=@COMMON_OBJ_ALL_SYMBOLS@ -COMPAT_SRC=compat/ctime_r.c compat/fake-rfc2553.c compat/gmtime_r.c \ -compat/inet_aton.c compat/inet_ntop.c compat/inet_pton.c compat/malloc.c \ -compat/memcmp.c compat/memmove.c compat/snprintf.c compat/strlcat.c \ -compat/strlcpy.c compat/strptime.c compat/getentropy_freebsd.c compat/getentropy_linux.c \ -compat/getentropy_osx.c compat/getentropy_solaris.c compat/getentropy_win.c \ -compat/explicit_bzero.c compat/arc4random.c compat/arc4random_uniform.c \ -compat/arc4_lock.c compat/sha512.c compat/reallocarray.c compat/isblank.c \ -compat/strsep.c -COMPAT_OBJ=$(LIBOBJS:.o=.lo) -COMPAT_OBJ_WITHOUT_CTIME=$(LIBOBJ_WITHOUT_CTIME:.o=.lo) -COMPAT_OBJ_WITHOUT_CTIMEARC4=$(LIBOBJ_WITHOUT_CTIMEARC4:.o=.lo) -SLDNS_SRC=sldns/keyraw.c sldns/sbuffer.c sldns/wire2str.c sldns/parse.c \ -sldns/parseutil.c sldns/rrdef.c sldns/str2wire.c -SLDNS_OBJ=keyraw.lo sbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ -str2wire.lo -SLDNS_ALLOCCHECK_EXTRA_OBJ=@SLDNS_ALLOCCHECK_EXTRA_OBJ@ -UNITTEST_SRC=testcode/unitanchor.c testcode/unitdname.c \ -testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \ -testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \ -testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c \ -testcode/unitecs.c testcode/unitauth.c testcode/unitzonemd.c \ -testcode/unittcpreuse.c -UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \ -unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \ -readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo \ -unittcpreuse.lo -UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \ -$(COMPAT_OBJ) -DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \ -daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@ -DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo \ -shm_main.lo remote.lo stats.lo unbound.lo \ -worker.lo @WIN_DAEMON_OBJ@ -DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \ -$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@ -CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c -CHECKCONF_OBJ=unbound-checkconf.lo worker_cb.lo -CHECKCONF_OBJ_LINK=$(CHECKCONF_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \ -$(COMPAT_OBJ) @WIN_CHECKCONF_OBJ_LINK@ -CONTROL_SRC=smallapp/unbound-control.c -CONTROL_OBJ=unbound-control.lo -CONTROL_OBJ_LINK=$(CONTROL_OBJ) worker_cb.lo $(COMMON_OBJ_ALL_SYMBOLS) \ -$(SLDNS_OBJ) $(COMPAT_OBJ) @WIN_CONTROL_OBJ_LINK@ -HOST_SRC=smallapp/unbound-host.c -HOST_OBJ=unbound-host.lo -HOST_OBJ_LINK=$(HOST_OBJ) $(SLDNS_OBJ) $(COMPAT_OBJ_WITHOUT_CTIMEARC4) $(SLDNS_ALLOCCHECK_EXTRA_OBJ) @WIN_HOST_OBJ_LINK@ -UBANCHOR_SRC=smallapp/unbound-anchor.c -UBANCHOR_OBJ=unbound-anchor.lo -UBANCHOR_OBJ_LINK=$(UBANCHOR_OBJ) parseutil.lo \ -$(COMPAT_OBJ_WITHOUT_CTIME) $(SLDNS_ALLOCCHECK_EXTRA_OBJ) @WIN_UBANCHOR_OBJ_LINK@ -TESTBOUND_SRC=testcode/testbound.c testcode/testpkts.c \ -daemon/worker.c daemon/acl_list.c \ -daemon/daemon.c daemon/stats.c \ -testcode/replay.c testcode/fake_event.c -TESTBOUND_OBJ=testbound.lo replay.lo fake_event.lo -TESTBOUND_OBJ_LINK=$(TESTBOUND_OBJ) testpkts.lo worker.lo acl_list.lo \ -daemon.lo stats.lo shm_main.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \ -$(COMPAT_OBJ) -LOCKVERIFY_SRC=testcode/lock_verify.c -LOCKVERIFY_OBJ=lock_verify.lo -LOCKVERIFY_OBJ_LINK=$(LOCKVERIFY_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \ -$(SLDNS_OBJ) -PETAL_SRC=testcode/petal.c -PETAL_OBJ=petal.lo -PETAL_OBJ_LINK=$(PETAL_OBJ) $(COMPAT_OBJ_WITHOUT_CTIMEARC4) -PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c -PKTVIEW_OBJ=pktview.lo -PKTVIEW_OBJ_LINK=$(PKTVIEW_OBJ) worker_cb.lo readhex.lo $(COMMON_OBJ) \ -$(COMPAT_OBJ) $(SLDNS_OBJ) -MEMSTATS_SRC=testcode/memstats.c -MEMSTATS_OBJ=memstats.lo -MEMSTATS_OBJ_LINK=$(MEMSTATS_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \ -$(SLDNS_OBJ) -ASYNCLOOK_SRC=testcode/asynclook.c -ASYNCLOOK_OBJ=asynclook.lo -ASYNCLOOK_OBJ_LINK=$(ASYNCLOOK_OBJ) log.lo locks.lo $(CHECKLOCK_OBJ) $(COMPAT_OBJ) @ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ@ -STREAMTCP_SRC=testcode/streamtcp.c -STREAMTCP_OBJ=streamtcp.lo -STREAMTCP_OBJ_LINK=$(STREAMTCP_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \ -$(SLDNS_OBJ) -DOHCLIENT_SRC=testcode/dohclient.c -DOHCLIENT_OBJ=dohclient.lo -DOHCLIENT_OBJ_LINK=$(DOHCLIENT_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \ -$(SLDNS_OBJ) -PERF_SRC=testcode/perf.c -PERF_OBJ=perf.lo -PERF_OBJ_LINK=$(PERF_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) $(SLDNS_OBJ) -DELAYER_SRC=testcode/delayer.c -DELAYER_OBJ=delayer.lo -DELAYER_OBJ_LINK=$(DELAYER_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \ -$(SLDNS_OBJ) -READZONE_SRC=testcode/readzone.c -READZONE_OBJ=readzone.lo -READZONE_OBJ_LINK=$(READZONE_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) $(SLDNS_OBJ) -IPSET_SRC=@IPSET_SRC@ -IPSET_OBJ=@IPSET_OBJ@ -DNSTAP_SOCKET_SRC=dnstap/unbound-dnstap-socket.c -DNSTAP_SOCKET_OBJ=unbound-dnstap-socket.lo -DNSTAP_SOCKET_OBJ_LINK=$(DNSTAP_SOCKET_OBJ) $(COMMON_OBJ) \ -$(COMPAT_OBJ) $(SLDNS_OBJ) -DNSTAP_SOCKET_TESTBIN=@DNSTAP_SOCKET_TESTBIN@ -LIBUNBOUND_SRC=libunbound/context.c libunbound/libunbound.c \ -libunbound/libworker.c -LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo ub_event_pluggable.lo -LIBUNBOUND_OBJ_LINK=$(LIBUNBOUND_OBJ) $(COMMON_OBJ_WITHOUT_UB_EVENT) $(SLDNS_OBJ) $(COMPAT_OBJ) - -# win apps or "" if not on windows -WINAPPS=@WINAPPS@ -WIN_DAEMON_THE_SRC=winrc/win_svc.c winrc/w_inst.c -SVCINST_SRC=winrc/unbound-service-install.c -SVCINST_OBJ=unbound-service-install.lo -SVCINST_OBJ_LINK=$(SVCINST_OBJ) w_inst.lo rsrc_svcinst.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4) -SVCUNINST_SRC=winrc/unbound-service-remove.c -SVCUNINST_OBJ=unbound-service-remove.lo -SVCUNINST_OBJ_LINK=$(SVCUNINST_OBJ) w_inst.lo rsrc_svcuninst.o \ -$(COMPAT_OBJ_WITHOUT_CTIMEARC4) -ANCHORUPD_SRC=winrc/anchor-update.c -ANCHORUPD_OBJ=anchor-update.lo -ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4) wire2str.lo str2wire.lo parseutil.lo sbuffer.lo rrdef.lo keyraw.lo parse.lo -RSRC_OBJ=rsrc_svcinst.o rsrc_svcuninst.o rsrc_anchorupd.o rsrc_unbound.o \ - rsrc_unbound_host.o rsrc_unbound_anchor.o rsrc_unbound_control.o \ - rsrc_unbound_checkconf.o - -ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \ - $(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) \ - $(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \ - $(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \ - $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) $(DNSTAP_SOCKET_SRC)\ - $(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC) \ - $(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC) \ - $(DOHCLIENT_SRC) $(READZONE_SRC) - -ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \ - $(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \ - $(MEMSTATS_OBJ) $(CHECKCONF_OBJ) $(LIBUNBOUND_OBJ) $(HOST_OBJ) \ - $(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \ - $(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) $(DNSTAP_SOCKET_OBJ)\ - $(COMPAT_OBJ) $(PYUNBOUND_OBJ) \ - $(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) $(SLDNS_OBJ) \ - $(DOHCLIENT_OBJ) $(READZONE_OBJ) - -COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@ -LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined - -.PHONY: clean realclean doc lint all install uninstall tests test strip lib longtest longcheck check alltargets - -all: $(COMMON_OBJ) $(ALLTARGET) - -alltargets: unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET) - -# compat with BSD make, register suffix, and an implicit rule to actualise it. -.SUFFIXES: .lo -.c.lo: - $(COMPILE) -o $@ -c $< - -$(ALL_OBJ): - @@SOURCEDETERMINE@ - $(COMPILE) -o $@ -c @SOURCEFILE@ - -$(RSRC_OBJ): - @@SOURCEDETERMINE@ - $(WINDRES) $(CPPFLAGS) @SOURCEFILE@ $@ - -rsrc_svcinst.o: $(srcdir)/winrc/rsrc_svcinst.rc config.h -rsrc_svcuninst.o: $(srcdir)/winrc/rsrc_svcuninst.rc config.h -rsrc_anchorupd.o: $(srcdir)/winrc/rsrc_anchorupd.rc config.h -rsrc_unbound.o: $(srcdir)/winrc/rsrc_unbound.rc config.h -rsrc_unbound_host.o: $(srcdir)/winrc/rsrc_unbound_host.rc config.h -rsrc_unbound_anchor.o: $(srcdir)/winrc/rsrc_unbound_anchor.rc config.h -rsrc_unbound_control.o: $(srcdir)/winrc/rsrc_unbound_control.rc config.h -rsrc_unbound_checkconf.o: $(srcdir)/winrc/rsrc_unbound_checkconf.rc config.h - -TEST_BIN=asynclook$(EXEEXT) delayer$(EXEEXT) \ - lock-verify$(EXEEXT) memstats$(EXEEXT) perf$(EXEEXT) \ - petal$(EXEEXT) pktview$(EXEEXT) streamtcp$(EXEEXT) \ - $(DNSTAP_SOCKET_TESTBIN) dohclient$(EXEEXT) \ - testbound$(EXEEXT) unittest$(EXEEXT) readzone$(EXEEXT) -tests: all $(TEST_BIN) - -check: test -longcheck: longtest - -test: unittest$(EXEEXT) testbound$(EXEEXT) - ./unittest$(EXEEXT) - ./testbound$(EXEEXT) -s - for x in $(srcdir)/testdata/*.rpl; do \ - output=`./testbound$(EXEEXT) -p $$x -o -vvvvv 2>&1`; \ - if test $$? -eq 0; then \ - printf "%s OK\n" "$$x "; \ - else \ - printf "%s\n" "$$output "; \ - printf "%s failed\n" "$$x "; \ - exit 1; \ - fi; \ - done - @echo test OK - -longtest: tests - if test ! $(srcdir)/testdata -ef ./testdata; then rm -rf testcode testdata; mkdir testcode testdata; cp -R $(srcdir)/testdata/*.sh $(srcdir)/testdata/*.tdir $(srcdir)/testdata/*.rpl $(srcdir)/testdata/*.crpl testdata; cp $(srcdir)/testcode/*.sh testcode; if test ! -d util; then mkdir util; fi; cp $(srcdir)/util/iana_ports.inc util; fi - if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi - -lib: libunbound.la unbound.h - -libunbound.la: $(LIBUNBOUND_OBJ_LINK) - $(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) $(SSLLIB) $(LIBS) - -unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS) - -unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) - -unbound-control$(EXEEXT): $(CONTROL_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) - -unbound-host$(EXEEXT): $(HOST_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(HOST_OBJ_LINK) libunbound.la $(SSLLIB) $(LIBS) - -unbound-anchor$(EXEEXT): $(UBANCHOR_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(UBANCHOR_OBJ_LINK) libunbound.la -lexpat $(SSLLIB) $(LIBS) - -unbound-service-install$(EXEEXT): $(SVCINST_OBJ_LINK) - $(LINK) -o $@ $(SVCINST_OBJ_LINK) $(LIBS) - -unbound-service-remove$(EXEEXT): $(SVCUNINST_OBJ_LINK) - $(LINK) -o $@ $(SVCUNINST_OBJ_LINK) $(LIBS) - -anchor-update$(EXEEXT): $(ANCHORUPD_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(ANCHORUPD_OBJ_LINK) libunbound.la $(LIBS) - -unittest$(EXEEXT): $(UNITTEST_OBJ_LINK) - $(LINK) -o $@ $(UNITTEST_OBJ_LINK) $(SSLLIB) $(LIBS) - -testbound$(EXEEXT): $(TESTBOUND_OBJ_LINK) - $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) $(SSLLIB) $(LIBS) - -lock-verify$(EXEEXT): $(LOCKVERIFY_OBJ_LINK) - $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) $(SSLLIB) $(LIBS) - -petal$(EXEEXT): $(PETAL_OBJ_LINK) - $(LINK) -o $@ $(PETAL_OBJ_LINK) $(SSLLIB) $(LIBS) - -pktview$(EXEEXT): $(PKTVIEW_OBJ_LINK) - $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) $(SSLLIB) $(LIBS) - -memstats$(EXEEXT): $(MEMSTATS_OBJ_LINK) - $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) $(SSLLIB) $(LIBS) - -asynclook$(EXEEXT): $(ASYNCLOOK_OBJ_LINK) libunbound.la - $(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) libunbound.la $(SSLLIB) $(LIBS) - -streamtcp$(EXEEXT): $(STREAMTCP_OBJ_LINK) - $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS) - -dohclient$(EXEEXT): $(DOHCLIENT_OBJ_LINK) - $(LINK) -o $@ $(DOHCLIENT_OBJ_LINK) $(SSLLIB) $(LIBS) - -perf$(EXEEXT): $(PERF_OBJ_LINK) - $(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS) - -delayer$(EXEEXT): $(DELAYER_OBJ_LINK) - $(LINK) -o $@ $(DELAYER_OBJ_LINK) $(SSLLIB) $(LIBS) - -readzone$(EXEEXT): $(READZONE_OBJ_LINK) - $(LINK) -o $@ $(READZONE_OBJ_LINK) $(SSLLIB) $(LIBS) - -signit$(EXEEXT): testcode/signit.c - $(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@ -o $@ testcode/signit.c $(LDFLAGS) -lldns $(SSLLIB) $(LIBS) - -unbound.h: $(srcdir)/libunbound/unbound.h - sed -e 's/@''UNBOUND_VERSION_MAJOR@/$(UNBOUND_VERSION_MAJOR)/' -e 's/@''UNBOUND_VERSION_MINOR@/$(UNBOUND_VERSION_MINOR)/' -e 's/@''UNBOUND_VERSION_MICRO@/$(UNBOUND_VERSION_MICRO)/' < $(srcdir)/libunbound/unbound.h > $@ - -unbound-control-setup: smallapp/unbound-control-setup.sh - cp smallapp/unbound-control-setup.sh $@ - -chmod +x $@ - -# dnstap -dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h dnstap/dnstap_config.h \ - dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h - -dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h: $(srcdir)/dnstap/dnstap.proto - @-if test ! -d dnstap; then $(INSTALL) -d dnstap; fi - $(PROTOC_C) --c_out=. --proto_path=$(srcdir) $(srcdir)/dnstap/dnstap.proto - -unbound-dnstap-socket$(EXEEXT): $(DNSTAP_SOCKET_OBJ_LINK) - $(LINK) -o $@ $(DNSTAP_SOCKET_OBJ_LINK) $(SSLLIB) $(LIBS) - -dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h -dtstream.lo dtstream.o: $(srcdir)/dnstap/dtstream.c config.h $(srcdir)/dnstap/dtstream.h -dnstap_fstrm.lo dnstap_fstrm.o: $(srcdir)/dnstap/dnstap_fstrm.c config.h $(srcdir)/dnstap/dnstap_fstrm.h -unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnstap-socket.c config.h $(srcdir)/dnstap/dtstream.h -dynlibmod.lo dynlibdmod.o: $(srcdir)/dynlibmod/dynlibmod.c config.h $(srcdir)/dynlibmod/dynlibmod.h -cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h -redis.lo redis.o: $(srcdir)/cachedb/redis.c config.h $(srcdir)/cachedb/redis.h -timeval_func.lo timeval_func.o: $(srcdir)/util/timeval_func.c $(srcdir)/util/timeval_func.h - -# dnscrypt -dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \ - dnscrypt/dnscrypt_config.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h - -# Python Module -pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \ - pythonmod/interface.h \ - $(srcdir)/pythonmod/pythonmod.h $(srcdir)/util/module.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/config_file.h \ - $(srcdir)/pythonmod/pythonmod_utils.h $(srcdir)/util/netevent.h \ - $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h \ - $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h - -pythonmod/interface.h: $(srcdir)/pythonmod/interface.i config.h - @-if test ! -d pythonmod; then $(INSTALL) -d pythonmod; fi - $(SWIG) $(PYTHON_CPPFLAGS) -o $@ -python $(srcdir)/pythonmod/interface.i - -libunbound_wrap.lo libunbound_wrap.o: libunbound/python/libunbound_wrap.c \ - unbound.h -libunbound/python/libunbound_wrap.c: $(srcdir)/libunbound/python/libunbound.i unbound.h - @-if test ! -d libunbound/python; then $(INSTALL) -d libunbound/python; fi - $(SWIG) -python -o $@ $(PYTHON_CPPFLAGS) -DPY_MAJOR_VERSION=$(PY_MAJOR_VERSION) $(srcdir)/libunbound/python/libunbound.i - -# Pyunbound python unbound wrapper -_unbound.la: libunbound_wrap.lo libunbound.la - $(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -module -avoid-version -no-undefined -shared -o $@ libunbound_wrap.lo -rpath $(PYTHON_SITE_PKG) -L. -L.libs libunbound.la $(PYTHON_LIBS) - -util/config_file.c: util/configparser.h -util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h - @-if test ! -d util; then $(INSTALL) -d util; fi - if test "$(LEX)" != ":"; then \ - echo "#include \"config.h\"" > $@ ;\ - echo "#include \"util/configyyrename.h\"" >> $@ ;\ - $(LEX) -t $(srcdir)/util/configlexer.lex >> $@ ;\ - fi - @if test ! -f $@; then echo "No $@ : need flex and bison to compile from source repository"; exit 1; fi - -util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y - @-if test ! -d util; then $(INSTALL) -d util; fi - $(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y - -clean: - rm -f *.o *.d *.lo *~ tags - rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h - rm -f $(ALL_SRC:.c=.lint) - rm -f _unbound.la libunbound/python/libunbound_wrap.c libunbound/python/unbound.py pythonmod/interface.h pythonmod/unboundmodule.py - rm -f libunbound.a - rm -rf autom4te.cache .libs build doc/html doc/xml - -distclean: clean - rm -f config.status config.log config.h - rm -f doc/example.conf doc/libunbound.3 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound-control.8 doc/unbound.8 doc/unbound.conf.5 doc/unbound-host.1 - rm -f smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service - rm -f $(TEST_BIN) - rm -f Makefile - -maintainer-clean: distclean - rm -f util/configlexer.c util/configparser.c util/configparser.h - -realclean: maintainer-clean - rm -f configure config.h.in config.sub config.guess ltmain.sh aclocal.m4 libtool - -.SUFFIXES: .lint -.c.lint: - $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $< - touch $@ - -util/configparser.lint util/configlexer.lint pythonmod/pythonmod.lint libunbound/python/libunbound_wrap.lint dnstap/dnstap.pb-c.lint: - # skip lint for generated code - touch $@ - -winrc/win_svc.lint winrc/w_inst.lint winrc/unbound-service-install.lint winrc/unbound-service-remove.lint: - # skip lint for windows types - touch $@ - -lint: $(ALL_SRC:.c=.lint) - -tags: $(srcdir)/*.[ch] $(srcdir)/*/*.[ch] - ctags -f $(srcdir)/tags $(srcdir)/*.[ch] $(srcdir)/*/*.[ch] - -doc: - if test -n "$(doxygen)"; then \ - $(doxygen) $(srcdir)/doc/unbound.doxygen; fi - if test "$(WITH_PYUNBOUND)" = "yes" -o "$(WITH_PYTHONMODULE)" = "yes"; \ - then if test -x "`which sphinx-build-$(PY_MAJOR_VERSION) 2>&1`"; then \ - sphinx-build-$(PY_MAJOR_VERSION) -b html pythonmod/doc doc/html/pythonmod; \ - sphinx-build-$(PY_MAJOR_VERSION) -b html libunbound/python/doc doc/html/pyunbound;\ - fi ;\ - fi - -strip: - $(STRIP) unbound$(EXEEXT) - $(STRIP) unbound-checkconf$(EXEEXT) - $(STRIP) unbound-control$(EXEEXT) - $(STRIP) unbound-host$(EXEEXT) || $(STRIP) .libs/unbound-host$(EXEEXT) - $(STRIP) unbound-anchor$(EXEEXT) || $(STRIP) .libs/unbound-anchor$(EXEEXT) - -pythonmod-install: - $(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG) - $(INSTALL) -c -m 644 pythonmod/unboundmodule.py $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py - -pyunbound-install: - $(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG) - $(INSTALL) -c -m 644 libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py - $(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG) - $(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG) - -unbound-event-install: - $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) - $(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound-event.h $(DESTDIR)$(includedir)/unbound-event.h - -install: $(INSTALLTARGET) - -install-lib: lib $(UNBOUND_EVENT_INSTALL) - $(INSTALL) -m 755 -d $(DESTDIR)$(libdir) - $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man3 - $(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3 - for mpage in ub_ctx ub_result ub_ctx_create ub_ctx_delete \ - ub_ctx_set_option ub_ctx_get_option ub_ctx_config ub_ctx_set_fwd \ - ub_ctx_resolvconf ub_ctx_hosts ub_ctx_add_ta ub_ctx_add_ta_file \ - ub_ctx_trustedkeys ub_ctx_debugout ub_ctx_debuglevel ub_ctx_async \ - ub_poll ub_wait ub_fd ub_process ub_resolve ub_resolve_async ub_cancel \ - ub_resolve_free ub_strerror ub_ctx_print_local_zones ub_ctx_zone_add \ - ub_ctx_zone_remove ub_ctx_data_add ub_ctx_data_remove; \ - do \ - echo ".so man3/libunbound.3" > $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \ - done - $(LIBTOOL) --mode=install cp unbound.h $(DESTDIR)$(includedir)/unbound.h - $(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig - $(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig - $(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir) - $(LIBTOOL) --mode=finish $(DESTDIR)$(libdir) - -install-all: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTALL) install-lib - $(INSTALL) -m 755 -d $(DESTDIR)$(sbindir) - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8 - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5 - $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 - $(LIBTOOL) --mode=install cp -f unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT) - $(LIBTOOL) --mode=install cp -f unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) - $(LIBTOOL) --mode=install cp -f unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) - $(LIBTOOL) --mode=install cp -f unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) - $(LIBTOOL) --mode=install cp -f unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) - $(INSTALL) -c -m 644 doc/unbound.8 $(DESTDIR)$(mandir)/man8 - $(INSTALL) -c -m 644 doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8 - $(INSTALL) -c -m 644 doc/unbound-control.8 $(DESTDIR)$(mandir)/man8 - $(INSTALL) -c -m 644 doc/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-control-setup.8 - $(INSTALL) -c -m 644 doc/unbound-anchor.8 $(DESTDIR)$(mandir)/man8 - $(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5 - $(INSTALL) -c -m 644 doc/unbound-host.1 $(DESTDIR)$(mandir)/man1 - $(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup - if test ! -e "$(DESTDIR)$(configfile)"; then $(INSTALL) -d `dirname "$(DESTDIR)$(configfile)"`; $(INSTALL) -c -m 644 doc/example.conf "$(DESTDIR)$(configfile)"; fi - -pythonmod-uninstall: - rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py - -pyunbound-uninstall: - rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(PYTHON_SITE_PKG)/_unbound.la - -unbound-event-uninstall: - rm -f -- $(DESTDIR)$(includedir)/unbound-event.h - -uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) $(UNBOUND_EVENT_UNINSTALL) - rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup - rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8 $(DESTDIR)$(mandir)/man8/unbound-control-setup.8 - rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3 - for mpage in ub_ctx ub_result ub_ctx_create ub_ctx_delete \ - ub_ctx_set_option ub_ctx_get_option ub_ctx_config ub_ctx_set_fwd \ - ub_ctx_resolvconf ub_ctx_hosts ub_ctx_add_ta ub_ctx_add_ta_file \ - ub_ctx_trustedkeys ub_ctx_debugout ub_ctx_debuglevel ub_ctx_async \ - ub_poll ub_wait ub_fd ub_process ub_resolve ub_resolve_async ub_cancel \ - ub_resolve_free ub_strerror ub_ctx_print_local_zones ub_ctx_zone_add \ - ub_ctx_zone_remove ub_ctx_data_add ub_ctx_data_remove; \ - do \ - rm -f -- $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \ - done - rm -f -- $(DESTDIR)$(includedir)/unbound.h - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la - @echo - @echo "You still need to remove "`dirname "$(DESTDIR)$(configfile)"`" , $(DESTDIR)$(configfile) by hand" - -iana_update: - curl -o port-numbers.tmp https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed - if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '// {p=0;} /udp/ {p=1;} /[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} // { if(u==1) {u=0;} else { if(p==1) { match($$0,/[0-9]+/); print substr($$0, RSTART, RLENGTH) ","}}}' | sort -nu > util/iana_ports.inc - rm -f port-numbers.tmp - -# dependency generation -DEPEND_TMP=depend1073.tmp -DEPEND_TMP2=depend1074.tmp -DEPEND_TARGET=Makefile -DEPEND_TARGET2=$(srcdir)/Makefile.in -# actions: generate deplines from gcc, -# then, filter out home/xx, /usr/xx and /opt/xx lines (some cc already do this) -# then, remove empty " \" lines -# then, add srcdir before .c and .h in deps. -# then, remove srcdir from the (generated) parser and lexer. -# and mention the .lo -depend: - (BUILDDIR=$$PWD; cd $(srcdir) ; $(CC) $(DEPFLAG) $(CPPFLAGS) $(CFLAGS) -I$$BUILDDIR @PTHREAD_CFLAGS_ONLY@ $(ALL_SRC) $(COMPAT_SRC)) | \ - sed -e 's?'$$PWD'/config.h?config.h?g' | \ - sed -e 's!'$$HOME'[^ ]* !!g' -e 's!'$$HOME'[^ ]*$$!!g' \ - -e 's!/usr[^ ]* !!g' -e 's!/usr[^ ]*$$!!g' \ - -e 's!/opt[^ ]* !!g' -e 's!/opt[^ ]*$$!!g' | \ - sed -e '/^ \\$$/d' | \ - sed -e 's? *\([^ ]*\.[ch]\)? $$(srcdir)/\1?g' | \ - sed -e 's? *\([^ ]*\.inc\)? $$(srcdir)/\1?g' | \ - sed -e 's?$$(srcdir)/config.h?config.h?g' \ - -e 's?$$(srcdir)/util/configlexer.c?util/configlexer.c?g' \ - -e 's?$$(srcdir)/util/configparser.c?util/configparser.c?g' \ - -e 's?$$(srcdir)/util/configparser.h?util/configparser.h?g' \ - -e 's?$$(srcdir)/dnstap/dnstap_config.h??g' \ - -e 's?$$(srcdir)/dnstap/dnstap.pb-c.c?dnstap/dnstap.pb-c.c?g' \ - -e 's?$$(srcdir)/dnstap/dnstap.pb-c.h?dnstap/dnstap.pb-c.h?g' \ - -e 's?$$(srcdir)/dnscrypt/dnscrypt_config.h??g' \ - -e 's?$$(srcdir)/pythonmod/pythonmod.h?$$(PYTHONMOD_HEADER)?g' \ - -e 's?$$(srcdir)/edns-subnet/subnetmod.h $$(srcdir)/edns-subnet/subnet-whitelist.h $$(srcdir)/edns-subnet/edns-subnet.h $$(srcdir)/edns-subnet/addrtree.h?$$(SUBNET_HEADER)?g' \ - -e 's?$$(srcdir)/ipsecmod/ipsecmod.h $$(srcdir)/ipsecmod/ipsecmod-whitelist.h?$$(IPSECMOD_HEADER)?g' \ - -e 's?$$(srcdir)/dynlibmod/dynlibmod.h?$$(DYNLIBMOD_HEADER)?g' \ - -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \ - > $(DEPEND_TMP) - cp $(DEPEND_TARGET) $(DEPEND_TMP2) - head -`egrep -n "# Dependencies" $(DEPEND_TARGET) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET) - cat $(DEPEND_TMP) >> $(DEPEND_TARGET) - @if diff $(DEPEND_TARGET) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET) unchanged"; else echo " Updated $(DEPEND_TARGET))"; fi - @if test -f $(DEPEND_TARGET2); then \ - cp $(DEPEND_TARGET2) $(DEPEND_TMP2); \ - head -`egrep -n "# Dependencies" $(DEPEND_TARGET2) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET2); \ - cat $(DEPEND_TMP) >> $(DEPEND_TARGET2); \ - if diff $(DEPEND_TARGET2) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET2) unchanged"; else echo " Updated $(DEPEND_TARGET2))"; fi; \ - fi - rm -f $(DEPEND_TMP) $(DEPEND_TMP2) - -# build rules -ipset.lo ipset.o: $(srcdir)/ipset/ipset.c - -# Dependencies -dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ - $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/validator/val_nsec.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h $(srcdir)/services/cache/dns.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h -infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/services/cache/infra.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h -rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/regional.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h -as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h -dname.lo dname.o: $(srcdir)/util/data/dname.c config.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/storage/lookup3.h $(srcdir)/sldns/sbuffer.h -msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/util/data/msgencode.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h $(srcdir)/services/view.h -msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h -msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/module.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/respip/respip.h -packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h -iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/iterator/iter_utils.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_donotq.h \ - $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_scrub.h $(srcdir)/iterator/iter_priv.h \ - $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \ - $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \ - $(srcdir)/util/random.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h -iter_delegpt.lo iter_delegpt.o: $(srcdir)/iterator/iter_delegpt.c config.h $(srcdir)/iterator/iter_delegpt.h \ - $(srcdir)/util/log.h $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h -iter_donotq.lo iter_donotq.o: $(srcdir)/iterator/iter_donotq.c config.h $(srcdir)/iterator/iter_donotq.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h -iter_fwd.lo iter_fwd.o: $(srcdir)/iterator/iter_fwd.c config.h $(srcdir)/iterator/iter_fwd.h \ - $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h -iter_hints.lo iter_hints.o: $(srcdir)/iterator/iter_hints.c config.h $(srcdir)/iterator/iter_hints.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/sldns/wire2str.h -iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h $(srcdir)/iterator/iter_priv.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h -iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h -iter_scrub.lo iter_scrub.o: $(srcdir)/iterator/iter_scrub.c config.h $(srcdir)/iterator/iter_scrub.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/iterator/iter_priv.h $(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/alloc.h $(srcdir)/sldns/sbuffer.h -iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/iterator/iter_utils.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/iterator/iter_hints.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_fwd.h \ - $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_priv.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outside_network.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/sldns/str2wire.h -listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \ - $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h -localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/as112.h -mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/alloc.h \ - $(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h $(srcdir)/services/listen_dnsport.h -modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h -view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h -rpz.lo rpz.o: $(srcdir)/services/rpz.c config.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h \ - $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h -outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - -outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c config.h \ - $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/edns.h $(srcdir)/dnstap/dnstap.h -alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/regional.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/util/log.h \ - $(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/util/iana_ports.inc -configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \ - $(srcdir)/util/config_file.h util/configparser.h -configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/configyyrename.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/sldns/rrdef.h -shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/util/shm_side/shm_main.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ - $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h \ - $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \ - $(srcdir)/util/rtt.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/tube.h $(srcdir)/util/timeval_func.h -authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/outside_network.h \ - $(srcdir)/services/listen_dnsport.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/keyraw.h $(srcdir)/validator/val_nsec3.h \ - $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/val_sigcrypt.h \ - $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_utils.h -fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/outside_network.h $(srcdir)/services/cache/infra.h \ - $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \ - $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \ - $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \ - $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \ - $(srcdir)/libunbound/worker.h -locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h -log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h -mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h -netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/ub_event.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/timeval_func.h -proxy_protocol.lo proxy_protocol.o: $(srcdir)/util/proxy_protocol.c config.h \ - $(srcdir)/util/proxy_protocol.h $(srcdir)/sldns/sbuffer.h -net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \ - $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h -random.lo random.o: $(srcdir)/util/random.c config.h $(srcdir)/util/random.h $(srcdir)/util/log.h -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h $(srcdir)/util/regional.h -rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h -siphash.lo siphash.o: $(srcdir)/util/siphash.c -rfc_1982.lo rfc_1982.o: $(srcdir)/util/rfc_1982.c -edns.lo edns.o: $(srcdir)/util/edns.c config.h $(srcdir)/util/edns.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/regional.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h -dnstree.lo dnstree.o: $(srcdir)/util/storage/dnstree.c config.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/net_help.h -lookup3.lo lookup3.o: $(srcdir)/util/storage/lookup3.c config.h $(srcdir)/util/storage/lookup3.h -lruhash.lo lruhash.o: $(srcdir)/util/storage/lruhash.c config.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -slabhash.lo slabhash.o: $(srcdir)/util/storage/slabhash.c config.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h -tcp_conn_limit.lo tcp_conn_limit.o: $(srcdir)/util/tcp_conn_limit.c config.h $(srcdir)/util/regional.h \ - $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/tcp_conn_limit.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h -timehist.lo timehist.o: $(srcdir)/util/timehist.c config.h $(srcdir)/util/timehist.h $(srcdir)/util/log.h -tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/ub_event.h -ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h -ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \ - $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h -winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h -autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/services/mesh.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/respip/respip.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/validator/val_kcache.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h -val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/validator/autotrust.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/as112.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/sldns/str2wire.h -validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.h \ - $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_kcache.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_nsec.h \ - $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_neg.h $(srcdir)/validator/val_sigcrypt.h \ - $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/respip/respip.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h -val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h -val_kentry.lo val_kentry.o: $(srcdir)/validator/val_kentry.c config.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h -val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h -val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/validator/val_nsec3.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/validator.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h $(srcdir)/sldns/sbuffer.h -val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h $(srcdir)/validator/val_nsec.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h -val_secalgo.lo val_secalgo.o: $(srcdir)/validator/val_secalgo.c config.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h \ - $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \ - $(srcdir)/sldns/sbuffer.h -val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \ - $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/val_secalgo.h \ - $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/rbtree.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ - $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h \ - $(srcdir)/sldns/wire2str.h -val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \ - $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/parseutil.h -dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(srcdir)/util/module.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/str2wire.h -edns-subnet.lo edns-subnet.o: $(srcdir)/edns-subnet/edns-subnet.c config.h -subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h -addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/util/log.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/edns-subnet/addrtree.h -subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c config.h -respip.lo respip.o: $(srcdir)/respip/respip.c config.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/modstack.h \ - $(srcdir)/services/rpz.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/services/cache/dns.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/regional.h -checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/testcode/checklocks.h -ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h -ipsecmod-whitelist.lo ipsecmod-whitelist.o: $(srcdir)/ipsecmod/ipsecmod-whitelist.c config.h -unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h -unitdname.lo unitdname.o: $(srcdir)/testcode/unitdname.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h -unitlruhash.lo unitlruhash.o: $(srcdir)/testcode/unitlruhash.c config.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h -unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \ - $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/util/timehist.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/libunbound/unbound.h $(srcdir)/services/cache/infra.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/random.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/services/outside_network.h -unitmsgparse.lo unitmsgparse.o: $(srcdir)/testcode/unitmsgparse.c config.h $(srcdir)/util/log.h \ - $(srcdir)/testcode/unitmain.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/testcode/readhex.h \ - $(srcdir)/testcode/testpkts.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h -unitneg.lo unitneg.o: $(srcdir)/testcode/unitneg.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/dname.h $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h \ - $(srcdir)/sldns/rrdef.h -unitregional.lo unitregional.o: $(srcdir)/testcode/unitregional.c config.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/util/log.h $(srcdir)/util/regional.h -unitslabhash.lo unitslabhash.o: $(srcdir)/testcode/unitslabhash.c config.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h -unitverify.lo unitverify.o: $(srcdir)/testcode/unitverify.c config.h $(srcdir)/util/log.h \ - $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_nsec3.h \ - $(srcdir)/util/rbtree.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/testcode/testpkts.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/keyraw.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h -readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h $(srcdir)/util/log.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h -testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h -unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/parseutil.h -unitecs.lo unitecs.o: $(srcdir)/testcode/unitecs.c config.h -unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/services/authzone.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/testcode/unitmain.h \ - $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/sldns/wire2str.h -unitzonemd.lo unitzonemd.o: $(srcdir)/testcode/unitzonemd.c config.h $(srcdir)/util/log.h \ - $(srcdir)/testcode/unitmain.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/authzone.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h \ - $(srcdir)/validator/val_anchor.h -unittcpreuse.lo unittcpreuse.o: $(srcdir)/testcode/unittcpreuse.c config.h $(srcdir)/services/outside_network.h \ -$(srcdir)/util/random.h -acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h -cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \ - $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \ - $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \ - $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/config_file.h $(srcdir)/services/outside_network.h -daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ - $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \ - $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \ - $(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \ - $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h -remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \ - $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/alloc.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ - $(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h \ - $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \ - $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \ - $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \ - $(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \ - $(srcdir)/sldns/wire2str.h -stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/tube.h \ - $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h -unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \ - $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ - $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/ub_event.h -worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/timeval_func.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ - $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ - $(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/respip/respip.h $(srcdir)/util/data/msgencode.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \ - $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_utils.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/validator/autotrust.h $(srcdir)/validator/val_anchor.h \ - $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/libunbound/libworker.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/dnstap/dtstream.h -testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \ - $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \ - $(srcdir)/daemon/remote.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c $(srcdir)/daemon/daemon.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/timeval_func.h $(srcdir)/services/modstack.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h -testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h -worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/timeval_func.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \ - $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ - $(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/respip/respip.h $(srcdir)/util/data/msgencode.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \ - $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_utils.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/validator/autotrust.h $(srcdir)/validator/val_anchor.h \ - $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/libunbound/libworker.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/dnstap/dtstream.h -acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h -daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ - $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \ - $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \ - $(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \ - $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \ - $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h -stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/tube.h \ - $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h -replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h $(srcdir)/util/timeval_func.h \ - $(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h -fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/testcode/fake_event.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/edns.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \ - $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h $(srcdir)/util/timeval_func.h \ - $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \ - $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h -lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -pktview.lo pktview.o: $(srcdir)/testcode/pktview.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/testcode/unitmain.h $(srcdir)/testcode/readhex.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/sldns/parseutil.h -readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h $(srcdir)/util/log.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h -memstats.lo memstats.o: $(srcdir)/testcode/memstats.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h -unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c config.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ - $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \ - $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h -worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h -context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbound/context.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \ - $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h -libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \ - $(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/libworker.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \ - $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h $(srcdir)/util/edns.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \ - $(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \ - $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h -libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/libunbound/worker.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/services/outside_network.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \ - $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \ - $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \ - $(srcdir)/sldns/str2wire.h -unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h -asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \ - $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h -streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ - $(srcdir)/util/net_help.h $(srcdir)/util/proxy_protocol.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h -perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h -delayer.lo delayer.o: $(srcdir)/testcode/delayer.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h -unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h $(srcdir)/util/log.h \ - $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h $(srcdir)/util/shm_side/shm_main.h \ - $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/services/modstack.h $(srcdir)/respip/respip.h \ - $(srcdir)/services/listen_dnsport.h -unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h -petal.lo petal.o: $(srcdir)/testcode/petal.c config.h -unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnstap-socket.c config.h \ - $(srcdir)/dnstap/dtstream.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/dnstap/dnstap_fstrm.h \ - $(srcdir)/util/ub_event.h $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h \ - $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/config_file.h \ - $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/daemon/worker.h \ - $(srcdir)/libunbound/worker.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \ - $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \ - $(srcdir)/daemon/remote.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \ - $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ - $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \ - $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h $(srcdir)/libunbound/context.h \ - $(srcdir)/libunbound/unbound-event.h -pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c config.h \ - $(srcdir)/pythonmod/pythonmod_utils.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h \ - $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/net_help.h \ - $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ - $(srcdir)/util/regional.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h -win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \ - $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ - $(srcdir)/daemon/worker.h \ - $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ - $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \ - $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h \ - $(srcdir)/util/net_help.h -w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h -unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \ - $(srcdir)/winrc/w_inst.h -unbound-service-remove.lo unbound-service-remove.o: $(srcdir)/winrc/unbound-service-remove.c config.h \ - $(srcdir)/winrc/w_inst.h -anchor-update.lo anchor-update.o: $(srcdir)/winrc/anchor-update.c config.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/wire2str.h -keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/rrdef.h -sbuffer.lo sbuffer.o: $(srcdir)/sldns/sbuffer.c config.h $(srcdir)/sldns/sbuffer.h -wire2str.lo wire2str.o: $(srcdir)/sldns/wire2str.c config.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \ - $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h \ - $(srcdir)/sldns/keyraw.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ - $(srcdir)/util/log.h -parse.lo parse.o: $(srcdir)/sldns/parse.c config.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h \ - $(srcdir)/sldns/sbuffer.h -parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/parseutil.h -rrdef.lo rrdef.o: $(srcdir)/sldns/rrdef.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h -str2wire.lo str2wire.o: $(srcdir)/sldns/str2wire.c config.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h -dohclient.lo dohclient.o: $(srcdir)/testcode/dohclient.c config.h $(srcdir)/sldns/wire2str.h \ - $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h \ - $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ - $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \ - $(srcdir)/sldns/pkthdr.h $(srcdir)/util/net_help.h -readzone.lo readzone.o: $(srcdir)/testcode/readzone.c -ctime_r.lo ctime_r.o: $(srcdir)/compat/ctime_r.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h -fake-rfc2553.lo fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c $(srcdir)/compat/fake-rfc2553.h config.h -gmtime_r.lo gmtime_r.o: $(srcdir)/compat/gmtime_r.c config.h -inet_aton.lo inet_aton.o: $(srcdir)/compat/inet_aton.c config.h -inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h -inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h -malloc.lo malloc.o: $(srcdir)/compat/malloc.c config.h -memcmp.lo memcmp.o: $(srcdir)/compat/memcmp.c config.h -memmove.lo memmove.o: $(srcdir)/compat/memmove.c config.h -snprintf.lo snprintf.o: $(srcdir)/compat/snprintf.c config.h -strlcat.lo strlcat.o: $(srcdir)/compat/strlcat.c config.h -strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h -strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h -getentropy_freebsd.lo getentropy_freebsd.o: $(srcdir)/compat/getentropy_freebsd.c -getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h -getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c -getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h -getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c -explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h -arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h -arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h -arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h $(srcdir)/util/locks.h -sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h -reallocarray.lo reallocarray.o: $(srcdir)/compat/reallocarray.c config.h -isblank.lo isblank.o: $(srcdir)/compat/isblank.c config.h -strsep.lo strsep.o: $(srcdir)/compat/strsep.c config.h diff --git a/crates/libunbound-sys/unbound/README b/crates/libunbound-sys/unbound/README deleted file mode 100644 index 85f91822..00000000 --- a/crates/libunbound-sys/unbound/README +++ /dev/null @@ -1,10 +0,0 @@ -Unbound README -* ./configure && make && make install -* You can use libevent if you want. libevent is useful when using - many (10000) outgoing ports. By default max 256 ports are opened at - the same time and the builtin alternative is equally capable and a - little faster. -* More detailed README, README.svn, README.tests in doc directory -* manual pages can be found in doc directory, and are installed, unbound(8). -* example configuration file doc/example.conf - diff --git a/crates/libunbound-sys/unbound/README-Travis.md b/crates/libunbound-sys/unbound/README-Travis.md deleted file mode 100644 index ca644561..00000000 --- a/crates/libunbound-sys/unbound/README-Travis.md +++ /dev/null @@ -1,278 +0,0 @@ -# Travis Testing - -Unbound 1.10 and above leverage Travis CI to increase coverage of compilers and platforms. Compilers include Clang and GCC; while platforms include Android, iOS, Linux, and OS X on AMD64, Aarch64, PowerPC and s390x hardware. - -Android is tested on armv7a, aarch64, x86 and x86_64. The Android recipes build and install OpenSSL and Expat, and then builds Unbound. The testing is tailored for Android NDK-r19 and above, and includes NDK-r20 and NDK-r21. Mips and Mips64 are not tested because they are no longer supported under current NDKs. - -iOS is tested for iPhoneOS, WatchOS, AppleTVOS, iPhoneSimulator, AppleTVSimulator and WatchSimulator. The testing uses Xcode 10 on OS X 10.13. - -The Unbound Travis configuration file `.travis.yml` does not use top-level keys like `os:` and `compiler:` so there is no matrix expansion. Instead Unbound specifies the exact job to run under the `jobs:` and `include:` keys. - -## Typical recipe - -A typical recipe tests Clang and GCC on various hardware. The hardware includes AMD64, Aarch64, PowerPC and s390x. PowerPC is a little-endian platform, and s390x is a big-endian platform. There are pairs of recipes that are similar to the following. - -``` -- os: linux - name: GCC on Linux, Aarch64 - compiler: gcc - arch: arm64 - dist: bionic -- os: linux - name: Clang on Linux, Aarch64 - compiler: clang - arch: arm64 - dist: bionic -``` - -OS X provides a single recipe to test Clang. GCC is not tested because GCC is an alias for Clang. - -## Sanitizer builds - -Two sanitizer builds are tested using Clang and GCC, for a total of four builds. The first sanitizer is Undefined Behavior sanitizer (UBsan), and the second is Address sanitizer (Asan). The sanitizers are only run on AMD64 hardware. Note the environment includes `TEST_UBSAN=yes` or `TEST_ASAN=yes` for the sanitizer builds. - -The recipes are similar to the following. - -``` -- os: linux - name: UBsan, GCC on Linux, Amd64 - compiler: gcc - arch: amd64 - dist: bionic - env: TEST_UBSAN=yes -- os: linux - name: UBsan, Clang on Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: TEST_UBSAN=yes -``` - -When the Travis script encounters a sanitizer it uses different `CFLAGS` and configuration string. - -``` -if [ "$TEST_UBSAN" = "yes" ]; then - export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover" - ./configure - make -j 2 - make test -elif [ "$TEST_ASAN" = "yes" ]; then - export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" - ./configure - make -j 2 - make test -... -``` - -## Android builds - -Travis tests Android builds for the armv7a, aarch64, x86 and x86_64 architectures. The builds are trickier than other builds for several reasons. The testing requires installation of the Android NDK and SDK, it requires a cross-compile, and requires OpenSSL and Expat prerequisites. The Android cross-compiles also require care to set the Autotools triplet, the OpenSSL triplet, the toolchain path, the tool variables, and the sysroot. The discussion below detail the steps of the Android recipes. - -### Android job - -The first step sets environmental variables for the cross-compile using the Travis job. A typical job with variables is shown below. - -``` -- os: linux - name: Android armv7a, Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ANDROID=yes - - AUTOTOOLS_HOST=armv7a-linux-androideabi - - OPENSSL_HOST=android-arm - - ANDROID_CPU=armv7a - - ANDROID_API=23 - - ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - - ANDROID_SDK_ROOT="$HOME/android-sdk" - - ANDROID_NDK_ROOT="$HOME/android-ndk" -``` - -### ANDROID_NDK_ROOT - -The second step for Android is to set the environmental variables `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT`. This is an important step because the NDK and SDK use the variables internally to locate their own tools. Also see [Recommended NDK Directory?](https://groups.google.com/forum/#!topic/android-ndk/qZjhOaynHXc) on the android-ndk mailing list. (Many folks miss this step, or use incorrect variables like `ANDROID_NDK_HOME` or `ANDROID_SDK_HOME`). - -If you are working from a developer machine you probably already have the necessary tools installed. You should ensure `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT` are set properly. - -### Tool installation - -The second step installs tools needed for OpenSSL, Expat and Unbound. This step is handled in by the script `contrib/android/install_tools.sh`. The tools include curl, tar, zip, unzip and java. - -``` -before_script: - - | - if [ "$TEST_ANDROID" = "yes" ]; then - ./contrib/android/install_tools.sh - elif [ "$TEST_IOS" = "yes" ]; then - ./contrib/ios/install_tools.sh - fi -``` - -### NDK installation - -The third step installs the NDK and SDK. This step is handled in by the script `contrib/android/install_ndk.sh`. The script uses `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT` to place the NDK and SDK in the `$HOME` directory. - -If you are working from a developer machine you probably already have a NDK and SDK installed. - -### Android environment - -The fourth step sets the Android cross-compile environment using the script `contrib/android/setenv_android.sh`. The script is `sourced` so the variables in the script are available to the calling shell. The script sets variables like `CC`, `CXX`, `AS` and `AR`; sets `CFLAGS` and `CXXFLAGS`; sets a `sysroot` so Android headers and libraries are found; and adds the path to the toolchain to `PATH`. - -`contrib/android/setenv_android.sh` knows which toolchain and architecture to select by inspecting environmental variables set by Travis for the job. In particular, the variables `ANDROID_CPU` and `ANDROID_API` tell `contrib/android/setenv_android.sh` which tools and libraries to select. - -The `contrib/android/setenv_android.sh` script specifies the tools in a `case` statement like the following. There is a case for each of the architectures armv7a, aarch64, x86 and x86_64. - -``` -armv8a|aarch64|arm64|arm64-v8a) - CC="aarch64-linux-android$ANDROID_API-clang" - CXX="aarch64-linux-android$ANDROID_API-clang++" - LD="aarch64-linux-android-ld" - AS="aarch64-linux-android-as" - AR="aarch64-linux-android-ar" - RANLIB="aarch64-linux-android-ranlib" - STRIP="aarch64-linux-android-strip" - - CFLAGS="-funwind-tables -fexceptions" - CXXFLAGS="-funwind-tables -fexceptions -frtti" -``` - -### OpenSSL and Expat - -The fifth step builds OpenSSL and Expat. OpenSSL and Expat are built for Android using the scripts `contrib/android/install_openssl.sh` and `contrib/android/install_expat.sh`. The scripts download, configure and install the latest release version of the libraries. The libraries are configured with `--prefix="$ANDROID_PREFIX"` so the headers are placed in `$ANDROID_PREFIX/include` directory, and the libraries are placed in the `$ANDROID_PREFIX/lib` directory. - -`ANDROID_PREFIX` is the value `$HOME/android$ANDROID_API-$ANDROID_CPU`. The libraries will be installed in `$HOME/android23-armv7a`, `$HOME/android23-aarch64`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported. `PKG_CONFIG_PATH` is the userland equivalent to sysroot, and allows Autotools to find non-system headers and libraries for an architecture. Typical `PKG_CONFIG_PATH` are `$HOME/android23-armv7a/lib/pkgconfig` and `$HOME/android23-aarch64/lib/pkgconfig`. - -OpenSSL also uses a custom configuration file called `15-android.conf`. It is a copy of the OpenSSL's project file and located at `contrib/android/15-android.conf`. The Unbound version is copied to the OpenSSL source files after unpacking the OpenSSL distribution. The Unbound version has legacy NDK support removed and some other fixes, like `ANDROID_NDK_ROOT` awareness. The changes mean Unbound's `15-android.conf` will only work with Unbound, with NDK-r19 and above, and a properly set environment. - -OpenSSL is configured with `no-engine`. If you want to include OpenSSL engines then edit `contrib/android/install_openssl.sh` and remove the config option. - -### Android build - -Finally, once OpenSSL and Expat are built, then the Travis script configures and builds Unbound. The recipe looks as follows. - -``` -elif [ "$TEST_ANDROID" = "yes" ]; then - export AUTOTOOLS_BUILD="$(./config.guess)" - export PKG_CONFIG_PATH="$ANDROID_PREFIX/lib/pkgconfig" - ./contrib/android/install_ndk.sh - source ./contrib/android/setenv_android.sh - ./contrib/android/install_openssl.sh - ./contrib/android/install_expat.sh - ./configure \ - --build="$AUTOTOOLS_BUILD" \ - --host="$AUTOTOOLS_HOST" \ - --prefix="$ANDROID_PREFIX" \ - --with-ssl="$ANDROID_PREFIX" \ - --with-libexpat="$ANDROID_PREFIX" \ - --disable-gost; - make -j 2 - make install -``` - -Travis only smoke tests an Android build using a compile, link and install. The self tests are not run. TODO: figure out how to fire up an emulator, push the tests to the device and run them. - -### Android flags - -`contrib/android/setenv_android.sh` uses specific flags for `CFLAGS` and `CXXFLAGS`. They are taken from `ndk-build`, so we consider them the official flag set. It is important to use the same flags across projects to avoid subtle problems due to mixing and matching different flags. - -`CXXFLAGS` includes `-fexceptions` and `-frtti` because exceptions and runtime type info are disabled by default. `CFLAGS` include `-funwind-tables` and `-fexceptions` to ensure C++ exceptions pass through C code, if needed. Also see `docs/CPLUSPLUS-SUPPORT.html` in the NDK docs. - -To inspect the flags used by `ndk-build` for a platform clone ASOP's [ndk-samples](https://github.com/android/ndk-samples/tree/master/hello-jni) and build the `hello-jni` project. Use the `V=1` flag to see the full compiler output from `ndk-build`. - -## iOS builds - -Travis tests iOS builds for the armv7a, armv7s and aarch64 architectures for iPhoneOS, AppleTVOS and WatchOS. iPhoneOS is tested using both 32-bit builds (iPhones) and 64-bit builds (iPads). Travis also tests compiles against the simulators. The builds are trickier than other builds for several reasons. The testing requires a cross-compile, and requires OpenSSL and Expat prerequisites. The iOS cross-compiles also require care to set the Autotools triplet, the OpenSSL triplet, the toolchain path, the tool variables, and the sysroot. The discussion below detail the steps of the iOS recipes. - -### iOS job - -The first step sets environmental variables for the cross-compile using the Travis job. A typical job with variables is shown below. - -``` -- os: osx - osx_image: xcode10 - name: Apple iPhone on iOS, armv7 - compiler: clang - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=armv7-apple-ios - - OPENSSL_HOST=ios-cross - - IOS_SDK=iPhoneOS - - IOS_CPU=armv7s - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" -``` - -### Tool installation - -The second step installs tools needed for OpenSSL, Expat and Unbound. This step is handled in by the script `contrib/ios/install_tools.sh`. The tools include autotools, curl and perl. The installation happens at the `before_script:` stage of Travis. - -``` -before_script: - - | - if [ "$TEST_ANDROID" = "yes" ]; then - ./contrib/android/install_tools.sh - elif [ "$TEST_IOS" = "yes" ]; then - ./contrib/ios/install_tools.sh - fi -``` - -### iOS environment - -The third step sets the iOS cross-compile environment using the script `contrib/ios/setenv_ios.sh`. The script is `sourced` so the variables in the script are available to the calling shell. The script sets variables like `CC`, `CXX`, `AS` and `AR`; sets `CFLAGS` and `CXXFLAGS`; sets a `sysroot` so iOS headers and libraries are found; and adds the path to the toolchain to `PATH`. - -`contrib/ios/setenv_ios.sh` knows which toolchain and architecture to select by inspecting environmental variables set by Travis for the job. In particular, the variables `IOS_SDK` and `IOS_CPU` tell `contrib/ios/setenv_ios.sh` which tools and libraries to select. - -The `contrib/ios/setenv_ios.sh` script specifies the tools to use during the cross-compile. For Apple SDKs, the tool names are the same as a desktop. There are no special prefixes for the mobile tools. - -``` -CPP=cpp -CC=clang -CXX=clang++ -LD=ld -AS=as -AR=ar -RANLIB=ranlib -STRIP=strip -``` - -If you are working from a developer machine you probably already have the necessary tools installed. - -### OpenSSL and Expat - -The fourth step builds OpenSSL and Expat. OpenSSL and Expat are built for iOS using the scripts `contrib/ios/install_openssl.sh` and `contrib/ios/install_expat.sh`. The scripts download, configure and install the latest release version of the libraries. The libraries are configured with `--prefix="$IOS_PREFIX"` so the headers are placed in `$IOS_PREFIX/include` directory, and the libraries are placed in the `$IOS_PREFIX/lib` directory. - -`IOS_PREFIX` is the value `$HOME/$IOS_SDK-$IOS_CPU`. The scheme handles both iOS SDKs and cpu architectures so the pair receives a unique installation directory. The libraries will be installed in `$HOME/iPhoneOS-armv7s`, `$HOME/iPhoneOS-arm64`, `$HOME/iPhoneSimulator-i386`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported. - -`PKG_CONFIG_PATH` is an important variable. It is the userland equivalent to sysroot, and allows Autotools to find non-system headers and libraries for an architecture. Typical `PKG_CONFIG_PATH` are `$HOME/iPhoneOS-armv7s/lib/pkgconfig` and `$HOME/iPhoneOS-arm64/lib/pkgconfig`. - -OpenSSL also uses a custom configuration file called `15-ios.conf`. It is a copy of the OpenSSL's project file and located at `contrib/ios/15-ios.conf`. The Unbound version is copied to the OpenSSL source files after unpacking the OpenSSL distribution. The changes mean Unbound's `15-ios.conf` will only work with Unbound and a properly set environment. - -OpenSSL is configured with `no-engine`. Engines require dynamic loading so engines are disabled permanently in `15-ios.conf`. - -### iOS build - -Finally, once OpenSSL and Expat are built, then the Travis script configures and builds Unbound. The full recipe looks as follows. - -``` -elif [ "$TEST_IOS" = "yes" ]; then - export AUTOTOOLS_BUILD="$(./config.guess)" - export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig" - source ./contrib/ios/setenv_ios.sh - ./contrib/ios/install_openssl.sh - ./contrib/ios/install_expat.sh - ./configure \ - --build="$AUTOTOOLS_BUILD" \ - --host="$AUTOTOOLS_HOST" \ - --prefix="$IOS_PREFIX" \ - --with-ssl="$IOS_PREFIX" \ - --with-libexpat="$IOS_PREFIX" \ - --disable-gost; - make -j 2 - make install -``` - -Travis only smoke tests an iOS build using a compile, link and install. The self tests are not run. TODO: figure out how to fire up an simulator, push the tests to the device and run them. - -### iOS flags - -`contrib/ios/setenv_ios.sh` uses specific flags for `CFLAGS` and `CXXFLAGS`. They are taken from Xcode, so we consider them the official flag set. It is important to use the same flags across projects to avoid subtle problems due to mixing and matching different flags. diff --git a/crates/libunbound-sys/unbound/README.md b/crates/libunbound-sys/unbound/README.md deleted file mode 100644 index c220da03..00000000 --- a/crates/libunbound-sys/unbound/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Unbound - -[![Github Build Status](https://github.com/NLnetLabs/unbound/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/NLnetLabs/unbound/actions) -[![Packaging status](https://repology.org/badge/tiny-repos/unbound.svg)](https://repology.org/project/unbound/versions) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/unbound.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound) -[![Documentation Status](https://readthedocs.org/projects/unbound/badge/?version=latest)](https://unbound.readthedocs.io/en/latest/?badge=latest) -[![Mastodon Follow](https://img.shields.io/mastodon/follow/109262826617293067?domain=https%3A%2F%2Ffosstodon.org&style=social)](https://fosstodon.org/@nlnetlabs) - -Unbound is a validating, recursive, caching DNS resolver. It is designed to be -fast and lean and incorporates modern features based on open standards. If you -have any feedback, we would love to hear from you. Don’t hesitate to -[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new) -or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users). -You can learn more about Unbound by reading our -[documentation](https://unbound.docs.nlnetlabs.nl/). - -## Compiling - -Make sure you have the C toolchain, OpenSSL and its include files, and libexpat -installed. Unbound can be compiled and installed using: - -``` -./configure && make && make install -``` - -You can use libevent if you want. libevent is useful when using many (10000) -outgoing ports. By default max 256 ports are opened at the same time and the -builtin alternative is equally capable and a little faster. - -Use the `--with-libevent=dir` configure option to compile Unbound with libevent -support. - -## Unbound configuration - -All of Unbound's configuration options are described in the man pages, which -will be installed and are available on the Unbound -[documentation page](https://unbound.docs.nlnetlabs.nl/). - -An example configuration file is located in -[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in). diff --git a/crates/libunbound-sys/unbound/SECURITY.md b/crates/libunbound-sys/unbound/SECURITY.md deleted file mode 100644 index 5770ccd7..00000000 --- a/crates/libunbound-sys/unbound/SECURITY.md +++ /dev/null @@ -1,31 +0,0 @@ -# Security Policy - -## Supported Versions - -NLnet Labs adheres to the straightforward, semantic versioning scheme that is -commonly used in the software industry. - -Support is provided in respect of the latest release, i.e. releases with the -highest minor and patch version level. We do not backport security fixes to -older (minor) versions. In the event a new major version is released (e.g. from -3.2.18 to 4.0.0), support will also be provided on the latest minor version of -the previous major version (3.2.18) for a period of one year from the release of -the new major version (4.0.0). - -In the event that, during this period, a new patch or minor version of the -previous major version is released, then support on these versions will only be -provided for the remainder of the one-year-period. - -You can find detailed information on our software support policy here: - -https://www.nlnetlabs.nl/support/software-support-policy/ - -## Reporting a Vulnerability - -We take security very seriously. If you have discovered a security vulnerability -in one of our projects and you would like to report it to us, you can send an -encrypted message to our Security Entry Point. - -Details are described here: - -https://www.nlnetlabs.nl/security-report/ diff --git a/crates/libunbound-sys/unbound/cachedb/cachedb.c b/crates/libunbound-sys/unbound/cachedb/cachedb.c deleted file mode 100644 index 30645268..00000000 --- a/crates/libunbound-sys/unbound/cachedb/cachedb.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * cachedb/cachedb.c - cache from a database external to the program module - * - * Copyright (c) 2016, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that uses an external database to cache - * dns responses. - */ - -#include "config.h" -#ifdef USE_CACHEDB -#include "cachedb/cachedb.h" -#include "cachedb/redis.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "util/data/msgreply.h" -#include "util/data/msgencode.h" -#include "services/cache/dns.h" -#include "validator/val_neg.h" -#include "validator/val_secalgo.h" -#include "iterator/iter_utils.h" -#include "sldns/parseutil.h" -#include "sldns/wire2str.h" -#include "sldns/sbuffer.h" - -/* header file for htobe64 */ -#ifdef HAVE_ENDIAN_H -# include -#endif -#ifdef HAVE_SYS_ENDIAN_H -# include -#endif - -#ifndef HAVE_HTOBE64 -# ifdef HAVE_LIBKERN_OSBYTEORDER_H - /* In practice this is specific to MacOS X. We assume it doesn't have - * htobe64/be64toh but has alternatives with a different name. */ -# include -# define htobe64(x) OSSwapHostToBigInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) -# else - /* not OSX */ - /* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */ -# if __BIG_ENDIAN__ -# define be64toh(n) (n) -# define htobe64(n) (n) -# else -# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32)) -# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32)) -# endif /* _ENDIAN */ -# endif /* HAVE_LIBKERN_OSBYTEORDER_H */ -#endif /* HAVE_BE64TOH */ - -/** the unit test testframe for cachedb, its module state contains - * a cache for a couple queries (in memory). */ -struct testframe_moddata { - /** lock for mutex */ - lock_basic_type lock; - /** key for single stored data element, NULL if none */ - char* stored_key; - /** data for single stored data element, NULL if none */ - uint8_t* stored_data; - /** length of stored data */ - size_t stored_datalen; -}; - -static int -testframe_init(struct module_env* env, struct cachedb_env* cachedb_env) -{ - struct testframe_moddata* d; - verbose(VERB_ALGO, "testframe_init"); - d = (struct testframe_moddata*)calloc(1, - sizeof(struct testframe_moddata)); - cachedb_env->backend_data = (void*)d; - if(!cachedb_env->backend_data) { - log_err("out of memory"); - return 0; - } - /* Register an EDNS option (65534) to bypass the worker cache lookup - * for testing */ - if(!edns_register_option(LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST, - 1 /* bypass cache */, - 0 /* no aggregation */, env)) { - log_err("testframe_init, could not register test opcode"); - free(d); - return 0; - } - lock_basic_init(&d->lock); - lock_protect(&d->lock, d, sizeof(*d)); - return 1; -} - -static void -testframe_deinit(struct module_env* env, struct cachedb_env* cachedb_env) -{ - struct testframe_moddata* d = (struct testframe_moddata*) - cachedb_env->backend_data; - (void)env; - verbose(VERB_ALGO, "testframe_deinit"); - if(!d) - return; - lock_basic_destroy(&d->lock); - free(d->stored_key); - free(d->stored_data); - free(d); -} - -static int -testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env, - char* key, struct sldns_buffer* result_buffer) -{ - struct testframe_moddata* d = (struct testframe_moddata*) - cachedb_env->backend_data; - (void)env; - verbose(VERB_ALGO, "testframe_lookup of %s", key); - lock_basic_lock(&d->lock); - if(d->stored_key && strcmp(d->stored_key, key) == 0) { - if(d->stored_datalen > sldns_buffer_capacity(result_buffer)) { - lock_basic_unlock(&d->lock); - return 0; /* too large */ - } - verbose(VERB_ALGO, "testframe_lookup found %d bytes", - (int)d->stored_datalen); - sldns_buffer_clear(result_buffer); - sldns_buffer_write(result_buffer, d->stored_data, - d->stored_datalen); - sldns_buffer_flip(result_buffer); - lock_basic_unlock(&d->lock); - return 1; - } - lock_basic_unlock(&d->lock); - return 0; -} - -static void -testframe_store(struct module_env* env, struct cachedb_env* cachedb_env, - char* key, uint8_t* data, size_t data_len, time_t ATTR_UNUSED(ttl)) -{ - struct testframe_moddata* d = (struct testframe_moddata*) - cachedb_env->backend_data; - (void)env; - lock_basic_lock(&d->lock); - verbose(VERB_ALGO, "testframe_store %s (%d bytes)", key, (int)data_len); - - /* free old data element (if any) */ - free(d->stored_key); - d->stored_key = NULL; - free(d->stored_data); - d->stored_data = NULL; - d->stored_datalen = 0; - - d->stored_data = memdup(data, data_len); - if(!d->stored_data) { - lock_basic_unlock(&d->lock); - log_err("out of memory"); - return; - } - d->stored_datalen = data_len; - d->stored_key = strdup(key); - if(!d->stored_key) { - free(d->stored_data); - d->stored_data = NULL; - d->stored_datalen = 0; - lock_basic_unlock(&d->lock); - return; - } - lock_basic_unlock(&d->lock); - /* (key,data) successfully stored */ -} - -/** The testframe backend is for unit tests */ -static struct cachedb_backend testframe_backend = { "testframe", - testframe_init, testframe_deinit, testframe_lookup, testframe_store -}; - -/** find a particular backend from possible backends */ -static struct cachedb_backend* -cachedb_find_backend(const char* str) -{ -#ifdef USE_REDIS - if(strcmp(str, redis_backend.name) == 0) - return &redis_backend; -#endif - if(strcmp(str, testframe_backend.name) == 0) - return &testframe_backend; - /* TODO add more backends here */ - return NULL; -} - -/** apply configuration to cachedb module 'global' state */ -static int -cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg) -{ - const char* backend_str = cfg->cachedb_backend; - if(!backend_str || *backend_str==0) - return 1; - cachedb_env->backend = cachedb_find_backend(backend_str); - if(!cachedb_env->backend) { - log_err("cachedb: cannot find backend name '%s'", backend_str); - return 0; - } - - /* TODO see if more configuration needs to be applied or not */ - return 1; -} - -int -cachedb_init(struct module_env* env, int id) -{ - struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1, - sizeof(struct cachedb_env)); - if(!cachedb_env) { - log_err("malloc failure"); - return 0; - } - env->modinfo[id] = (void*)cachedb_env; - if(!cachedb_apply_cfg(cachedb_env, env->cfg)) { - log_err("cachedb: could not apply configuration settings."); - free(cachedb_env); - env->modinfo[id] = NULL; - return 0; - } - /* see if a backend is selected */ - if(!cachedb_env->backend || !cachedb_env->backend->name) - return 1; - if(!(*cachedb_env->backend->init)(env, cachedb_env)) { - log_err("cachedb: could not init %s backend", - cachedb_env->backend->name); - free(cachedb_env); - env->modinfo[id] = NULL; - return 0; - } - cachedb_env->enabled = 1; - if(env->cfg->serve_expired_reply_ttl) - log_warn( - "cachedb: serve-expired-reply-ttl is set but not working for data " - "originating from the external cache; 0 TLL is used for those."); - if(env->cfg->serve_expired_client_timeout) - log_warn( - "cachedb: serve-expired-client-timeout is set but not working for " - "data originating from the external cache; expired data are used " - "in the reply without first trying to refresh the data."); - return 1; -} - -void -cachedb_deinit(struct module_env* env, int id) -{ - struct cachedb_env* cachedb_env; - if(!env || !env->modinfo[id]) - return; - cachedb_env = (struct cachedb_env*)env->modinfo[id]; - if(cachedb_env->enabled) { - (*cachedb_env->backend->deinit)(env, cachedb_env); - } - free(cachedb_env); - env->modinfo[id] = NULL; -} - -/** new query for cachedb */ -static int -cachedb_new(struct module_qstate* qstate, int id) -{ - struct cachedb_qstate* iq = (struct cachedb_qstate*)regional_alloc( - qstate->region, sizeof(struct cachedb_qstate)); - qstate->minfo[id] = iq; - if(!iq) - return 0; - memset(iq, 0, sizeof(*iq)); - /* initialise it */ - /* TODO */ - - return 1; -} - -/** - * Return an error - * @param qstate: our query state - * @param id: module id - * @param rcode: error code (DNS errcode). - * @return: 0 for use by caller, to make notation easy, like: - * return error_response(..). - */ -static int -error_response(struct module_qstate* qstate, int id, int rcode) -{ - verbose(VERB_QUERY, "return error response %s", - sldns_lookup_by_id(sldns_rcodes, rcode)? - sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??"); - qstate->return_rcode = rcode; - qstate->return_msg = NULL; - qstate->ext_state[id] = module_finished; - return 0; -} - -/** - * Hash the query name, type, class and dbacess-secret into lookup buffer. - * @param qstate: query state with query info - * and env->cfg with secret. - * @param buf: returned buffer with hash to lookup - * @param len: length of the buffer. - */ -static void -calc_hash(struct module_qstate* qstate, char* buf, size_t len) -{ - uint8_t clear[1024]; - size_t clen = 0; - uint8_t hash[CACHEDB_HASHSIZE/8]; - const char* hex = "0123456789ABCDEF"; - const char* secret = qstate->env->cfg->cachedb_secret; - size_t i; - - /* copy the hash info into the clear buffer */ - if(clen + qstate->qinfo.qname_len < sizeof(clear)) { - memmove(clear+clen, qstate->qinfo.qname, - qstate->qinfo.qname_len); - clen += qstate->qinfo.qname_len; - } - if(clen + 4 < sizeof(clear)) { - uint16_t t = htons(qstate->qinfo.qtype); - uint16_t c = htons(qstate->qinfo.qclass); - memmove(clear+clen, &t, 2); - memmove(clear+clen+2, &c, 2); - clen += 4; - } - if(secret && secret[0] && clen + strlen(secret) < sizeof(clear)) { - memmove(clear+clen, secret, strlen(secret)); - clen += strlen(secret); - } - - /* hash the buffer */ - secalgo_hash_sha256(clear, clen, hash); -#ifdef HAVE_EXPLICIT_BZERO - explicit_bzero(clear, clen); -#else - memset(clear, 0, clen); -#endif - - /* hex encode output for portability (some online dbs need - * no nulls, no control characters, and so on) */ - log_assert(len >= sizeof(hash)*2 + 1); - (void)len; - for(i=0; i>4]; - buf[i*2+1] = hex[hash[i]&0x0f]; - } - buf[sizeof(hash)*2] = 0; -} - -/** convert data from return_msg into the data buffer */ -static int -prep_data(struct module_qstate* qstate, struct sldns_buffer* buf) -{ - uint64_t timestamp, expiry; - size_t oldlim; - struct edns_data edns; - memset(&edns, 0, sizeof(edns)); - edns.edns_present = 1; - edns.bits = EDNS_DO; - edns.ext_rcode = 0; - edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.udp_size = EDNS_ADVERTISED_SIZE; - - if(!qstate->return_msg || !qstate->return_msg->rep) - return 0; - /* do not store failures like SERVFAIL in the cachedb, this avoids - * overwriting expired, valid, content with broken content. */ - if(FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != - LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != - LDNS_RCODE_NXDOMAIN && - FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != - LDNS_RCODE_YXDOMAIN) - return 0; - /* We don't store the reply if its TTL is 0 unless serve-expired is - * enabled. Such a reply won't be reusable and simply be a waste for - * the backend. It's also compatible with the default behavior of - * dns_cache_store_msg(). */ - if(qstate->return_msg->rep->ttl == 0 && - !qstate->env->cfg->serve_expired) - return 0; - - /* The EDE is added to the out-list so it is encoded in the cached message */ - if (qstate->env->cfg->ede && qstate->return_msg->rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&edns.opt_list_out, qstate->env->scratch, - qstate->return_msg->rep->reason_bogus, - qstate->return_msg->rep->reason_bogus_str); - } - - if(verbosity >= VERB_ALGO) - log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo, - qstate->return_msg->rep); - if(!reply_info_answer_encode(&qstate->return_msg->qinfo, - qstate->return_msg->rep, 0, qstate->query_flags, - buf, 0, 1, qstate->env->scratch, 65535, &edns, 1, 0)) - return 0; - - /* TTLs in the return_msg are relative to time(0) so we have to - * store that, we also store the smallest ttl in the packet+time(0) - * as the packet expiry time */ - /* qstate->return_msg->rep->ttl contains that relative shortest ttl */ - timestamp = (uint64_t)*qstate->env->now; - expiry = timestamp + (uint64_t)qstate->return_msg->rep->ttl; - timestamp = htobe64(timestamp); - expiry = htobe64(expiry); - oldlim = sldns_buffer_limit(buf); - if(oldlim + sizeof(timestamp)+sizeof(expiry) >= - sldns_buffer_capacity(buf)) - return 0; /* doesn't fit. */ - sldns_buffer_set_limit(buf, oldlim + sizeof(timestamp)+sizeof(expiry)); - sldns_buffer_write_at(buf, oldlim, ×tamp, sizeof(timestamp)); - sldns_buffer_write_at(buf, oldlim+sizeof(timestamp), &expiry, - sizeof(expiry)); - - return 1; -} - -/** check expiry, return true if matches OK */ -static int -good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf) -{ - uint64_t expiry; - /* the expiry time is the last bytes of the buffer */ - if(sldns_buffer_limit(buf) < sizeof(expiry)) - return 0; - sldns_buffer_read_at(buf, sldns_buffer_limit(buf)-sizeof(expiry), - &expiry, sizeof(expiry)); - expiry = be64toh(expiry); - - /* Check if we are allowed to return expired entries: - * - serve_expired needs to be set - * - if SERVE_EXPIRED_TTL is set make sure that the record is not older - * than that. */ - if((time_t)expiry < *qstate->env->now && - (!qstate->env->cfg->serve_expired || - (SERVE_EXPIRED_TTL && - *qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL))) - return 0; - - return 1; -} - -/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is - * negative, set the TTL to 0. */ -static void -packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract) -{ - size_t i; - size_t total = data->count + data->rrsig_count; - if(subtract >= 0 && data->ttl > subtract) - data->ttl -= subtract; - else data->ttl = 0; - for(i=0; i= 0 && data->rr_ttl[i] > subtract) - data->rr_ttl[i] -= subtract; - else data->rr_ttl[i] = 0; - } - data->ttl_add = (subtract < data->ttl_add) ? (data->ttl_add - subtract) : 0; -} - -/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is - * negative, set the TTLs to 0. */ -static void -adjust_msg_ttl(struct dns_msg* msg, time_t adjust) -{ - size_t i; - if(adjust >= 0 && msg->rep->ttl > adjust) - msg->rep->ttl -= adjust; - else - msg->rep->ttl = 0; - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - - for(i=0; irep->rrset_count; i++) { - packed_rrset_ttl_subtract((struct packed_rrset_data*)msg-> - rep->rrsets[i]->entry.data, adjust); - } -} - -/** convert dns message in buffer to return_msg */ -static int -parse_data(struct module_qstate* qstate, struct sldns_buffer* buf) -{ - struct msg_parse* prs; - struct edns_data edns; - struct edns_option* ede; - uint64_t timestamp, expiry; - time_t adjust; - size_t lim = sldns_buffer_limit(buf); - if(lim < LDNS_HEADER_SIZE+sizeof(timestamp)+sizeof(expiry)) - return 0; /* too short */ - - /* remove timestamp and expiry from end */ - sldns_buffer_read_at(buf, lim-sizeof(expiry), &expiry, sizeof(expiry)); - sldns_buffer_read_at(buf, lim-sizeof(expiry)-sizeof(timestamp), - ×tamp, sizeof(timestamp)); - expiry = be64toh(expiry); - timestamp = be64toh(timestamp); - - /* parse DNS packet */ - regional_free_all(qstate->env->scratch); - prs = (struct msg_parse*)regional_alloc(qstate->env->scratch, - sizeof(struct msg_parse)); - if(!prs) - return 0; /* out of memory */ - memset(prs, 0, sizeof(*prs)); - memset(&edns, 0, sizeof(edns)); - sldns_buffer_set_limit(buf, lim - sizeof(expiry)-sizeof(timestamp)); - if(parse_packet(buf, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) { - sldns_buffer_set_limit(buf, lim); - return 0; - } - if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) != - LDNS_RCODE_NOERROR) { - sldns_buffer_set_limit(buf, lim); - return 0; - } - - qstate->return_msg = dns_alloc_msg(buf, prs, qstate->region); - sldns_buffer_set_limit(buf, lim); - if(!qstate->return_msg) - return 0; - - /* We find the EDE in the in-list after parsing */ - if(qstate->env->cfg->ede && - (ede = edns_opt_list_find(edns.opt_list_in, LDNS_EDNS_EDE))) { - if(ede->opt_len >= 2) { - qstate->return_msg->rep->reason_bogus = - sldns_read_uint16(ede->opt_data); - } - /* allocate space and store the error string and it's size */ - if(ede->opt_len > 2) { - size_t ede_len = ede->opt_len - 2; - qstate->return_msg->rep->reason_bogus_str = regional_alloc( - qstate->region, sizeof(char) * (ede_len+1)); - memcpy(qstate->return_msg->rep->reason_bogus_str, - ede->opt_data+2, ede_len); - qstate->return_msg->rep->reason_bogus_str[ede_len] = 0; - } - } - - qstate->return_rcode = LDNS_RCODE_NOERROR; - - /* see how much of the TTL expired, and remove it */ - if(*qstate->env->now <= (time_t)timestamp) { - verbose(VERB_ALGO, "cachedb msg adjust by zero"); - return 1; /* message from the future (clock skew?) */ - } - adjust = *qstate->env->now - (time_t)timestamp; - if(qstate->return_msg->rep->ttl < adjust) { - verbose(VERB_ALGO, "cachedb msg expired"); - /* If serve-expired is enabled, we still use an expired message - * setting the TTL to 0. */ - if(!qstate->env->cfg->serve_expired || - (FLAGS_GET_RCODE(qstate->return_msg->rep->flags) - != LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(qstate->return_msg->rep->flags) - != LDNS_RCODE_NXDOMAIN && - FLAGS_GET_RCODE(qstate->return_msg->rep->flags) - != LDNS_RCODE_YXDOMAIN)) - return 0; /* message expired */ - else - adjust = -1; - } - verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust); - adjust_msg_ttl(qstate->return_msg, adjust); - - /* Similar to the unbound worker, if serve-expired is enabled and - * the msg would be considered to be expired, mark the state so a - * refetch will be scheduled. The comparison between 'expiry' and - * 'now' should be redundant given how these values were calculated, - * but we check it just in case as does good_expiry_and_qinfo(). */ - if(qstate->env->cfg->serve_expired && - (adjust == -1 || (time_t)expiry < *qstate->env->now)) { - qstate->need_refetch = 1; - } - - return 1; -} - -/** - * Lookup the qstate.qinfo in extcache, store in qstate.return_msg. - * return true if lookup was successful. - */ -static int -cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie) -{ - char key[(CACHEDB_HASHSIZE/8)*2+1]; - calc_hash(qstate, key, sizeof(key)); - - /* call backend to fetch data for key into scratch buffer */ - if( !(*ie->backend->lookup)(qstate->env, ie, key, - qstate->env->scratch_buffer)) { - return 0; - } - - /* check expiry date and check if query-data matches */ - if( !good_expiry_and_qinfo(qstate, qstate->env->scratch_buffer) ) { - return 0; - } - - /* parse dns message into return_msg */ - if( !parse_data(qstate, qstate->env->scratch_buffer) ) { - return 0; - } - return 1; -} - -/** - * Store the qstate.return_msg in extcache for key qstate.info - */ -static void -cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie) -{ - char key[(CACHEDB_HASHSIZE/8)*2+1]; - calc_hash(qstate, key, sizeof(key)); - - /* prepare data in scratch buffer */ - if(!prep_data(qstate, qstate->env->scratch_buffer)) - return; - - /* call backend */ - (*ie->backend->store)(qstate->env, ie, key, - sldns_buffer_begin(qstate->env->scratch_buffer), - sldns_buffer_limit(qstate->env->scratch_buffer), - qstate->return_msg->rep->ttl); -} - -/** - * See if unbound's internal cache can answer the query - */ -static int -cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde) -{ - uint8_t* dpname=NULL; - size_t dpnamelen=0; - struct dns_msg* msg; - /* for testframe bypass this lookup */ - if(cde->backend == &testframe_backend) { - return 0; - } - if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, - &dpname, &dpnamelen)) - return 0; /* no cache for these queries */ - msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname, - qstate->qinfo.qname_len, qstate->qinfo.qtype, - qstate->qinfo.qclass, qstate->query_flags, - qstate->region, qstate->env->scratch, - 1, /* no partial messages with only a CNAME */ - dpname, dpnamelen - ); - if(!msg && qstate->env->neg_cache && - iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) { - /* lookup in negative cache; may result in - * NOERROR/NODATA or NXDOMAIN answers that need validation */ - msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo, - qstate->region, qstate->env->rrset_cache, - qstate->env->scratch_buffer, - *qstate->env->now, 1/*add SOA*/, NULL, - qstate->env->cfg); - } - if(!msg) - return 0; - /* this is the returned msg */ - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = msg; - return 1; -} - -/** - * Store query into the internal cache of unbound. - */ -static void -cachedb_intcache_store(struct module_qstate* qstate) -{ - uint32_t store_flags = qstate->query_flags; - - if(qstate->env->cfg->serve_expired) - store_flags |= DNSCACHE_STORE_ZEROTTL; - if(!qstate->return_msg) - return; - (void)dns_cache_store(qstate->env, &qstate->qinfo, - qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0, - qstate->region, store_flags, qstate->qstarttime); -} - -/** - * Handle a cachedb module event with a query - * @param qstate: query state (from the mesh), passed between modules. - * contains qstate->env module environment with global caches and so on. - * @param iq: query state specific for this module. per-query. - * @param ie: environment specific for this module. global. - * @param id: module id. - */ -static void -cachedb_handle_query(struct module_qstate* qstate, - struct cachedb_qstate* ATTR_UNUSED(iq), - struct cachedb_env* ie, int id) -{ - qstate->is_cachedb_answer = 0; - /* check if we are enabled, and skip if so */ - if(!ie->enabled) { - /* pass request to next module */ - qstate->ext_state[id] = module_wait_module; - return; - } - - if(qstate->blacklist || qstate->no_cache_lookup) { - /* cache is blacklisted or we are instructed from edns to not look */ - /* pass request to next module */ - qstate->ext_state[id] = module_wait_module; - return; - } - - /* lookup inside unbound's internal cache. - * This does not look for expired entries. */ - if(cachedb_intcache_lookup(qstate, ie)) { - if(verbosity >= VERB_ALGO) { - if(qstate->return_msg->rep) - log_dns_msg("cachedb internal cache lookup", - &qstate->return_msg->qinfo, - qstate->return_msg->rep); - else log_info("cachedb internal cache lookup: rcode %s", - sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode) - ?sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name - :"??"); - } - /* we are done with the query */ - qstate->ext_state[id] = module_finished; - return; - } - - /* ask backend cache to see if we have data */ - if(cachedb_extcache_lookup(qstate, ie)) { - if(verbosity >= VERB_ALGO) - log_dns_msg(ie->backend->name, - &qstate->return_msg->qinfo, - qstate->return_msg->rep); - /* store this result in internal cache */ - cachedb_intcache_store(qstate); - /* In case we have expired data but there is a client timer for expired - * answers, pass execution to next module in order to try updating the - * data first. - * TODO: this needs revisit. The expired data stored from cachedb has - * 0 TTL which is picked up by iterator later when looking in the cache. - * Document that ext cachedb does not work properly with - * serve_stale_reply_ttl yet. */ - if(qstate->need_refetch && qstate->serve_expired_data && - qstate->serve_expired_data->timer) { - qstate->return_msg = NULL; - qstate->ext_state[id] = module_wait_module; - return; - } - qstate->is_cachedb_answer = 1; - /* we are done with the query */ - qstate->ext_state[id] = module_finished; - return; - } - - /* no cache fetches */ - /* pass request to next module */ - qstate->ext_state[id] = module_wait_module; -} - -/** - * Handle a cachedb module event with a response from the iterator. - * @param qstate: query state (from the mesh), passed between modules. - * contains qstate->env module environment with global caches and so on. - * @param iq: query state specific for this module. per-query. - * @param ie: environment specific for this module. global. - * @param id: module id. - */ -static void -cachedb_handle_response(struct module_qstate* qstate, - struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id) -{ - qstate->is_cachedb_answer = 0; - /* check if we are not enabled or instructed to not cache, and skip */ - if(!ie->enabled || qstate->no_cache_store) { - /* we are done with the query */ - qstate->ext_state[id] = module_finished; - return; - } - - /* store the item into the backend cache */ - cachedb_extcache_store(qstate, ie); - - /* we are done with the query */ - qstate->ext_state[id] = module_finished; -} - -void -cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id]; - struct cachedb_qstate* iq = (struct cachedb_qstate*)qstate->minfo[id]; - verbose(VERB_QUERY, "cachedb[module %d] operate: extstate:%s event:%s", - id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if(iq) log_query_info(VERB_QUERY, "cachedb operate: query", - &qstate->qinfo); - - /* perform cachedb state machine */ - if((event == module_event_new || event == module_event_pass) && - iq == NULL) { - if(!cachedb_new(qstate, id)) { - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - iq = (struct cachedb_qstate*)qstate->minfo[id]; - } - if(iq && (event == module_event_pass || event == module_event_new)) { - cachedb_handle_query(qstate, iq, ie, id); - return; - } - if(iq && (event == module_event_moddone)) { - cachedb_handle_response(qstate, iq, ie, id); - return; - } - if(iq && outbound) { - /* cachedb does not need to process responses at this time - * ignore it. - cachedb_process_response(qstate, iq, ie, id, outbound, event); - */ - return; - } - if(event == module_event_error) { - verbose(VERB_ALGO, "got called with event error, giving up"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - if(!iq && (event == module_event_moddone)) { - /* during priming, module done but we never started */ - qstate->ext_state[id] = module_finished; - return; - } - - log_err("bad event for cachedb"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); -} - -void -cachedb_inform_super(struct module_qstate* ATTR_UNUSED(qstate), - int ATTR_UNUSED(id), struct module_qstate* ATTR_UNUSED(super)) -{ - /* cachedb does not use subordinate requests at this time */ - verbose(VERB_ALGO, "cachedb inform_super was called"); -} - -void -cachedb_clear(struct module_qstate* qstate, int id) -{ - struct cachedb_qstate* iq; - if(!qstate) - return; - iq = (struct cachedb_qstate*)qstate->minfo[id]; - if(iq) { - /* free contents of iq */ - /* TODO */ - } - qstate->minfo[id] = NULL; -} - -size_t -cachedb_get_mem(struct module_env* env, int id) -{ - struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id]; - if(!ie) - return 0; - return sizeof(*ie); /* TODO - more mem */ -} - -/** - * The cachedb function block - */ -static struct module_func_block cachedb_block = { - "cachedb", - &cachedb_init, &cachedb_deinit, &cachedb_operate, - &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem -}; - -struct module_func_block* -cachedb_get_funcblock(void) -{ - return &cachedb_block; -} -#endif /* USE_CACHEDB */ diff --git a/crates/libunbound-sys/unbound/cachedb/cachedb.h b/crates/libunbound-sys/unbound/cachedb/cachedb.h deleted file mode 100644 index 05c4368e..00000000 --- a/crates/libunbound-sys/unbound/cachedb/cachedb.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * cachedb/cachedb.h - cache from a database external to the program module - * - * Copyright (c) 2016, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that uses an external database to cache - * dns responses. - */ -#include "util/module.h" -struct cachedb_backend; - -/** - * The global variable environment contents for the cachedb - * Shared between threads, this represents long term information. - * Like database connections. - */ -struct cachedb_env { - /** true is cachedb is enabled, the backend is turned on */ - int enabled; - - /** the backend routines */ - struct cachedb_backend* backend; - - /** backend specific data here */ - void* backend_data; -}; - -/** - * Per query state for the cachedb module. - */ -struct cachedb_qstate { - int todo; -}; - -/** - * Backend call routines - */ -struct cachedb_backend { - /** backend name */ - const char* name; - - /** Init(env, cachedb_env): false on setup failure */ - int (*init)(struct module_env*, struct cachedb_env*); - - /** Deinit - close db for program exit */ - void (*deinit)(struct module_env*, struct cachedb_env*); - - /** Lookup (env, cachedb_env, key, result_buffer): true if found */ - int (*lookup)(struct module_env*, struct cachedb_env*, char*, - struct sldns_buffer*); - - /** Store (env, cachedb_env, key, data, data_len) */ - void (*store)(struct module_env*, struct cachedb_env*, char*, - uint8_t*, size_t, time_t); -}; - -#define CACHEDB_HASHSIZE 256 /* bit hash */ - -/** Init the cachedb module */ -int cachedb_init(struct module_env* env, int id); -/** Deinit the cachedb module */ -void cachedb_deinit(struct module_env* env, int id); -/** Operate on an event on a query (in qstate). */ -void cachedb_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); -/** Subordinate query done, inform this super request of its conclusion */ -void cachedb_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); -/** clear the cachedb query-specific contents out of qstate */ -void cachedb_clear(struct module_qstate* qstate, int id); -/** return memory estimate for cachedb module */ -size_t cachedb_get_mem(struct module_env* env, int id); - -/** - * Get the function block with pointers to the cachedb functions - * @return the function block for "cachedb". - */ -struct module_func_block* cachedb_get_funcblock(void); - diff --git a/crates/libunbound-sys/unbound/cachedb/redis.c b/crates/libunbound-sys/unbound/cachedb/redis.c deleted file mode 100644 index 93a575a4..00000000 --- a/crates/libunbound-sys/unbound/cachedb/redis.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * cachedb/redis.c - cachedb redis module - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that uses the redis database to cache - * dns responses. - */ - -#include "config.h" -#ifdef USE_CACHEDB -#include "cachedb/redis.h" -#include "cachedb/cachedb.h" -#include "util/alloc.h" -#include "util/config_file.h" -#include "sldns/sbuffer.h" - -#ifdef USE_REDIS -#include "hiredis/hiredis.h" - -struct redis_moddata { - redisContext** ctxs; /* thread-specific redis contexts */ - int numctxs; /* number of ctx entries */ - const char* server_host; /* server's IP address or host name */ - int server_port; /* server's TCP port */ - const char* server_path; /* server's unix path, or "", NULL if unused */ - const char* server_password; /* server's AUTH password, or "", NULL if unused */ - struct timeval timeout; /* timeout for connection setup and commands */ -}; - -static redisReply* redis_command(struct module_env*, struct cachedb_env*, - const char*, const uint8_t*, size_t); - -static redisContext* -redis_connect(const struct redis_moddata* moddata) -{ - redisContext* ctx; - - if(moddata->server_path && moddata->server_path[0]!=0) { - ctx = redisConnectUnixWithTimeout(moddata->server_path, - moddata->timeout); - } else { - ctx = redisConnectWithTimeout(moddata->server_host, - moddata->server_port, moddata->timeout); - } - if(!ctx || ctx->err) { - const char *errstr = "out of memory"; - if(ctx) - errstr = ctx->errstr; - log_err("failed to connect to redis server: %s", errstr); - goto fail; - } - if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) { - log_err("failed to set redis timeout"); - goto fail; - } - if(moddata->server_password && moddata->server_password[0]!=0) { - redisReply* rep; - rep = redisCommand(ctx, "AUTH %s", moddata->server_password); - if(!rep || rep->type == REDIS_REPLY_ERROR) { - log_err("failed to authenticate with password"); - freeReplyObject(rep); - goto fail; - } - freeReplyObject(rep); - } - verbose(VERB_OPS, "Connection to Redis established"); - return ctx; - - fail: - if(ctx) - redisFree(ctx); - return NULL; -} - -static int -redis_init(struct module_env* env, struct cachedb_env* cachedb_env) -{ - int i; - struct redis_moddata* moddata = NULL; - - verbose(VERB_OPS, "Redis initialization"); - - moddata = calloc(1, sizeof(struct redis_moddata)); - if(!moddata) { - log_err("out of memory"); - return 0; - } - moddata->numctxs = env->cfg->num_threads; - moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*)); - if(!moddata->ctxs) { - log_err("out of memory"); - free(moddata); - return 0; - } - /* note: server_host is a shallow reference to configured string. - * we don't have to free it in this module. */ - moddata->server_host = env->cfg->redis_server_host; - moddata->server_port = env->cfg->redis_server_port; - moddata->server_path = env->cfg->redis_server_path; - moddata->server_password = env->cfg->redis_server_password; - moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000; - moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000; - for(i = 0; i < moddata->numctxs; i++) - moddata->ctxs[i] = redis_connect(moddata); - cachedb_env->backend_data = moddata; - if(env->cfg->redis_expire_records) { - redisReply* rep = NULL; - int redis_reply_type = 0; - /** check if setex command is supported */ - rep = redis_command(env, cachedb_env, - "SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0); - if(!rep) { - /** init failed, no response from redis server*/ - log_err("redis_init: failed to init redis, the " - "redis-expire-records option requires the SETEX command " - "(redis >= 2.0.0)"); - return 0; - } - redis_reply_type = rep->type; - freeReplyObject(rep); - switch(redis_reply_type) { - case REDIS_REPLY_STATUS: - break; - default: - /** init failed, setex command not supported */ - log_err("redis_init: failed to init redis, the " - "redis-expire-records option requires the SETEX command " - "(redis >= 2.0.0)"); - return 0; - } - } - - return 1; -} - -static void -redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env) -{ - struct redis_moddata* moddata = (struct redis_moddata*) - cachedb_env->backend_data; - (void)env; - - verbose(VERB_OPS, "Redis deinitialization"); - - if(!moddata) - return; - if(moddata->ctxs) { - int i; - for(i = 0; i < moddata->numctxs; i++) { - if(moddata->ctxs[i]) - redisFree(moddata->ctxs[i]); - } - free(moddata->ctxs); - } - free(moddata); -} - -/* - * Send a redis command and get a reply. Unified so that it can be used for - * both SET and GET. If 'data' is non-NULL the command is supposed to be - * SET and GET otherwise, but the implementation of this function is agnostic - * about the semantics (except for logging): 'command', 'data', and 'data_len' - * are opaquely passed to redisCommand(). - * This function first checks whether a connection with a redis server has - * been established; if not it tries to set up a new one. - * It returns redisReply returned from redisCommand() or NULL if some low - * level error happens. The caller is responsible to check the return value, - * if it's non-NULL, it has to free it with freeReplyObject(). - */ -static redisReply* -redis_command(struct module_env* env, struct cachedb_env* cachedb_env, - const char* command, const uint8_t* data, size_t data_len) -{ - redisContext* ctx; - redisReply* rep; - struct redis_moddata* d = (struct redis_moddata*) - cachedb_env->backend_data; - - /* We assume env->alloc->thread_num is a unique ID for each thread - * in [0, num-of-threads). We could treat it as an error condition - * if the assumption didn't hold, but it seems to be a fundamental - * assumption throughout the unbound architecture, so we simply assert - * it. */ - log_assert(env->alloc->thread_num < d->numctxs); - ctx = d->ctxs[env->alloc->thread_num]; - - /* If we've not established a connection to the server or we've closed - * it on a failure, try to re-establish a new one. Failures will be - * logged in redis_connect(). */ - if(!ctx) { - ctx = redis_connect(d); - d->ctxs[env->alloc->thread_num] = ctx; - } - if(!ctx) - return NULL; - - /* Send the command and get a reply, synchronously. */ - rep = (redisReply*)redisCommand(ctx, command, data, data_len); - if(!rep) { - /* Once an error as a NULL-reply is returned the context cannot - * be reused and we'll need to set up a new connection. */ - log_err("redis_command: failed to receive a reply, " - "closing connection: %s", ctx->errstr); - redisFree(ctx); - d->ctxs[env->alloc->thread_num] = NULL; - return NULL; - } - - /* Check error in reply to unify logging in that case. - * The caller may perform context-dependent checks and logging. */ - if(rep->type == REDIS_REPLY_ERROR) - log_err("redis: %s resulted in an error: %s", - data ? "set" : "get", rep->str); - - return rep; -} - -static int -redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env, - char* key, struct sldns_buffer* result_buffer) -{ - redisReply* rep; - char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */ - int n; - int ret = 0; - - verbose(VERB_ALGO, "redis_lookup of %s", key); - - n = snprintf(cmdbuf, sizeof(cmdbuf), "GET %s", key); - if(n < 0 || n >= (int)sizeof(cmdbuf)) { - log_err("redis_lookup: unexpected failure to build command"); - return 0; - } - - rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0); - if(!rep) - return 0; - switch(rep->type) { - case REDIS_REPLY_NIL: - verbose(VERB_ALGO, "redis_lookup: no data cached"); - break; - case REDIS_REPLY_STRING: - verbose(VERB_ALGO, "redis_lookup found %d bytes", - (int)rep->len); - if((size_t)rep->len > sldns_buffer_capacity(result_buffer)) { - log_err("redis_lookup: replied data too long: %lu", - (size_t)rep->len); - break; - } - sldns_buffer_clear(result_buffer); - sldns_buffer_write(result_buffer, rep->str, rep->len); - sldns_buffer_flip(result_buffer); - ret = 1; - break; - case REDIS_REPLY_ERROR: - break; /* already logged */ - default: - log_err("redis_lookup: unexpected type of reply for (%d)", - rep->type); - break; - } - freeReplyObject(rep); - return ret; -} - -static void -redis_store(struct module_env* env, struct cachedb_env* cachedb_env, - char* key, uint8_t* data, size_t data_len, time_t ttl) -{ - redisReply* rep; - int n; - int set_ttl = (env->cfg->redis_expire_records && - (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0)); - /* Supported commands: - * - "SET " + key + " %b" - * - "SETEX " + key + " " + ttl + " %b" - */ - char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1]; - - if (!set_ttl) { - verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len); - /* build command to set to a binary safe string */ - n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key); - } else { - /* add expired ttl time to redis ttl to avoid premature eviction of key */ - ttl += env->cfg->serve_expired_ttl; - verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u", - key, (int)data_len, (uint32_t)ttl); - /* build command to set to a binary safe string */ - n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key, - (uint32_t)ttl); - } - - - if(n < 0 || n >= (int)sizeof(cmdbuf)) { - log_err("redis_store: unexpected failure to build command"); - return; - } - - rep = redis_command(env, cachedb_env, cmdbuf, data, data_len); - if(rep) { - verbose(VERB_ALGO, "redis_store set completed"); - if(rep->type != REDIS_REPLY_STATUS && - rep->type != REDIS_REPLY_ERROR) { - log_err("redis_store: unexpected type of reply (%d)", - rep->type); - } - freeReplyObject(rep); - } -} - -struct cachedb_backend redis_backend = { "redis", - redis_init, redis_deinit, redis_lookup, redis_store -}; -#endif /* USE_REDIS */ -#endif /* USE_CACHEDB */ diff --git a/crates/libunbound-sys/unbound/cachedb/redis.h b/crates/libunbound-sys/unbound/cachedb/redis.h deleted file mode 100644 index 2da2a64f..00000000 --- a/crates/libunbound-sys/unbound/cachedb/redis.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * cachedb/redis.h - cachedb redis module - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that uses the redis database to cache - * dns responses. - */ - -/** the redis backend definition, contains callable functions - * and name string */ -extern struct cachedb_backend redis_backend; diff --git a/crates/libunbound-sys/unbound/compat/arc4_lock.c b/crates/libunbound-sys/unbound/compat/arc4_lock.c deleted file mode 100644 index a78f7523..00000000 --- a/crates/libunbound-sys/unbound/compat/arc4_lock.c +++ /dev/null @@ -1,82 +0,0 @@ -/* arc4_lock.c - global lock for arc4random -* - * Copyright (c) 2014, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "config.h" -#define LOCKRET(func) func -#ifdef ENABLE_LOCK_CHECKS -#undef ENABLE_LOCK_CHECKS -#endif -#include "util/locks.h" - -void _ARC4_LOCK(void); -void _ARC4_UNLOCK(void); - -#ifdef THREADS_DISABLED -void _ARC4_LOCK(void) -{ -} - -void _ARC4_UNLOCK(void) -{ -} - -void _ARC4_LOCK_DESTROY(void) -{ -} -#else /* !THREADS_DISABLED */ - -static lock_quick_type arc4lock; -static int arc4lockinit = 0; - -void _ARC4_LOCK(void) -{ - if(!arc4lockinit) { - arc4lockinit = 1; - lock_quick_init(&arc4lock); - } - lock_quick_lock(&arc4lock); -} - -void _ARC4_UNLOCK(void) -{ - lock_quick_unlock(&arc4lock); -} - -void _ARC4_LOCK_DESTROY(void) -{ - if(arc4lockinit) { - arc4lockinit = 0; - lock_quick_destroy(&arc4lock); - } -} -#endif /* THREADS_DISABLED */ diff --git a/crates/libunbound-sys/unbound/compat/arc4random.c b/crates/libunbound-sys/unbound/compat/arc4random.c deleted file mode 100644 index 486ab89c..00000000 --- a/crates/libunbound-sys/unbound/compat/arc4random.c +++ /dev/null @@ -1,312 +0,0 @@ -/* $OpenBSD: arc4random.c,v 1.41 2014/07/12 13:24:54 deraadt Exp $ */ - -/* - * Copyright (c) 1996, David Mazieres - * Copyright (c) 2008, Damien Miller - * Copyright (c) 2013, Markus Friedl - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "config.h" - -/* - * ChaCha based random number generator for OpenBSD. - */ - -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#include -#include -#include -#ifndef UB_ON_WINDOWS -#include -#endif - -#define KEYSTREAM_ONLY -#include "chacha_private.h" - -#define arc4_min(a, b) ((a) < (b) ? (a) : (b)) -#ifdef __GNUC__ -#define inline __inline -#else /* !__GNUC__ */ -#define inline -#endif /* !__GNUC__ */ -#ifndef MAP_ANON -#define MAP_ANON MAP_ANONYMOUS -#endif - -#define KEYSZ 32 -#define IVSZ 8 -#define BLOCKSZ 64 -#define RSBUFSZ (16*BLOCKSZ) - -#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */ - -/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ -static struct { - size_t rs_have; /* valid bytes at end of rs_buf */ - size_t rs_count; /* bytes till reseed */ -} *rs; - -/* Preserved in fork children. */ -static struct { - chacha_ctx rs_chacha; /* chacha context for random keystream */ - u_char rs_buf[RSBUFSZ]; /* keystream blocks */ -} *rsx; - -static inline void _rs_rekey(u_char *dat, size_t datlen); - -/* - * Basic sanity checking; wish we could do better. - */ -static int -fallback_gotdata(char *buf, size_t len) -{ - char any_set = 0; - size_t i; - - for (i = 0; i < len; ++i) - any_set |= buf[i]; - if (any_set == 0) - return -1; - return 0; -} - -/* fallback for getentropy in case libc returns failure */ -static int -fallback_getentropy_urandom(void *buf, size_t len) -{ - size_t i; - int fd, flags; - int save_errno = errno; - -start: - - flags = O_RDONLY; -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - fd = open("/dev/urandom", flags, 0); - if (fd == -1) { - if (errno == EINTR) - goto start; - goto nodevrandom; - } -#ifndef O_CLOEXEC -# ifdef HAVE_FCNTL - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -# endif -#endif - for (i = 0; i < len; ) { - size_t wanted = len - i; - ssize_t ret = read(fd, (char*)buf + i, wanted); - - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - close(fd); - goto nodevrandom; - } - i += ret; - } - close(fd); - if (fallback_gotdata(buf, len) == 0) { - errno = save_errno; - return 0; /* satisfied */ - } -nodevrandom: - errno = EIO; - return -1; -} - -static inline void -_rs_init(u_char *buf, size_t n) -{ - assert(buf); - if (n < KEYSZ + IVSZ) - return; - - if (rs == NULL) { -#ifndef UB_ON_WINDOWS - if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) - abort(); -#ifdef MAP_INHERIT_ZERO - if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1) - abort(); -#endif -#else /* WINDOWS */ - rs = malloc(sizeof(*rs)); - if(!rs) - abort(); -#endif - } - if (rsx == NULL) { -#ifndef UB_ON_WINDOWS - if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) - abort(); -#else /* WINDOWS */ - rsx = malloc(sizeof(*rsx)); - if(!rsx) - abort(); -#endif - } - - chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); - chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); -} - -static void -_rs_stir(void) -{ - u_char rnd[KEYSZ + IVSZ]; - uint32_t rekey_fuzz = 0; - - if (getentropy(rnd, sizeof rnd) == -1) { - if(errno != ENOSYS || - fallback_getentropy_urandom(rnd, sizeof rnd) == -1) { -#ifdef SIGKILL - raise(SIGKILL); -#else - exit(9); /* windows */ -#endif - } - } - - if (!rs) - _rs_init(rnd, sizeof(rnd)); - else - _rs_rekey(rnd, sizeof(rnd)); - explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ - - /* invalidate rs_buf */ - rs->rs_have = 0; - memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); - - /* rekey interval should not be predictable */ - chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz, - (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz)); - rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE); -} - -static inline void -_rs_stir_if_needed(size_t len) -{ -#ifndef MAP_INHERIT_ZERO - static pid_t _rs_pid = 0; - pid_t pid = getpid(); - - /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */ - if (_rs_pid == 0 || _rs_pid != pid) { - _rs_pid = pid; - if (rs) - rs->rs_count = 0; - } -#endif - if (!rs || rs->rs_count <= len) - _rs_stir(); - if (rs->rs_count <= len) - rs->rs_count = 0; - else - rs->rs_count -= len; -} - -static inline void -_rs_rekey(u_char *dat, size_t datlen) -{ -#ifndef KEYSTREAM_ONLY - memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); -#endif - /* fill rs_buf with the keystream */ - chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf, - rsx->rs_buf, sizeof(rsx->rs_buf)); - /* mix in optional user provided data */ - if (dat) { - size_t i, m; - - m = arc4_min(datlen, KEYSZ + IVSZ); - for (i = 0; i < m; i++) - rsx->rs_buf[i] ^= dat[i]; - } - /* immediately reinit for backtracking resistance */ - _rs_init(rsx->rs_buf, KEYSZ + IVSZ); - memset(rsx->rs_buf, 0, KEYSZ + IVSZ); - rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; -} - -static inline void -_rs_random_buf(void *_buf, size_t n) -{ - u_char *buf = (u_char *)_buf; - u_char *keystream; - size_t m; - - _rs_stir_if_needed(n); - while (n > 0) { - if (rs->rs_have > 0) { - m = arc4_min(n, rs->rs_have); - keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - - rs->rs_have; - memcpy(buf, keystream, m); - memset(keystream, 0, m); - buf += m; - n -= m; - rs->rs_have -= m; - } - if (rs->rs_have == 0) - _rs_rekey(NULL, 0); - } -} - -static inline void -_rs_random_u32(uint32_t *val) -{ - u_char *keystream; - _rs_stir_if_needed(sizeof(*val)); - if (rs->rs_have < sizeof(*val)) - _rs_rekey(NULL, 0); - keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; - memcpy(val, keystream, sizeof(*val)); - memset(keystream, 0, sizeof(*val)); - rs->rs_have -= sizeof(*val); -} - -uint32_t -arc4random(void) -{ - uint32_t val; - - _ARC4_LOCK(); - _rs_random_u32(&val); - _ARC4_UNLOCK(); - return val; -} - -void -arc4random_buf(void *buf, size_t n) -{ - _ARC4_LOCK(); - _rs_random_buf(buf, n); - _ARC4_UNLOCK(); -} diff --git a/crates/libunbound-sys/unbound/compat/arc4random_uniform.c b/crates/libunbound-sys/unbound/compat/arc4random_uniform.c deleted file mode 100644 index 154260eb..00000000 --- a/crates/libunbound-sys/unbound/compat/arc4random_uniform.c +++ /dev/null @@ -1,57 +0,0 @@ -/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */ - -/* - * Copyright (c) 2008, Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "config.h" -#include -#include - -/* - * Calculate a uniformly distributed random number less than upper_bound - * avoiding "modulo bias". - * - * Uniformity is achieved by generating new random numbers until the one - * returned is outside the range [0, 2**32 % upper_bound). This - * guarantees the selected random number will be inside - * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) - * after reduction modulo upper_bound. - */ -uint32_t -arc4random_uniform(uint32_t upper_bound) -{ - uint32_t r, min; - - if (upper_bound < 2) - return 0; - - /* 2**32 % x == (2**32 - x) % x */ - min = -upper_bound % upper_bound; - - /* - * This could theoretically loop forever but each retry has - * p > 0.5 (worst case, usually far better) of selecting a - * number inside the range we need, so it should rarely need - * to re-roll. - */ - for (;;) { - r = arc4random(); - if (r >= min) - break; - } - - return r % upper_bound; -} diff --git a/crates/libunbound-sys/unbound/compat/chacha_private.h b/crates/libunbound-sys/unbound/compat/chacha_private.h deleted file mode 100644 index 192258c7..00000000 --- a/crates/libunbound-sys/unbound/compat/chacha_private.h +++ /dev/null @@ -1,222 +0,0 @@ -/* -chacha-merged.c version 20080118 -D. J. Bernstein -Public domain. -*/ - -/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */ - -typedef unsigned char u8; -typedef unsigned int u32; - -typedef struct -{ - u32 input[16]; /* could be compressed */ -} chacha_ctx; - -#define U8C(v) (v##U) -#define U32C(v) (v##U) - -#define U8V(v) ((u8)(v) & U8C(0xFF)) -#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) - -#define ROTL32(v, n) \ - (U32V((v) << (n)) | ((v) >> (32 - (n)))) - -#define U8TO32_LITTLE(p) \ - (((u32)((p)[0]) ) | \ - ((u32)((p)[1]) << 8) | \ - ((u32)((p)[2]) << 16) | \ - ((u32)((p)[3]) << 24)) - -#define U32TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - (p)[2] = U8V((v) >> 16); \ - (p)[3] = U8V((v) >> 24); \ - } while (0) - -#define ROTATE(v,c) (ROTL32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -#define QUARTERROUND(a,b,c,d) \ - a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ - a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); - -static const char sigma[16] = "expand 32-byte k"; -static const char tau[16] = "expand 16-byte k"; - -static void -chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits)) -{ - const char *constants; - - x->input[4] = U8TO32_LITTLE(k + 0); - x->input[5] = U8TO32_LITTLE(k + 4); - x->input[6] = U8TO32_LITTLE(k + 8); - x->input[7] = U8TO32_LITTLE(k + 12); - if (kbits == 256) { /* recommended */ - k += 16; - constants = sigma; - } else { /* kbits == 128 */ - constants = tau; - } - x->input[8] = U8TO32_LITTLE(k + 0); - x->input[9] = U8TO32_LITTLE(k + 4); - x->input[10] = U8TO32_LITTLE(k + 8); - x->input[11] = U8TO32_LITTLE(k + 12); - x->input[0] = U8TO32_LITTLE(constants + 0); - x->input[1] = U8TO32_LITTLE(constants + 4); - x->input[2] = U8TO32_LITTLE(constants + 8); - x->input[3] = U8TO32_LITTLE(constants + 12); -} - -static void -chacha_ivsetup(chacha_ctx *x,const u8 *iv) -{ - x->input[12] = 0; - x->input[13] = 0; - x->input[14] = U8TO32_LITTLE(iv + 0); - x->input[15] = U8TO32_LITTLE(iv + 4); -} - -static void -chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) -{ - u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - u8 *ctarget = NULL; - u8 tmp[64]; - u_int i; - - if (!bytes) return; - - j0 = x->input[0]; - j1 = x->input[1]; - j2 = x->input[2]; - j3 = x->input[3]; - j4 = x->input[4]; - j5 = x->input[5]; - j6 = x->input[6]; - j7 = x->input[7]; - j8 = x->input[8]; - j9 = x->input[9]; - j10 = x->input[10]; - j11 = x->input[11]; - j12 = x->input[12]; - j13 = x->input[13]; - j14 = x->input[14]; - j15 = x->input[15]; - - for (;;) { - if (bytes < 64) { - for (i = 0;i < bytes;++i) tmp[i] = m[i]; - m = tmp; - ctarget = c; - c = tmp; - } - x0 = j0; - x1 = j1; - x2 = j2; - x3 = j3; - x4 = j4; - x5 = j5; - x6 = j6; - x7 = j7; - x8 = j8; - x9 = j9; - x10 = j10; - x11 = j11; - x12 = j12; - x13 = j13; - x14 = j14; - x15 = j15; - for (i = 20;i > 0;i -= 2) { - QUARTERROUND( x0, x4, x8,x12) - QUARTERROUND( x1, x5, x9,x13) - QUARTERROUND( x2, x6,x10,x14) - QUARTERROUND( x3, x7,x11,x15) - QUARTERROUND( x0, x5,x10,x15) - QUARTERROUND( x1, x6,x11,x12) - QUARTERROUND( x2, x7, x8,x13) - QUARTERROUND( x3, x4, x9,x14) - } - x0 = PLUS(x0,j0); - x1 = PLUS(x1,j1); - x2 = PLUS(x2,j2); - x3 = PLUS(x3,j3); - x4 = PLUS(x4,j4); - x5 = PLUS(x5,j5); - x6 = PLUS(x6,j6); - x7 = PLUS(x7,j7); - x8 = PLUS(x8,j8); - x9 = PLUS(x9,j9); - x10 = PLUS(x10,j10); - x11 = PLUS(x11,j11); - x12 = PLUS(x12,j12); - x13 = PLUS(x13,j13); - x14 = PLUS(x14,j14); - x15 = PLUS(x15,j15); - -#ifndef KEYSTREAM_ONLY - x0 = XOR(x0,U8TO32_LITTLE(m + 0)); - x1 = XOR(x1,U8TO32_LITTLE(m + 4)); - x2 = XOR(x2,U8TO32_LITTLE(m + 8)); - x3 = XOR(x3,U8TO32_LITTLE(m + 12)); - x4 = XOR(x4,U8TO32_LITTLE(m + 16)); - x5 = XOR(x5,U8TO32_LITTLE(m + 20)); - x6 = XOR(x6,U8TO32_LITTLE(m + 24)); - x7 = XOR(x7,U8TO32_LITTLE(m + 28)); - x8 = XOR(x8,U8TO32_LITTLE(m + 32)); - x9 = XOR(x9,U8TO32_LITTLE(m + 36)); - x10 = XOR(x10,U8TO32_LITTLE(m + 40)); - x11 = XOR(x11,U8TO32_LITTLE(m + 44)); - x12 = XOR(x12,U8TO32_LITTLE(m + 48)); - x13 = XOR(x13,U8TO32_LITTLE(m + 52)); - x14 = XOR(x14,U8TO32_LITTLE(m + 56)); - x15 = XOR(x15,U8TO32_LITTLE(m + 60)); -#endif - - j12 = PLUSONE(j12); - if (!j12) { - j13 = PLUSONE(j13); - /* stopping at 2^70 bytes per nonce is user's responsibility */ - } - - U32TO8_LITTLE(c + 0,x0); - U32TO8_LITTLE(c + 4,x1); - U32TO8_LITTLE(c + 8,x2); - U32TO8_LITTLE(c + 12,x3); - U32TO8_LITTLE(c + 16,x4); - U32TO8_LITTLE(c + 20,x5); - U32TO8_LITTLE(c + 24,x6); - U32TO8_LITTLE(c + 28,x7); - U32TO8_LITTLE(c + 32,x8); - U32TO8_LITTLE(c + 36,x9); - U32TO8_LITTLE(c + 40,x10); - U32TO8_LITTLE(c + 44,x11); - U32TO8_LITTLE(c + 48,x12); - U32TO8_LITTLE(c + 52,x13); - U32TO8_LITTLE(c + 56,x14); - U32TO8_LITTLE(c + 60,x15); - - if (bytes <= 64) { - if (bytes < 64) { - for (i = 0;i < bytes;++i) ctarget[i] = c[i]; - } - x->input[12] = j12; - x->input[13] = j13; - return; - } - bytes -= 64; - c += 64; -#ifndef KEYSTREAM_ONLY - m += 64; -#endif - } -} diff --git a/crates/libunbound-sys/unbound/compat/ctime_r.c b/crates/libunbound-sys/unbound/compat/ctime_r.c deleted file mode 100644 index 9f2bf15b..00000000 --- a/crates/libunbound-sys/unbound/compat/ctime_r.c +++ /dev/null @@ -1,42 +0,0 @@ -/* taken from ldns 1.6.1 */ -#include "config.h" -#ifdef HAVE_TIME_H -#include -#endif -#include "util/locks.h" - -/** the lock for ctime buffer */ -static lock_basic_type ctime_lock; -/** has it been inited */ -static int ctime_r_init = 0; - -/** cleanup ctime_r on exit */ -static void -ctime_r_cleanup(void) -{ - if(ctime_r_init) { - ctime_r_init = 0; - lock_basic_destroy(&ctime_lock); - } -} - -char *ctime_r(const time_t *timep, char *buf) -{ - char* result; - if(!ctime_r_init) { - /* still small race where this init can be done twice, - * which is mostly harmless */ - ctime_r_init = 1; - lock_basic_init(&ctime_lock); - atexit(&ctime_r_cleanup); - } - lock_basic_lock(&ctime_lock); - result = ctime(timep); - if(buf && result) { - if(strlen(result) > 10 && result[7]==' ' && result[8]=='0') - result[8]=' '; /* fix error in windows ctime */ - strcpy(buf, result); - } - lock_basic_unlock(&ctime_lock); - return buf; -} diff --git a/crates/libunbound-sys/unbound/compat/explicit_bzero.c b/crates/libunbound-sys/unbound/compat/explicit_bzero.c deleted file mode 100644 index 5f1c427c..00000000 --- a/crates/libunbound-sys/unbound/compat/explicit_bzero.c +++ /dev/null @@ -1,26 +0,0 @@ -/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ -/* - * Public domain. - * Written by Matthew Dempsky. - */ -#include "config.h" -#include - -#ifdef HAVE_ATTR_WEAK -__attribute__((weak)) void -#else -void -#endif -__explicit_bzero_hook(void *ATTR_UNUSED(buf), size_t ATTR_UNUSED(len)) -{ -} - -void -explicit_bzero(void *buf, size_t len) -{ -#ifdef UB_ON_WINDOWS - SecureZeroMemory(buf, len); -#endif - memset(buf, 0, len); - __explicit_bzero_hook(buf, len); -} diff --git a/crates/libunbound-sys/unbound/compat/fake-rfc2553.c b/crates/libunbound-sys/unbound/compat/fake-rfc2553.c deleted file mode 100644 index 0f0f34f1..00000000 --- a/crates/libunbound-sys/unbound/compat/fake-rfc2553.c +++ /dev/null @@ -1,225 +0,0 @@ -/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ -/* - * Copyright (C) 2000-2003 Damien Miller. All rights reserved. - * Copyright (C) 1999 WIDE Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Pseudo-implementation of RFC2553 name / address resolution functions - * - * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For example, this routine assumes - * that ai_family is AF_INET. Don't use it for another purpose. - */ - -#include -#include -#include -#include -#include "compat/fake-rfc2553.h" - -#ifndef HAVE_GETNAMEINFO -int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, - size_t hostlen, char *serv, size_t servlen, int flags) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)sa; - struct hostent *hp; - char tmpserv[16]; - - if (serv != NULL) { - snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); - if (strlcpy(serv, tmpserv, servlen) >= servlen) - return (EAI_MEMORY); - } - - if (host != NULL) { - if (flags & NI_NUMERICHOST) { - if (strlcpy(host, inet_ntoa(sin->sin_addr), - hostlen) >= hostlen) - return (EAI_MEMORY); - else - return (0); - } else { - hp = gethostbyaddr((char *)&sin->sin_addr, - sizeof(struct in_addr), AF_INET); - if (hp == NULL) - return (EAI_NODATA); - - if (strlcpy(host, hp->h_name, hostlen) >= hostlen) - return (EAI_MEMORY); - else - return (0); - } - } - return (0); -} -#endif /* !HAVE_GETNAMEINFO */ - -#ifndef HAVE_GAI_STRERROR -#ifdef HAVE_CONST_GAI_STRERROR_PROTO -const char * -#else -char * -#endif -gai_strerror(int err) -{ - switch (err) { - case EAI_NODATA: - return ("no address associated with name"); - case EAI_MEMORY: - return ("memory allocation failure."); - case EAI_NONAME: - return ("nodename nor servname provided, or not known"); - default: - return ("unknown/invalid error."); - } -} -#endif /* !HAVE_GAI_STRERROR */ - -#ifndef HAVE_FREEADDRINFO -void -freeaddrinfo(struct addrinfo *ai) -{ - struct addrinfo *next; - - for(; ai != NULL;) { - next = ai->ai_next; - free(ai); - ai = next; - } -} -#endif /* !HAVE_FREEADDRINFO */ - -#ifndef HAVE_GETADDRINFO -static struct -addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) -{ - struct addrinfo *ai; - - ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in)); - if (ai == NULL) - return (NULL); - - ai->ai_addr = (struct sockaddr *)(ai + 1); - /* XXX -- ssh doesn't use sa_len */ - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr->sa_family = ai->ai_family = AF_INET; - - ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; - ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; - - /* XXX: the following is not generally correct, but does what we want */ - if (hints->ai_socktype) - ai->ai_socktype = hints->ai_socktype; - else - ai->ai_socktype = SOCK_STREAM; - - if (hints->ai_protocol) - ai->ai_protocol = hints->ai_protocol; - - return (ai); -} - -int -getaddrinfo(const char *hostname, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - struct hostent *hp; - struct servent *sp; - struct in_addr in; - int i; - long int port; - u_long addr; - - port = 0; - if (servname != NULL) { - char *cp; - - port = strtol(servname, &cp, 10); - if (port > 0 && port <= 65535 && *cp == '\0') - port = htons(port); - else if ((sp = getservbyname(servname, NULL)) != NULL) - port = sp->s_port; - else - port = 0; - } - - if (hints && hints->ai_flags & AI_PASSIVE) { - addr = htonl(0x00000000); - if (hostname && inet_aton(hostname, &in) != 0) - addr = in.s_addr; - *res = malloc_ai(port, addr, hints); - if (*res == NULL) - return (EAI_MEMORY); - return (0); - } - - if (!hostname) { - *res = malloc_ai(port, htonl(0x7f000001), hints); - if (*res == NULL) - return (EAI_MEMORY); - return (0); - } - - if (inet_aton(hostname, &in)) { - *res = malloc_ai(port, in.s_addr, hints); - if (*res == NULL) - return (EAI_MEMORY); - return (0); - } - - /* Don't try DNS if AI_NUMERICHOST is set */ - if (hints && hints->ai_flags & AI_NUMERICHOST) - return (EAI_NONAME); - - hp = gethostbyname(hostname); - if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { - struct addrinfo *cur, *prev; - - cur = prev = *res = NULL; - for (i = 0; hp->h_addr_list[i]; i++) { - struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; - - cur = malloc_ai(port, in->s_addr, hints); - if (cur == NULL) { - if (*res != NULL) - freeaddrinfo(*res); - return (EAI_MEMORY); - } - if (prev) - prev->ai_next = cur; - else - *res = cur; - - prev = cur; - } - return (0); - } - - return (EAI_NODATA); -} -#endif /* !HAVE_GETADDRINFO */ diff --git a/crates/libunbound-sys/unbound/compat/fake-rfc2553.h b/crates/libunbound-sys/unbound/compat/fake-rfc2553.h deleted file mode 100644 index 466c0e66..00000000 --- a/crates/libunbound-sys/unbound/compat/fake-rfc2553.h +++ /dev/null @@ -1,174 +0,0 @@ -/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ -/* - * Copyright (C) 2000-2003 Damien Miller. All rights reserved. - * Copyright (C) 1999 WIDE Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Pseudo-implementation of RFC2553 name / address resolution functions - * - * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For example, this routine assumes - * that ai_family is AF_INET. Don't use it for another purpose. - */ - -#ifndef _FAKE_RFC2553_H -#define _FAKE_RFC2553_H - -#include -#include -#include -#include -#include - -/* - * First, socket and INET6 related definitions - */ -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE -# define _SS_MAXSIZE 128 /* Implementation specific max size */ -# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) -struct sockaddr_storage { - struct sockaddr ss_sa; - char __ss_pad2[_SS_PADSIZE]; -}; -# define ss_family ss_sa.sa_family -#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ - -#ifndef IN6_IS_ADDR_LOOPBACK -# define IN6_IS_ADDR_LOOPBACK(a) \ - (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ - ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) -#endif /* !IN6_IS_ADDR_LOOPBACK */ - -#ifndef HAVE_STRUCT_IN6_ADDR -struct in6_addr { - uint8_t s6_addr[16]; -}; -#endif /* !HAVE_STRUCT_IN6_ADDR */ - -#ifndef HAVE_STRUCT_SOCKADDR_IN6 -struct sockaddr_in6 { - unsigned short sin6_family; - uint16_t sin6_port; - uint32_t sin6_flowinfo; - struct in6_addr sin6_addr; -}; -#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ - -#ifndef AF_INET6 -/* Define it to something that should never appear */ -#define AF_INET6 AF_MAX -#endif - -/* - * Next, RFC2553 name / address resolution API - */ - -#ifndef NI_NUMERICHOST -# define NI_NUMERICHOST (1) -#endif -#ifndef NI_NAMEREQD -# define NI_NAMEREQD (1<<1) -#endif -#ifndef NI_NUMERICSERV -# define NI_NUMERICSERV (1<<2) -#endif - -#ifndef AI_PASSIVE -# define AI_PASSIVE (1) -#endif -#ifndef AI_CANONNAME -# define AI_CANONNAME (1<<1) -#endif -#ifndef AI_NUMERICHOST -# define AI_NUMERICHOST (1<<2) -#endif - -#ifndef NI_MAXSERV -# define NI_MAXSERV 32 -#endif /* !NI_MAXSERV */ -#ifndef NI_MAXHOST -# define NI_MAXHOST 1025 -#endif /* !NI_MAXHOST */ - -#ifndef INT_MAX -#define INT_MAX 0xffffffff -#endif - -#ifndef EAI_NODATA -# define EAI_NODATA (INT_MAX - 1) -#endif -#ifndef EAI_MEMORY -# define EAI_MEMORY (INT_MAX - 2) -#endif -#ifndef EAI_NONAME -# define EAI_NONAME (INT_MAX - 3) -#endif -#ifndef EAI_SYSTEM -# define EAI_SYSTEM (INT_MAX - 4) -#endif - -#ifndef HAVE_STRUCT_ADDRINFO -struct addrinfo { - int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for hostname */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ -}; -#endif /* !HAVE_STRUCT_ADDRINFO */ - -#ifndef HAVE_GETADDRINFO -#ifdef getaddrinfo -# undef getaddrinfo -#endif -#define getaddrinfo(a,b,c,d) (getaddrinfo_unbound(a,b,c,d)) -int getaddrinfo(const char *, const char *, - const struct addrinfo *, struct addrinfo **); -#endif /* !HAVE_GETADDRINFO */ - -#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) -#define gai_strerror(a) (gai_strerror_unbound(a)) -char *gai_strerror(int); -#endif /* !HAVE_GAI_STRERROR */ - -#ifndef HAVE_FREEADDRINFO -#define freeaddrinfo(a) (freeaddrinfo_unbound(a)) -void freeaddrinfo(struct addrinfo *); -#endif /* !HAVE_FREEADDRINFO */ - -#ifndef HAVE_GETNAMEINFO -#define getnameinfo(a,b,c,d,e,f,g) (getnameinfo_unbound(a,b,c,d,e,f,g)) -int getnameinfo(const struct sockaddr *, size_t, char *, size_t, - char *, size_t, int); -#endif /* !HAVE_GETNAMEINFO */ - -#endif /* !_FAKE_RFC2553_H */ - diff --git a/crates/libunbound-sys/unbound/compat/getentropy_freebsd.c b/crates/libunbound-sys/unbound/compat/getentropy_freebsd.c deleted file mode 100644 index 30cd68e9..00000000 --- a/crates/libunbound-sys/unbound/compat/getentropy_freebsd.c +++ /dev/null @@ -1,62 +0,0 @@ -/* $OpenBSD: getentropy_freebsd.c,v 1.3 2016/08/07 03:27:21 tb Exp $ */ - -/* - * Copyright (c) 2014 Pawel Jakub Dawidek - * Copyright (c) 2014 Brent Cook - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Emulation of getentropy(2) as documented at: - * http://man.openbsd.org/getentropy.2 - */ - -#include -#include - -#include -#include - -/* - * Derived from lib/libc/gen/arc4random.c from FreeBSD. - */ -static size_t -getentropy_sysctl(u_char *buf, size_t size) -{ - int mib[2]; - size_t len, done; - - mib[0] = CTL_KERN; - mib[1] = KERN_ARND; - done = 0; - - do { - len = size; - if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) - return (done); - done += len; - buf += len; - size -= len; - } while (size > 0); - - return (done); -} - -int -getentropy(void *buf, size_t len) -{ - if (len <= 256 && getentropy_sysctl(buf, len) == len) - return (0); - - errno = EIO; - return (-1); -} diff --git a/crates/libunbound-sys/unbound/compat/getentropy_linux.c b/crates/libunbound-sys/unbound/compat/getentropy_linux.c deleted file mode 100644 index 82cdb78b..00000000 --- a/crates/libunbound-sys/unbound/compat/getentropy_linux.c +++ /dev/null @@ -1,539 +0,0 @@ -/* $OpenBSD: getentropy_linux.c,v 1.46 2018/11/20 08:04:28 deraadt Exp $ */ - -/* - * Copyright (c) 2014 Theo de Raadt - * Copyright (c) 2014 Bob Beck - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Emulation of getentropy(2) as documented at: - * http://man.openbsd.org/getentropy.2 - */ - -#include "config.h" -/* -#define _POSIX_C_SOURCE 199309L -#define _GNU_SOURCE 1 -*/ -#include -#include -#include -#include -#include -#ifdef SYS__sysctl -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef HAVE_NETTLE -#include -#else -#include -#define SHA512_CTX struct sha512_ctx -#define SHA512_Init(x) sha512_init(x) -#define SHA512_Update(x, b, s) sha512_update(x, s, b) -#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r) -#endif - -#include -#include -#ifdef HAVE_GETAUXVAL -#include -#endif -#include -#ifndef MAP_ANON -#define MAP_ANON MAP_ANONYMOUS -#endif - -#define REPEAT 5 -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -#define HX(a, b) \ - do { \ - if ((a)) \ - HD(errno); \ - else \ - HD(b); \ - } while (0) - -#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) -#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) -#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) - -int getentropy(void *buf, size_t len); - -#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) -static int getentropy_getrandom(void *buf, size_t len); -#endif -static int getentropy_urandom(void *buf, size_t len); -#ifdef SYS__sysctl -static int getentropy_sysctl(void *buf, size_t len); -#endif -static int getentropy_fallback(void *buf, size_t len); -static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data); - -int -getentropy(void *buf, size_t len) -{ - int ret = -1; - - if (len > 256) { - errno = EIO; - return (-1); - } - -#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) - /* - * Try descriptor-less getrandom(), in non-blocking mode. - * - * The design of Linux getrandom is broken. It has an - * uninitialized phase coupled with blocking behaviour, which - * is unacceptable from within a library at boot time without - * possible recovery. See http://bugs.python.org/issue26839#msg267745 - */ - ret = getentropy_getrandom(buf, len); - if (ret != -1) - return (ret); -#endif - - /* - * Try to get entropy with /dev/urandom - * - * This can fail if the process is inside a chroot or if file - * descriptors are exhausted. - */ - ret = getentropy_urandom(buf, len); - if (ret != -1) - return (ret); - -#ifdef SYS__sysctl - /* - * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID. - * sysctl is a failsafe API, so it guarantees a result. This - * should work inside a chroot, or when file descriptors are - * exhausted. - * - * However this can fail if the Linux kernel removes support - * for sysctl. Starting in 2007, there have been efforts to - * deprecate the sysctl API/ABI, and push callers towards use - * of the chroot-unavailable fd-using /proc mechanism -- - * essentially the same problems as /dev/urandom. - * - * Numerous setbacks have been encountered in their deprecation - * schedule, so as of June 2014 the kernel ABI still exists on - * most Linux architectures. The sysctl() stub in libc is missing - * on some systems. There are also reports that some kernels - * spew messages to the console. - */ - ret = getentropy_sysctl(buf, len); - if (ret != -1) - return (ret); -#endif /* SYS__sysctl */ - - /* - * Entropy collection via /dev/urandom and sysctl have failed. - * - * No other API exists for collecting entropy. See the large - * comment block above. - * - * We have very few options: - * - Even syslog_r is unsafe to call at this low level, so - * there is no way to alert the user or program. - * - Cannot call abort() because some systems have unsafe - * corefiles. - * - Could raise(SIGKILL) resulting in silent program termination. - * - Return EIO, to hint that arc4random's stir function - * should raise(SIGKILL) - * - Do the best under the circumstances.... - * - * This code path exists to bring light to the issue that Linux - * still does not provide a failsafe API for entropy collection. - * - * We hope this demonstrates that Linux should either retain their - * sysctl ABI, or consider providing a new failsafe API which - * works in a chroot or when file descriptors are exhausted. - */ -#undef FAIL_INSTEAD_OF_TRYING_FALLBACK -#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK - raise(SIGKILL); -#endif - ret = getentropy_fallback(buf, len); - if (ret != -1) - return (ret); - - errno = EIO; - return (ret); -} - -#if defined(SYS_getrandom) && defined(GRND_NONBLOCK) -static int -getentropy_getrandom(void *buf, size_t len) -{ - int pre_errno = errno; - int ret; - if (len > 256) - return (-1); - do { - ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK); - } while (ret == -1 && errno == EINTR); - - if (ret != (int)len) - return (-1); - errno = pre_errno; - return (0); -} -#endif - -static int -getentropy_urandom(void *buf, size_t len) -{ - struct stat st; - size_t i; - int fd, cnt, flags; - int save_errno = errno; - -start: - - flags = O_RDONLY; -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - fd = open("/dev/urandom", flags, 0); - if (fd == -1) { - if (errno == EINTR) - goto start; - goto nodevrandom; - } -#ifndef O_CLOEXEC - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -#endif - - /* Lightly verify that the device node looks sane */ - if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { - close(fd); - goto nodevrandom; - } - if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) { - close(fd); - goto nodevrandom; - } - for (i = 0; i < len; ) { - size_t wanted = len - i; - ssize_t ret = read(fd, (char *)buf + i, wanted); - - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - close(fd); - goto nodevrandom; - } - i += ret; - } - close(fd); - errno = save_errno; - return (0); /* satisfied */ -nodevrandom: - errno = EIO; - return (-1); -} - -#ifdef SYS__sysctl -static int -getentropy_sysctl(void *buf, size_t len) -{ - static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; - size_t i; - int save_errno = errno; - - for (i = 0; i < len; ) { - size_t chunk = min(len - i, 16); - - /* SYS__sysctl because some systems already removed sysctl() */ - struct __sysctl_args args = { - .name = mib, - .nlen = 3, - .oldval = (char *)buf + i, - .oldlenp = &chunk, - }; - if (syscall(SYS__sysctl, &args) != 0) - goto sysctlfailed; - i += chunk; - } - errno = save_errno; - return (0); /* satisfied */ -sysctlfailed: - errno = EIO; - return (-1); -} -#endif /* SYS__sysctl */ - -static const int cl[] = { - CLOCK_REALTIME, -#ifdef CLOCK_MONOTONIC - CLOCK_MONOTONIC, -#endif -#ifdef CLOCK_MONOTONIC_RAW - CLOCK_MONOTONIC_RAW, -#endif -#ifdef CLOCK_TAI - CLOCK_TAI, -#endif -#ifdef CLOCK_VIRTUAL - CLOCK_VIRTUAL, -#endif -#ifdef CLOCK_UPTIME - CLOCK_UPTIME, -#endif -#ifdef CLOCK_PROCESS_CPUTIME_ID - CLOCK_PROCESS_CPUTIME_ID, -#endif -#ifdef CLOCK_THREAD_CPUTIME_ID - CLOCK_THREAD_CPUTIME_ID, -#endif -}; - -static int -getentropy_phdr(struct dl_phdr_info *info, size_t ATTR_UNUSED(size), void *data) -{ - SHA512_CTX *ctx = data; - - SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr)); - return (0); -} - -static int -getentropy_fallback(void *buf, size_t len) -{ - uint8_t results[SHA512_DIGEST_LENGTH]; - int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; - static int cnt; - struct timespec ts; - struct timeval tv; - struct rusage ru; - sigset_t sigset; - struct stat st; - SHA512_CTX ctx; - static pid_t lastpid; - pid_t pid; - size_t i, ii, m; - char *p; - - pid = getpid(); - if (lastpid == pid) { - faster = 1; - repeat = 2; - } else { - faster = 0; - lastpid = pid; - repeat = REPEAT; - } - for (i = 0; i < len; ) { - int j; - SHA512_Init(&ctx); - for (j = 0; j < repeat; j++) { - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - dl_iterate_phdr(getentropy_phdr, &ctx); - - for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) - HX(clock_gettime(cl[ii], &ts) == -1, ts); - - HX((pid = getpid()) == -1, pid); - HX((pid = getsid(pid)) == -1, pid); - HX((pid = getppid()) == -1, pid); - HX((pid = getpgid(0)) == -1, pid); - HX((e = getpriority(0, 0)) == -1, e); - - if (!faster) { - ts.tv_sec = 0; - ts.tv_nsec = 1; - (void) nanosleep(&ts, NULL); - } - - HX(sigpending(&sigset) == -1, sigset); - HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, - sigset); - - HF(getentropy); /* an addr in this library */ - HF(printf); /* an addr in libc */ - p = (char *)&p; - HD(p); /* an addr on stack */ - p = (char *)&errno; - HD(p); /* the addr of errno */ - - if (i == 0) { - struct sockaddr_storage ss; - struct statvfs stvfs; - struct termios tios; - struct statfs stfs; - socklen_t ssl; - off_t off; - - /* - * Prime-sized mappings encourage fragmentation; - * thus exposing some address entropy. - */ - struct mm { - size_t npg; - void *p; - } mm[] = { - { 17, MAP_FAILED }, { 3, MAP_FAILED }, - { 11, MAP_FAILED }, { 2, MAP_FAILED }, - { 5, MAP_FAILED }, { 3, MAP_FAILED }, - { 7, MAP_FAILED }, { 1, MAP_FAILED }, - { 57, MAP_FAILED }, { 3, MAP_FAILED }, - { 131, MAP_FAILED }, { 1, MAP_FAILED }, - }; - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - HX(mm[m].p = mmap(NULL, - mm[m].npg * pgs, - PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANON, -1, - (off_t)0), mm[m].p); - if (mm[m].p != MAP_FAILED) { - size_t mo; - - /* Touch some memory... */ - p = mm[m].p; - mo = cnt % - (mm[m].npg * pgs - 1); - p[mo] = 1; - cnt += (int)((long)(mm[m].p) - / pgs); - } - - /* Check cnts and times... */ - for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); - ii++) { - HX((e = clock_gettime(cl[ii], - &ts)) == -1, ts); - if (e != -1) - cnt += (int)ts.tv_nsec; - } - - HX((e = getrusage(RUSAGE_SELF, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - if (mm[m].p != MAP_FAILED) - munmap(mm[m].p, mm[m].npg * pgs); - mm[m].p = MAP_FAILED; - } - - HX(stat(".", &st) == -1, st); - HX(statvfs(".", &stvfs) == -1, stvfs); - HX(statfs(".", &stfs) == -1, stfs); - - HX(stat("/", &st) == -1, st); - HX(statvfs("/", &stvfs) == -1, stvfs); - HX(statfs("/", &stfs) == -1, stfs); - - HX((e = fstat(0, &st)) == -1, st); - if (e == -1) { - if (S_ISREG(st.st_mode) || - S_ISFIFO(st.st_mode) || - S_ISSOCK(st.st_mode)) { - HX(fstatvfs(0, &stvfs) == -1, - stvfs); - HX(fstatfs(0, &stfs) == -1, - stfs); - HX((off = lseek(0, (off_t)0, - SEEK_CUR)) < 0, off); - } - if (S_ISCHR(st.st_mode)) { - HX(tcgetattr(0, &tios) == -1, - tios); - } else if (S_ISSOCK(st.st_mode)) { - memset(&ss, 0, sizeof ss); - ssl = sizeof(ss); - HX(getpeername(0, - (void *)&ss, &ssl) == -1, - ss); - } - } - - HX((e = getrusage(RUSAGE_CHILDREN, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } else { - /* Subsequent hashes absorb previous result */ - HD(results); - } - - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - HD(cnt); - } -#ifdef HAVE_GETAUXVAL -#ifdef AT_RANDOM - /* Not as random as you think but we take what we are given */ - p = (char *) getauxval(AT_RANDOM); - if (p) - HR(p, 16); -#endif -#ifdef AT_SYSINFO_EHDR - p = (char *) getauxval(AT_SYSINFO_EHDR); - if (p) - HR(p, pgs); -#endif -#ifdef AT_BASE - p = (char *) getauxval(AT_BASE); - if (p) - HD(p); -#endif -#endif - - SHA512_Final(results, &ctx); - memcpy((char *)buf + i, results, min(sizeof(results), len - i)); - i += min(sizeof(results), len - i); - } - explicit_bzero(&ctx, sizeof ctx); - explicit_bzero(results, sizeof results); - errno = save_errno; - return (0); /* satisfied */ -} diff --git a/crates/libunbound-sys/unbound/compat/getentropy_osx.c b/crates/libunbound-sys/unbound/compat/getentropy_osx.c deleted file mode 100644 index 26dcc824..00000000 --- a/crates/libunbound-sys/unbound/compat/getentropy_osx.c +++ /dev/null @@ -1,417 +0,0 @@ -/* $OpenBSD: getentropy_osx.c,v 1.12 2018/11/20 08:04:28 deraadt Exp $ */ - -/* - * Copyright (c) 2014 Theo de Raadt - * Copyright (c) 2014 Bob Beck - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Emulation of getentropy(2) as documented at: - * http://man.openbsd.org/getentropy.2 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if TARGET_OS_OSX -#include -#include -#endif -#include -#include -#if TARGET_OS_OSX -#include -#include -#include -#include -#endif -#include -#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c))) -#define SHA512_Init(xxx) (CC_SHA512_Init((xxx))) -#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy))) -#define SHA512_CTX CC_SHA512_CTX -#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH - -#define REPEAT 5 -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -#define HX(a, b) \ - do { \ - if ((a)) \ - HD(errno); \ - else \ - HD(b); \ - } while (0) - -#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) -#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) -#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) - -int getentropy(void *buf, size_t len); - -static int getentropy_urandom(void *buf, size_t len); -static int getentropy_fallback(void *buf, size_t len); - -int -getentropy(void *buf, size_t len) -{ - int ret = -1; - - if (len > 256) { - errno = EIO; - return (-1); - } - - /* - * Try to get entropy with /dev/urandom - * - * This can fail if the process is inside a chroot or if file - * descriptors are exhausted. - */ - ret = getentropy_urandom(buf, len); - if (ret != -1) - return (ret); - - /* - * Entropy collection via /dev/urandom and sysctl have failed. - * - * No other API exists for collecting entropy, and we have - * no failsafe way to get it on OSX that is not sensitive - * to resource exhaustion. - * - * We have very few options: - * - Even syslog_r is unsafe to call at this low level, so - * there is no way to alert the user or program. - * - Cannot call abort() because some systems have unsafe - * corefiles. - * - Could raise(SIGKILL) resulting in silent program termination. - * - Return EIO, to hint that arc4random's stir function - * should raise(SIGKILL) - * - Do the best under the circumstances.... - * - * This code path exists to bring light to the issue that OSX - * does not provide a failsafe API for entropy collection. - * - * We hope this demonstrates that OSX should consider - * providing a new failsafe API which works in a chroot or - * when file descriptors are exhausted. - */ -#undef FAIL_INSTEAD_OF_TRYING_FALLBACK -#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK - raise(SIGKILL); -#endif - ret = getentropy_fallback(buf, len); - if (ret != -1) - return (ret); - - errno = EIO; - return (ret); -} - -static int -getentropy_urandom(void *buf, size_t len) -{ - struct stat st; - size_t i; - int fd, flags; - int save_errno = errno; - -start: - - flags = O_RDONLY; -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - fd = open("/dev/urandom", flags, 0); - if (fd == -1) { - if (errno == EINTR) - goto start; - goto nodevrandom; - } -#ifndef O_CLOEXEC - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -#endif - - /* Lightly verify that the device node looks sane */ - if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) { - close(fd); - goto nodevrandom; - } - for (i = 0; i < len; ) { - size_t wanted = len - i; - ssize_t ret = read(fd, (char *)buf + i, wanted); - - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - close(fd); - goto nodevrandom; - } - i += ret; - } - close(fd); - errno = save_errno; - return (0); /* satisfied */ -nodevrandom: - errno = EIO; - return (-1); -} - -#if TARGET_OS_OSX -static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS }; -static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS }; -static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS }; -#endif -static int kmib[] = { CTL_KERN, KERN_USRSTACK }; -static int hwmib[] = { CTL_HW, HW_USERMEM }; - -static int -getentropy_fallback(void *buf, size_t len) -{ - uint8_t results[SHA512_DIGEST_LENGTH]; - int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; - static int cnt; - struct timespec ts; - struct timeval tv; - struct rusage ru; - sigset_t sigset; - struct stat st; - SHA512_CTX ctx; - static pid_t lastpid; - pid_t pid; - size_t i, ii, m; - char *p; -#if TARGET_OS_OSX - struct tcpstat tcpstat; - struct udpstat udpstat; - struct ipstat ipstat; -#endif - u_int64_t mach_time; - unsigned int idata; - void *addr; - - pid = getpid(); - if (lastpid == pid) { - faster = 1; - repeat = 2; - } else { - faster = 0; - lastpid = pid; - repeat = REPEAT; - } - for (i = 0; i < len; ) { - int j; - SHA512_Init(&ctx); - for (j = 0; j < repeat; j++) { - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - mach_time = mach_absolute_time(); - HD(mach_time); - - ii = sizeof(addr); - HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]), - &addr, &ii, NULL, 0) == -1, addr); - - ii = sizeof(idata); - HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]), - &idata, &ii, NULL, 0) == -1, idata); - -#if TARGET_OS_OSX - ii = sizeof(tcpstat); - HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]), - &tcpstat, &ii, NULL, 0) == -1, tcpstat); - - ii = sizeof(udpstat); - HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]), - &udpstat, &ii, NULL, 0) == -1, udpstat); - - ii = sizeof(ipstat); - HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]), - &ipstat, &ii, NULL, 0) == -1, ipstat); -#endif - - HX((pid = getpid()) == -1, pid); - HX((pid = getsid(pid)) == -1, pid); - HX((pid = getppid()) == -1, pid); - HX((pid = getpgid(0)) == -1, pid); - HX((e = getpriority(0, 0)) == -1, e); - - if (!faster) { - ts.tv_sec = 0; - ts.tv_nsec = 1; - (void) nanosleep(&ts, NULL); - } - - HX(sigpending(&sigset) == -1, sigset); - HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, - sigset); - - HF(getentropy); /* an addr in this library */ - HF(printf); /* an addr in libc */ - p = (char *)&p; - HD(p); /* an addr on stack */ - p = (char *)&errno; - HD(p); /* the addr of errno */ - - if (i == 0) { - struct sockaddr_storage ss; - struct statvfs stvfs; - struct termios tios; - struct statfs stfs; - socklen_t ssl; - off_t off; - - /* - * Prime-sized mappings encourage fragmentation; - * thus exposing some address entropy. - */ - struct mm { - size_t npg; - void *p; - } mm[] = { - { 17, MAP_FAILED }, { 3, MAP_FAILED }, - { 11, MAP_FAILED }, { 2, MAP_FAILED }, - { 5, MAP_FAILED }, { 3, MAP_FAILED }, - { 7, MAP_FAILED }, { 1, MAP_FAILED }, - { 57, MAP_FAILED }, { 3, MAP_FAILED }, - { 131, MAP_FAILED }, { 1, MAP_FAILED }, - }; - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - HX(mm[m].p = mmap(NULL, - mm[m].npg * pgs, - PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANON, -1, - (off_t)0), mm[m].p); - if (mm[m].p != MAP_FAILED) { - size_t mo; - - /* Touch some memory... */ - p = mm[m].p; - mo = cnt % - (mm[m].npg * pgs - 1); - p[mo] = 1; - cnt += (int)((long)(mm[m].p) - / pgs); - } - - /* Check cnts and times... */ - mach_time = mach_absolute_time(); - HD(mach_time); - cnt += (int)mach_time; - - HX((e = getrusage(RUSAGE_SELF, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - if (mm[m].p != MAP_FAILED) - munmap(mm[m].p, mm[m].npg * pgs); - mm[m].p = MAP_FAILED; - } - - HX(stat(".", &st) == -1, st); - HX(statvfs(".", &stvfs) == -1, stvfs); - HX(statfs(".", &stfs) == -1, stfs); - - HX(stat("/", &st) == -1, st); - HX(statvfs("/", &stvfs) == -1, stvfs); - HX(statfs("/", &stfs) == -1, stfs); - - HX((e = fstat(0, &st)) == -1, st); - if (e == -1) { - if (S_ISREG(st.st_mode) || - S_ISFIFO(st.st_mode) || - S_ISSOCK(st.st_mode)) { - HX(fstatvfs(0, &stvfs) == -1, - stvfs); - HX(fstatfs(0, &stfs) == -1, - stfs); - HX((off = lseek(0, (off_t)0, - SEEK_CUR)) < 0, off); - } - if (S_ISCHR(st.st_mode)) { - HX(tcgetattr(0, &tios) == -1, - tios); - } else if (S_ISSOCK(st.st_mode)) { - memset(&ss, 0, sizeof ss); - ssl = sizeof(ss); - HX(getpeername(0, - (void *)&ss, &ssl) == -1, - ss); - } - } - - HX((e = getrusage(RUSAGE_CHILDREN, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } else { - /* Subsequent hashes absorb previous result */ - HD(results); - } - - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - HD(cnt); - } - - SHA512_Final(results, &ctx); - memcpy((char *)buf + i, results, min(sizeof(results), len - i)); - i += min(sizeof(results), len - i); - } - explicit_bzero(&ctx, sizeof ctx); - explicit_bzero(results, sizeof results); - errno = save_errno; - return (0); /* satisfied */ -} diff --git a/crates/libunbound-sys/unbound/compat/getentropy_solaris.c b/crates/libunbound-sys/unbound/compat/getentropy_solaris.c deleted file mode 100644 index 1ff81629..00000000 --- a/crates/libunbound-sys/unbound/compat/getentropy_solaris.c +++ /dev/null @@ -1,441 +0,0 @@ -/* $OpenBSD: getentropy_solaris.c,v 1.4 2014/07/12 20:41:47 wouter Exp $ */ - -/* - * Copyright (c) 2014 Theo de Raadt - * Copyright (c) 2014 Bob Beck - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_SHA2_H -#include -#define SHA512_Init SHA512Init -#define SHA512_Update SHA512Update -#define SHA512_Final SHA512Final -#else -#include -#endif - -#include -#include -#include - -#define REPEAT 5 -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -#define HX(a, b) \ - do { \ - if ((a)) \ - HD(errno); \ - else \ - HD(b); \ - } while (0) - -#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) -#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) -#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) - -int getentropy(void *buf, size_t len); - -#ifdef CAN_REFERENCE_MAIN -extern int main(int, char *argv[]); -#endif -static int gotdata(char *buf, size_t len); -static int getentropy_urandom(void *buf, size_t len, const char *path, - int devfscheck); -static int getentropy_fallback(void *buf, size_t len); - -int -getentropy(void *buf, size_t len) -{ - int ret = -1; - - if (len > 256) { - errno = EIO; - return -1; - } - - /* - * Try to get entropy with /dev/urandom - * - * Solaris provides /dev/urandom as a symbolic link to - * /devices/pseudo/random@0:urandom which is provided by - * a devfs filesystem. Best practice is to use O_NOFOLLOW, - * so we must try the unpublished name directly. - * - * This can fail if the process is inside a chroot which lacks - * the devfs mount, or if file descriptors are exhausted. - */ - ret = getentropy_urandom(buf, len, - "/devices/pseudo/random@0:urandom", 1); - if (ret != -1) - return (ret); - - /* - * Unfortunately, chroot spaces on Solaris are sometimes setup - * with direct device node of the well-known /dev/urandom name - * (perhaps to avoid dragging all of devfs into the space). - * - * This can fail if the process is inside a chroot or if file - * descriptors are exhausted. - */ - ret = getentropy_urandom(buf, len, "/dev/urandom", 0); - if (ret != -1) - return (ret); - - /* - * Entropy collection via /dev/urandom has failed. - * - * No other API exists for collecting entropy, and we have - * no failsafe way to get it on Solaris that is not sensitive - * to resource exhaustion. - * - * We have very few options: - * - Even syslog_r is unsafe to call at this low level, so - * there is no way to alert the user or program. - * - Cannot call abort() because some systems have unsafe - * corefiles. - * - Could raise(SIGKILL) resulting in silent program termination. - * - Return EIO, to hint that arc4random's stir function - * should raise(SIGKILL) - * - Do the best under the circumstances.... - * - * This code path exists to bring light to the issue that Solaris - * does not provide a failsafe API for entropy collection. - * - * We hope this demonstrates that Solaris should consider - * providing a new failsafe API which works in a chroot or - * when file descriptors are exhausted. - */ -#undef FAIL_INSTEAD_OF_TRYING_FALLBACK -#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK - raise(SIGKILL); -#endif - ret = getentropy_fallback(buf, len); - if (ret != -1) - return (ret); - - errno = EIO; - return (ret); -} - -/* - * Basic sanity checking; wish we could do better. - */ -static int -gotdata(char *buf, size_t len) -{ - char any_set = 0; - size_t i; - - for (i = 0; i < len; ++i) - any_set |= buf[i]; - if (any_set == 0) - return -1; - return 0; -} - -static int -getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck) -{ - struct stat st; - size_t i; - int fd, flags; - int save_errno = errno; - -start: - - flags = O_RDONLY; -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - fd = open(path, flags, 0); - if (fd == -1) { - if (errno == EINTR) - goto start; - goto nodevrandom; - } -#ifndef O_CLOEXEC - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -#endif - - /* Lightly verify that the device node looks sane */ - if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) || - (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) { - close(fd); - goto nodevrandom; - } - for (i = 0; i < len; ) { - size_t wanted = len - i; - ssize_t ret = read(fd, (char *)buf + i, wanted); - - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) - continue; - close(fd); - goto nodevrandom; - } - i += ret; - } - close(fd); - if (gotdata(buf, len) == 0) { - errno = save_errno; - return 0; /* satisfied */ - } -nodevrandom: - errno = EIO; - return -1; -} - -static const int cl[] = { - CLOCK_REALTIME, -#ifdef CLOCK_MONOTONIC - CLOCK_MONOTONIC, -#endif -#ifdef CLOCK_MONOTONIC_RAW - CLOCK_MONOTONIC_RAW, -#endif -#ifdef CLOCK_TAI - CLOCK_TAI, -#endif -#ifdef CLOCK_VIRTUAL - CLOCK_VIRTUAL, -#endif -#ifdef CLOCK_UPTIME - CLOCK_UPTIME, -#endif -#ifdef CLOCK_PROCESS_CPUTIME_ID - CLOCK_PROCESS_CPUTIME_ID, -#endif -#ifdef CLOCK_THREAD_CPUTIME_ID - CLOCK_THREAD_CPUTIME_ID, -#endif -}; - -static int -getentropy_fallback(void *buf, size_t len) -{ - uint8_t results[SHA512_DIGEST_LENGTH]; - int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; - static int cnt; - struct timespec ts; - struct timeval tv; - double loadavg[3]; - struct rusage ru; - sigset_t sigset; - struct stat st; - SHA512_CTX ctx; - static pid_t lastpid; - pid_t pid; - size_t i, ii, m; - char *p; - - pid = getpid(); - if (lastpid == pid) { - faster = 1; - repeat = 2; - } else { - faster = 0; - lastpid = pid; - repeat = REPEAT; - } - for (i = 0; i < len; ) { - int j; - SHA512_Init(&ctx); - for (j = 0; j < repeat; j++) { - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) - HX(clock_gettime(cl[ii], &ts) == -1, ts); - - HX((pid = getpid()) == -1, pid); - HX((pid = getsid(pid)) == -1, pid); - HX((pid = getppid()) == -1, pid); - HX((pid = getpgid(0)) == -1, pid); - HX((e = getpriority(0, 0)) == -1, e); - HX((getloadavg(loadavg, 3) == -1), loadavg); - - if (!faster) { - ts.tv_sec = 0; - ts.tv_nsec = 1; - (void) nanosleep(&ts, NULL); - } - - HX(sigpending(&sigset) == -1, sigset); - HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, - sigset); - -#ifdef CAN_REFERENCE_MAIN - HF(main); /* an addr in program */ -#endif - HF(getentropy); /* an addr in this library */ - HF(printf); /* an addr in libc */ - p = (char *)&p; - HD(p); /* an addr on stack */ - p = (char *)&errno; - HD(p); /* the addr of errno */ - - if (i == 0) { - struct sockaddr_storage ss; - struct statvfs stvfs; - struct termios tios; - socklen_t ssl; - off_t off; - - /* - * Prime-sized mappings encourage fragmentation; - * thus exposing some address entropy. - */ - struct mm { - size_t npg; - void *p; - } mm[] = { - { 17, MAP_FAILED }, { 3, MAP_FAILED }, - { 11, MAP_FAILED }, { 2, MAP_FAILED }, - { 5, MAP_FAILED }, { 3, MAP_FAILED }, - { 7, MAP_FAILED }, { 1, MAP_FAILED }, - { 57, MAP_FAILED }, { 3, MAP_FAILED }, - { 131, MAP_FAILED }, { 1, MAP_FAILED }, - }; - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - HX(mm[m].p = mmap(NULL, - mm[m].npg * pgs, - PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANON, -1, - (off_t)0), mm[m].p); - if (mm[m].p != MAP_FAILED) { - size_t mo; - - /* Touch some memory... */ - p = mm[m].p; - mo = cnt % - (mm[m].npg * pgs - 1); - p[mo] = 1; - cnt += (int)((long)(mm[m].p) - / pgs); - } - - /* Check cnts and times... */ - for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); - ii++) { - HX((e = clock_gettime(cl[ii], - &ts)) == -1, ts); - if (e != -1) - cnt += (int)ts.tv_nsec; - } - - HX((e = getrusage(RUSAGE_SELF, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } - - for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { - if (mm[m].p != MAP_FAILED) - munmap(mm[m].p, mm[m].npg * pgs); - mm[m].p = MAP_FAILED; - } - - HX(stat(".", &st) == -1, st); - HX(statvfs(".", &stvfs) == -1, stvfs); - - HX(stat("/", &st) == -1, st); - HX(statvfs("/", &stvfs) == -1, stvfs); - - HX((e = fstat(0, &st)) == -1, st); - if (e == -1) { - if (S_ISREG(st.st_mode) || - S_ISFIFO(st.st_mode) || - S_ISSOCK(st.st_mode)) { - HX(fstatvfs(0, &stvfs) == -1, - stvfs); - HX((off = lseek(0, (off_t)0, - SEEK_CUR)) < 0, off); - } - if (S_ISCHR(st.st_mode)) { - HX(tcgetattr(0, &tios) == -1, - tios); - } else if (S_ISSOCK(st.st_mode)) { - memset(&ss, 0, sizeof ss); - ssl = sizeof(ss); - HX(getpeername(0, - (void *)&ss, &ssl) == -1, - ss); - } - } - - HX((e = getrusage(RUSAGE_CHILDREN, - &ru)) == -1, ru); - if (e != -1) { - cnt += (int)ru.ru_utime.tv_sec; - cnt += (int)ru.ru_utime.tv_usec; - } - } else { - /* Subsequent hashes absorb previous result */ - HD(results); - } - - HX((e = gettimeofday(&tv, NULL)) == -1, tv); - if (e != -1) { - cnt += (int)tv.tv_sec; - cnt += (int)tv.tv_usec; - } - - HD(cnt); - } - SHA512_Final(results, &ctx); - memcpy((char *)buf + i, results, min(sizeof(results), len - i)); - i += min(sizeof(results), len - i); - } - memset(results, 0, sizeof results); - if (gotdata(buf, len) == 0) { - errno = save_errno; - return 0; /* satisfied */ - } - errno = EIO; - return -1; -} diff --git a/crates/libunbound-sys/unbound/compat/getentropy_win.c b/crates/libunbound-sys/unbound/compat/getentropy_win.c deleted file mode 100644 index 2abeb27b..00000000 --- a/crates/libunbound-sys/unbound/compat/getentropy_win.c +++ /dev/null @@ -1,59 +0,0 @@ -/* $OpenBSD: getentropy_win.c,v 1.5 2016/08/07 03:27:21 tb Exp $ */ - -/* - * Copyright (c) 2014, Theo de Raadt - * Copyright (c) 2014, Bob Beck - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Emulation of getentropy(2) as documented at: - * http://man.openbsd.org/getentropy.2 - */ - -#include -#include -#include -#include -#include -#include - -int getentropy(void *buf, size_t len); - -/* - * On Windows, CryptGenRandom is supposed to be a well-seeded - * cryptographically strong random number generator. - */ -int -getentropy(void *buf, size_t len) -{ - HCRYPTPROV provider; - - if (len > 256) { - errno = EIO; - return (-1); - } - - if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT) == 0) - goto fail; - if (CryptGenRandom(provider, len, buf) == 0) { - CryptReleaseContext(provider, 0); - goto fail; - } - CryptReleaseContext(provider, 0); - return (0); - -fail: - errno = EIO; - return (-1); -} diff --git a/crates/libunbound-sys/unbound/compat/gmtime_r.c b/crates/libunbound-sys/unbound/compat/gmtime_r.c deleted file mode 100644 index 19eb637e..00000000 --- a/crates/libunbound-sys/unbound/compat/gmtime_r.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision. - * localtime.c 7.78. - * tzfile.h 1.8 - * adapted to be replacement gmtime_r. - */ -#include "config.h" - -#ifdef HAVE_TIME_H -#include -#endif - -#define MONSPERYEAR 12 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERMIN 60 -#define SECSPERHOUR (60*60) -#define SECSPERDAY (24*60*60) -#define DAYSPERWEEK 7 -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -static const int mon_lengths[2][MONSPERYEAR] = { - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -}; - -static const int year_lengths[2] = { - DAYSPERNYEAR, DAYSPERLYEAR -}; - -static void -timesub(timep, offset, tmp) -const time_t * const timep; -const long offset; -struct tm * const tmp; -{ - long days; - long rem; - long y; - int yleap; - const int * ip; - - days = *timep / SECSPERDAY; - rem = *timep % SECSPERDAY; - rem += (offset); - while (rem < 0) { - rem += SECSPERDAY; - --days; - } - while (rem >= SECSPERDAY) { - rem -= SECSPERDAY; - ++days; - } - tmp->tm_hour = (int) (rem / SECSPERHOUR); - rem = rem % SECSPERHOUR; - tmp->tm_min = (int) (rem / SECSPERMIN); - /* - ** A positive leap second requires a special - ** representation. This uses "... ??:59:60" et seq. - */ - tmp->tm_sec = (int) (rem % SECSPERMIN) ; - tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); - if (tmp->tm_wday < 0) - tmp->tm_wday += DAYSPERWEEK; - y = EPOCH_YEAR; -#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) - while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { - long newy; - - newy = y + days / DAYSPERNYEAR; - if (days < 0) - --newy; - days -= (newy - y) * DAYSPERNYEAR + - LEAPS_THRU_END_OF(newy - 1) - - LEAPS_THRU_END_OF(y - 1); - y = newy; - } - tmp->tm_year = y - TM_YEAR_BASE; - tmp->tm_yday = (int) days; - ip = mon_lengths[yleap]; - for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) - days = days - (long) ip[tmp->tm_mon]; - tmp->tm_mday = (int) (days + 1); - tmp->tm_isdst = 0; -} - -/* -* Re-entrant version of gmtime. -*/ -struct tm * gmtime_r(const time_t* timep, struct tm *tm) -{ - timesub(timep, 0L, tm); - return tm; -} diff --git a/crates/libunbound-sys/unbound/compat/inet_aton.c b/crates/libunbound-sys/unbound/compat/inet_aton.c deleted file mode 100644 index e93fe8d7..00000000 --- a/crates/libunbound-sys/unbound/compat/inet_aton.c +++ /dev/null @@ -1,182 +0,0 @@ -/* From openssh4.3p2 compat/inet_aton.c */ -/* - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ - -/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */ - -#include - -#if !defined(HAVE_INET_ATON) - -#include -#include -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#include - -#if 0 -/* - * Ascii internet address interpretation routine. - * The value returned is in network order. - */ -in_addr_t -inet_addr(const char *cp) -{ - struct in_addr val; - - if (inet_aton(cp, &val)) - return (val.s_addr); - return (INADDR_NONE); -} -#endif - -/* - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(const char *cp, struct in_addr *addr) -{ - uint32_t val; - int base, n; - char c; - unsigned int parts[4]; - unsigned int *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, isdigit=decimal. - */ - if (!isdigit((unsigned char)c)) - return (0); - val = 0; base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') - base = 16, c = *++cp; - else - base = 8; - } - for (;;) { - if (isascii((unsigned char)c) && isdigit((unsigned char)c)) { - val = (val * base) + (c - '0'); - c = *++cp; - } else if (base == 16 && isascii((unsigned char)c) && isxdigit((unsigned char)c)) { - val = (val << 4) | - (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); - c = *++cp; - } else - break; - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) - return (0); - *pp++ = val; - c = *++cp; - } else - break; - } - /* - * Check for trailing characters. - */ - if (c != '\0' && (!isascii((unsigned char)c) || !isspace((unsigned char)c))) - return (0); - /* - * Concoct the address according to - * the number of parts specified. - */ - n = pp - parts + 1; - switch (n) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if ((val > 0xffffff) || (parts[0] > 0xff)) - return (0); - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - if (addr) - addr->s_addr = htonl(val); - return (1); -} - -#endif /* !defined(HAVE_INET_ATON) */ diff --git a/crates/libunbound-sys/unbound/compat/inet_ntop.c b/crates/libunbound-sys/unbound/compat/inet_ntop.c deleted file mode 100644 index bd418ae7..00000000 --- a/crates/libunbound-sys/unbound/compat/inet_ntop.c +++ /dev/null @@ -1,218 +0,0 @@ -/* From openssh 4.3p2 compat/inet_ntop.c */ -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */ - -#include - -#ifndef HAVE_INET_NTOP - -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#include -#include -#include - -#ifndef IN6ADDRSZ -#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ -#endif - -#ifndef INT16SZ -#define INT16SZ 2 /* for systems without 16-bit ints */ -#endif - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static const char *inet_ntop4(const u_char *src, char *dst, size_t size); -static const char *inet_ntop6(const u_char *src, char *dst, size_t size); - -/* char * - * inet_ntop(af, src, dst, size) - * convert a network format address to presentation format. - * return: - * pointer to presentation format address (`dst'), or NULL (see errno). - * author: - * Paul Vixie, 1996. - */ -const char * -inet_ntop(int af, const void *src, char *dst, size_t size) -{ - switch (af) { - case AF_INET: - return (inet_ntop4(src, dst, size)); - case AF_INET6: - return (inet_ntop6(src, dst, size)); - default: -#ifdef EAFNOSUPPORT - errno = EAFNOSUPPORT; -#else - errno = ENOSYS; -#endif - return (NULL); - } - /* NOTREACHED */ -} - -/* const char * - * inet_ntop4(src, dst, size) - * format an IPv4 address, more or less like inet_ntoa() - * return: - * `dst' (as a const) - * notes: - * (1) uses no statics - * (2) takes a u_char* not an in_addr as input - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop4(const u_char *src, char *dst, size_t size) -{ - static const char fmt[] = "%u.%u.%u.%u"; - char tmp[sizeof "255.255.255.255"]; - int l; - - l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); - if (l <= 0 || l >= (int)size) { - errno = ENOSPC; - return (NULL); - } - strlcpy(dst, tmp, size); - return (dst); -} - -/* const char * - * inet_ntop6(src, dst, size) - * convert IPv6 binary address into presentation (printable) format - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop6(const u_char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; - char *tp, *ep; - struct { int base, len; } best, cur; - u_int words[IN6ADDRSZ / INT16SZ]; - int i; - int advance; - - /* - * Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof words); - for (i = 0; i < IN6ADDRSZ; i++) - words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); - best.base = -1; - best.len = 0; - cur.base = -1; - cur.len = 0; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { - if (words[i] == 0) { - if (cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } else { - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - } - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - if (best.base != -1 && best.len < 2) - best.base = -1; - - /* - * Format the result. - */ - tp = tmp; - ep = tmp + sizeof(tmp); - for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { - /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && - i < (best.base + best.len)) { - if (i == best.base) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - continue; - } - /* Are we following an initial run of 0x00s or any real hex? */ - if (i != 0) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) - return (NULL); - tp += strlen(tp); - break; - } - advance = snprintf(tp, ep - tp, "%x", words[i]); - if (advance <= 0 || advance >= ep - tp) - return (NULL); - tp += advance; - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { - if (tp + 1 >= ep) - return (NULL); - *tp++ = ':'; - } - if (tp + 1 >= ep) - return (NULL); - *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { - errno = ENOSPC; - return (NULL); - } - strlcpy(dst, tmp, size); - return (dst); -} - -#endif /* !HAVE_INET_NTOP */ diff --git a/crates/libunbound-sys/unbound/compat/inet_pton.c b/crates/libunbound-sys/unbound/compat/inet_pton.c deleted file mode 100644 index 15780d0b..00000000 --- a/crates/libunbound-sys/unbound/compat/inet_pton.c +++ /dev/null @@ -1,230 +0,0 @@ -/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include -#include -#include - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static int inet_pton4 (const char *src, uint8_t *dst); -static int inet_pton6 (const char *src, uint8_t *dst); - -/* - * - * The definitions we might miss. - * - */ -#ifndef NS_INT16SZ -#define NS_INT16SZ 2 -#endif - -#ifndef NS_IN6ADDRSZ -#define NS_IN6ADDRSZ 16 -#endif - -#ifndef NS_INADDRSZ -#define NS_INADDRSZ 4 -#endif - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * author: - * Paul Vixie, 1996. - */ -int -inet_pton(af, src, dst) - int af; - const char *src; - void *dst; -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, dst)); - case AF_INET6: - return (inet_pton6(src, dst)); - default: -#ifdef EAFNOSUPPORT - errno = EAFNOSUPPORT; -#else - errno = ENOSYS; -#endif - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton4(src, dst) - const char *src; - uint8_t *dst; -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - uint8_t tmp[NS_INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr(digits, ch)) != NULL) { - uint32_t new = *tp * 10 + (pch - digits); - - if (new > 255) - return (0); - *tp = new; - if (! saw_digit) { - if (++octets > 4) - return (0); - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } else - return (0); - } - if (octets < 4) - return (0); - - memcpy(dst, tmp, NS_INADDRSZ); - return (1); -} - -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton6(src, dst) - const char *src; - uint8_t *dst; -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - uint32_t val; - - memset((tp = tmp), '\0', NS_IN6ADDRSZ); - endp = tp + NS_IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if (*src == ':') - if (*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return (0); - saw_xdigit = 1; - continue; - } - if (ch == ':') { - curtok = src; - if (!saw_xdigit) { - if (colonp) - return (0); - colonp = tp; - continue; - } - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if (saw_xdigit) { - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - } - if (colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - int i; - - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return (0); - memcpy(dst, tmp, NS_IN6ADDRSZ); - return (1); -} diff --git a/crates/libunbound-sys/unbound/compat/isblank.c b/crates/libunbound-sys/unbound/compat/isblank.c deleted file mode 100644 index 8feabed4..00000000 --- a/crates/libunbound-sys/unbound/compat/isblank.c +++ /dev/null @@ -1,45 +0,0 @@ -/* isblank - compatibility implementation of isblank - * - * Copyright (c) 2015, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -/* return true for a blank character: space or tab */ -int isblank(int c); - -/* implementation of isblank. unsigned char is the argument */ -int -isblank(int c) -{ - return (c==' ' || c=='\t'); -} diff --git a/crates/libunbound-sys/unbound/compat/malloc.c b/crates/libunbound-sys/unbound/compat/malloc.c deleted file mode 100644 index d8097b13..00000000 --- a/crates/libunbound-sys/unbound/compat/malloc.c +++ /dev/null @@ -1,24 +0,0 @@ -/* Just a replacement, if the original malloc is not - GNU-compliant. See autoconf documentation. */ - -#include "config.h" -#undef malloc -#include - -#ifndef USE_WINSOCK -void *malloc (); -#else -/* provide a prototype */ -void *malloc (size_t n); -#endif - -/* Allocate an N-byte block of memory from the heap. - If N is zero, allocate a 1-byte block. */ - -void * -rpl_malloc_unbound (size_t n) -{ - if (n == 0) - n = 1; - return malloc (n); -} diff --git a/crates/libunbound-sys/unbound/compat/memcmp.c b/crates/libunbound-sys/unbound/compat/memcmp.c deleted file mode 100644 index 9446276f..00000000 --- a/crates/libunbound-sys/unbound/compat/memcmp.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * memcmp.c: memcmp compat implementation. - * - * Copyright (c) 2010, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. -*/ - -#include - -int memcmp(const void *x, const void *y, size_t n); - -int memcmp(const void *x, const void *y, size_t n) -{ - const uint8_t* x8 = (const uint8_t*)x; - const uint8_t* y8 = (const uint8_t*)y; - size_t i; - for(i=0; i y8[i]) - return 1; - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/compat/memcmp.h b/crates/libunbound-sys/unbound/compat/memcmp.h deleted file mode 100644 index c1d195cc..00000000 --- a/crates/libunbound-sys/unbound/compat/memcmp.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * memcmp.h: undef memcmp for compat. - * - * Copyright (c) 2012, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. -*/ -#ifndef COMPAT_MEMCMP_H -#define COMPAT_MEMCMP_H - -#ifdef memcmp -/* undef here otherwise autoheader messes it up in config.h */ -# undef memcmp -#endif - -#endif /* COMPAT_MEMCMP_H */ diff --git a/crates/libunbound-sys/unbound/compat/memmove.c b/crates/libunbound-sys/unbound/compat/memmove.c deleted file mode 100644 index fe319bb4..00000000 --- a/crates/libunbound-sys/unbound/compat/memmove.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * memmove.c: memmove compat implementation. - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. -*/ - -#include -#include - -void *memmove(void *dest, const void *src, size_t n); - -void *memmove(void *dest, const void *src, size_t n) -{ - uint8_t* from = (uint8_t*) src; - uint8_t* to = (uint8_t*) dest; - - if (from == to || n == 0) - return dest; - if (to > from && to-from < (int)n) { - /* to overlaps with from */ - /* */ - /* */ - /* copy in reverse, to avoid overwriting from */ - int i; - for(i=n-1; i>=0; i--) - to[i] = from[i]; - return dest; - } - if (from > to && from-to < (int)n) { - /* to overlaps with from */ - /* */ - /* */ - /* copy forwards, to avoid overwriting from */ - size_t i; - for(i=0; i - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "config.h" -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include - -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) - -void * -reallocarray(void *optr, size_t nmemb, size_t size) -{ - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - return realloc(optr, size * nmemb); -} diff --git a/crates/libunbound-sys/unbound/compat/sha512.c b/crates/libunbound-sys/unbound/compat/sha512.c deleted file mode 100644 index 744b7ac7..00000000 --- a/crates/libunbound-sys/unbound/compat/sha512.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * FILE: sha2.c - * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ - * - * Copyright (c) 2000-2001, Aaron D. Gifford - * All rights reserved. - * - * Modified by Jelte Jansen to fit in ldns, and not clash with any - * system-defined SHA code. - * Changes: - * - Renamed (external) functions and constants to fit ldns style - * - Removed _End and _Data functions - * - Added ldns_shaX(data, len, digest) convenience functions - * - Removed prototypes of _Transform functions and made those static - * Modified by Wouter, and trimmed, to provide SHA512 for getentropy_fallback. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ - */ -#include "config.h" - -#include /* memcpy()/memset() or bcopy()/bzero() */ -#include /* assert() */ - -/* do we have sha512 header defs */ -#ifndef SHA512_DIGEST_LENGTH -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA512_CTX; -#endif /* do we have sha512 header defs */ - -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, void*, size_t); -void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -unsigned char *SHA512(void *data, unsigned int data_len, unsigned char *digest); - - -/*** SHA-256/384/512 Machine Architecture Definitions *****************/ -/* - * BYTE_ORDER NOTE: - * - * Please make sure that your system defines BYTE_ORDER. If your - * architecture is little-endian, make sure it also defines - * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivalent. - * - * If your system does not define the above, then you can do so by - * hand like this: - * - * #define LITTLE_ENDIAN 1234 - * #define BIG_ENDIAN 4321 - * - * And for little-endian machines, add: - * - * #define BYTE_ORDER LITTLE_ENDIAN - * - * Or for big-endian machines: - * - * #define BYTE_ORDER BIG_ENDIAN - * - * The FreeBSD machine this was written on defines BYTE_ORDER - * appropriately by including (which in turn includes - * where the appropriate definitions are actually - * made). - */ -#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) -#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN -#endif - -typedef uint8_t sha2_byte; /* Exactly 1 byte */ -typedef uint32_t sha2_word32; /* Exactly 4 bytes */ -#ifdef S_SPLINT_S -typedef unsigned long long sha2_word64; /* lint 8 bytes */ -#else -typedef uint64_t sha2_word64; /* Exactly 8 bytes */ -#endif - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) - - -/*** ENDIAN REVERSAL MACROS *******************************************/ -#if BYTE_ORDER == LITTLE_ENDIAN -#define REVERSE32(w,x) { \ - sha2_word32 tmp = (w); \ - tmp = (tmp >> 16) | (tmp << 16); \ - (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ -} -#ifndef S_SPLINT_S -#define REVERSE64(w,x) { \ - sha2_word64 tmp = (w); \ - tmp = (tmp >> 32) | (tmp << 32); \ - tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ - ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ - (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ - ((tmp & 0x0000ffff0000ffffULL) << 16); \ -} -#else /* splint */ -#define REVERSE64(w,x) /* splint */ -#endif /* splint */ -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* - * Macro for incrementally adding the unsigned 64-bit integer n to the - * unsigned 128-bit integer (represented using a two-element array of - * 64-bit words): - */ -#define ADDINC128(w,n) { \ - (w)[0] += (sha2_word64)(n); \ - if ((w)[0] < (n)) { \ - (w)[1]++; \ - } \ -} -#ifdef S_SPLINT_S -#undef ADDINC128 -#define ADDINC128(w,n) /* splint */ -#endif - -/* - * Macros for copying blocks of memory and for zeroing out ranges - * of memory. Using these macros makes it easy to switch from - * using memset()/memcpy() and using bzero()/bcopy(). - * - * Please define either SHA2_USE_MEMSET_MEMCPY or define - * SHA2_USE_BZERO_BCOPY depending on which function set you - * choose to use: - */ -#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) -/* Default to memset()/memcpy() if no option is specified */ -#define SHA2_USE_MEMSET_MEMCPY 1 -#endif -#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) -/* Abort with an error if BOTH options are defined */ -#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! -#endif - -#ifdef SHA2_USE_MEMSET_MEMCPY -#define MEMSET_BZERO(p,l) memset((p), 0, (l)) -#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) -#endif -#ifdef SHA2_USE_BZERO_BCOPY -#define MEMSET_BZERO(p,l) bzero((p), (l)) -#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) -#endif - - -/*** THE SIX LOGICAL FUNCTIONS ****************************************/ -/* - * Bit shifting and rotation (used by the six SHA-XYZ logical functions: - * - * NOTE: The naming of R and S appears backwards here (R is a SHIFT and - * S is a ROTATION) because the SHA-256/384/512 description document - * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this - * same "backwards" definition. - */ -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ -#define R(b,x) ((x) >> (b)) -/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ -#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) - -/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* Four of six logical functions used in SHA-384 and SHA-512: */ -#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) -#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) -#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) -#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) - -/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ -/* Hash constant words K for SHA-384 and SHA-512: */ -static const sha2_word64 K512[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL -}; - -/* initial hash value H for SHA-512 */ -static const sha2_word64 sha512_initial_hash_value[8] = { - 0x6a09e667f3bcc908ULL, - 0xbb67ae8584caa73bULL, - 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, - 0x510e527fade682d1ULL, - 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, - 0x5be0cd19137e2179ULL -}; - -typedef union _ldns_sha2_buffer_union { - uint8_t* theChars; - uint64_t* theLongs; -} ldns_sha2_buffer_union; - -/*** SHA-512: *********************************************************/ -void SHA512_Init(SHA512_CTX* context) { - if (context == (SHA512_CTX*)0) { - return; - } - MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); - MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); - context->bitcount[0] = context->bitcount[1] = 0; -} - -static void SHA512_Transform(SHA512_CTX* context, - const sha2_word64* data) { - sha2_word64 a, b, c, d, e, f, g, h, s0, s1; - sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; - int j; - - /* initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert TO host byte order */ - REVERSE64(*data++, W512[j]); - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-512 compression function to update a..h with copy */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W512[(j+1)&0x0f]; - s0 = sigma0_512(s0); - s1 = W512[(j+14)&0x0f]; - s1 = sigma1_512(s1); - - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -void SHA512_Update(SHA512_CTX* context, void *datain, size_t len) { - size_t freespace, usedspace; - const sha2_byte* data = (const sha2_byte*)datain; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); - - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA512_BLOCK_LENGTH - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); - ADDINC128(context->bitcount, freespace << 3); - len -= freespace; - data += freespace; - SHA512_Transform(context, (sha2_word64*)context->buffer); - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, len); - ADDINC128(context->bitcount, len << 3); - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= SHA512_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ - SHA512_Transform(context, (sha2_word64*)data); - ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); - len -= SHA512_BLOCK_LENGTH; - data += SHA512_BLOCK_LENGTH; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->buffer, data, len); - ADDINC128(context->bitcount, len << 3); - } - /* Clean up: */ - usedspace = freespace = 0; -} - -static void SHA512_Last(SHA512_CTX* context) { - size_t usedspace; - ldns_sha2_buffer_union cast_var; - - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->bitcount[0],context->bitcount[0]); - REVERSE64(context->bitcount[1],context->bitcount[1]); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA512_BLOCK_LENGTH) { - MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - SHA512_Transform(context, (sha2_word64*)context->buffer); - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); - } - } else { - /* Prepare for final transform: */ - MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; - } - /* Store the length of input data (in bits): */ - cast_var.theChars = context->buffer; - cast_var.theLongs[SHA512_SHORT_BLOCK_LENGTH / 8] = context->bitcount[1]; - cast_var.theLongs[SHA512_SHORT_BLOCK_LENGTH / 8 + 1] = context->bitcount[0]; - - /* final transform: */ - SHA512_Transform(context, (sha2_word64*)context->buffer); -} - -void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { - sha2_word64 *d = (sha2_word64*)digest; - - /* Sanity check: */ - assert(context != (SHA512_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha2_byte*)0) { - SHA512_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); -#endif - } - - /* Zero out state data */ - MEMSET_BZERO(context, sizeof(SHA512_CTX)); -} - -unsigned char * -SHA512(void *data, unsigned int data_len, unsigned char *digest) -{ - SHA512_CTX ctx; - SHA512_Init(&ctx); - SHA512_Update(&ctx, data, data_len); - SHA512_Final(digest, &ctx); - return digest; -} diff --git a/crates/libunbound-sys/unbound/compat/snprintf.c b/crates/libunbound-sys/unbound/compat/snprintf.c deleted file mode 100644 index bab873e3..00000000 --- a/crates/libunbound-sys/unbound/compat/snprintf.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* snprintf - compatibility implementation of snprintf, vsnprintf - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include - -/* for test */ -/* #define SNPRINTF_TEST 1 */ -#ifdef SNPRINTF_TEST -#define snprintf my_snprintf -#define vsnprintf my_vsnprintf -#endif /* SNPRINTF_TEST */ - -int snprintf(char* str, size_t size, const char* format, ...); -int vsnprintf(char* str, size_t size, const char* format, va_list arg); - -/** - * Very portable snprintf implementation, limited in functionality, - * esp. for %[capital] %[nonportable] and so on. Reduced float functionality, - * mostly in formatting and range (e+-16), for %f and %g. - * - * %s, %d, %u, %i, %x, %c, %n and %% are fully supported. - * This includes width, precision, flags 0- +, and *(arg for wid,prec). - * %f, %g, %m, %p have reduced support, support for wid,prec,flags,*, but - * less floating point range, no %e formatting for %g. - */ -int snprintf(char* str, size_t size, const char* format, ...) -{ - int r; - va_list args; - va_start(args, format); - r = vsnprintf(str, size, format, args); - va_end(args); - return r; -} - -/** add padding to string */ -static void -print_pad(char** at, size_t* left, int* ret, char p, int num) -{ - while(num--) { - if(*left > 1) { - *(*at)++ = p; - (*left)--; - } - (*ret)++; - } -} - -/** get negative symbol, 0 if none */ -static char -get_negsign(int negative, int plus, int space) -{ - if(negative) - return '-'; - if(plus) - return '+'; - if(space) - return ' '; - return 0; -} - -#define PRINT_DEC_BUFSZ 32 /* 20 is enough for 64 bit decimals */ -/** print decimal into buffer, returns length */ -static int -print_dec(char* buf, int max, unsigned int value) -{ - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = '0' + value % 10; - value /= 10; - } - return i; -} - -/** print long decimal into buffer, returns length */ -static int -print_dec_l(char* buf, int max, unsigned long value) -{ - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = '0' + value % 10; - value /= 10; - } - return i; -} - -/** print long decimal into buffer, returns length */ -static int -print_dec_ll(char* buf, int max, unsigned long long value) -{ - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = '0' + value % 10; - value /= 10; - } - return i; -} - -/** print hex into buffer, returns length */ -static int -print_hex(char* buf, int max, unsigned int value) -{ - const char* h = "0123456789abcdef"; - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = h[value & 0x0f]; - value >>= 4; - } - return i; -} - -/** print long hex into buffer, returns length */ -static int -print_hex_l(char* buf, int max, unsigned long value) -{ - const char* h = "0123456789abcdef"; - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = h[value & 0x0f]; - value >>= 4; - } - return i; -} - -/** print long long hex into buffer, returns length */ -static int -print_hex_ll(char* buf, int max, unsigned long long value) -{ - const char* h = "0123456789abcdef"; - int i = 0; - if(value == 0) { - if(max > 0) { - buf[0] = '0'; - i = 1; - } - } else while(value && i < max) { - buf[i++] = h[value & 0x0f]; - value >>= 4; - } - return i; -} - -/** copy string into result, reversed */ -static void -spool_str_rev(char** at, size_t* left, int* ret, const char* buf, int len) -{ - int i = len; - while(i) { - if(*left > 1) { - *(*at)++ = buf[--i]; - (*left)--; - } else --i; - (*ret)++; - } -} - -/** copy string into result */ -static void -spool_str(char** at, size_t* left, int* ret, const char* buf, int len) -{ - int i; - for(i=0; i 1) { - *(*at)++ = buf[i]; - (*left)--; - } - (*ret)++; - } -} - -/** print number formatted */ -static void -print_num(char** at, size_t* left, int* ret, int minw, int precision, - int prgiven, int zeropad, int minus, int plus, int space, - int zero, int negative, char* buf, int len) -{ - int w = len; /* excludes minus sign */ - char s = get_negsign(negative, plus, space); - if(minus) { - /* left adjust the number into the field, space padding */ - /* calc numw = [sign][zeroes][number] */ - int numw = w; - if(precision == 0 && zero) numw = 0; - if(numw < precision) numw = precision; - if(s) numw++; - - /* sign */ - if(s) print_pad(at, left, ret, s, 1); - - /* number */ - if(precision == 0 && zero) { - /* "" for the number */ - } else { - if(w < precision) - print_pad(at, left, ret, '0', precision - w); - spool_str_rev(at, left, ret, buf, len); - } - /* spaces */ - if(numw < minw) - print_pad(at, left, ret, ' ', minw - numw); - } else { - /* pad on the left of the number */ - /* calculate numw has width of [sign][zeroes][number] */ - int numw = w; - if(precision == 0 && zero) numw = 0; - if(numw < precision) numw = precision; - if(!prgiven && zeropad && numw < minw) numw = minw; - else if(s) numw++; - - /* pad with spaces */ - if(numw < minw) - print_pad(at, left, ret, ' ', minw - numw); - /* print sign (and one less zeropad if so) */ - if(s) { - print_pad(at, left, ret, s, 1); - numw--; - } - /* pad with zeroes */ - if(w < numw) - print_pad(at, left, ret, '0', numw - w); - if(precision == 0 && zero) - return; - /* print the characters for the value */ - spool_str_rev(at, left, ret, buf, len); - } -} - -/** print %d and %i */ -static void -print_num_d(char** at, size_t* left, int* ret, int value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = (value < 0); - int zero = (value == 0); - int len = print_dec(buf, (int)sizeof(buf), - (unsigned int)(negative?-value:value)); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %ld and %li */ -static void -print_num_ld(char** at, size_t* left, int* ret, long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = (value < 0); - int zero = (value == 0); - int len = print_dec_l(buf, (int)sizeof(buf), - (unsigned long)(negative?-value:value)); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %lld and %lli */ -static void -print_num_lld(char** at, size_t* left, int* ret, long long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = (value < 0); - int zero = (value == 0); - int len = print_dec_ll(buf, (int)sizeof(buf), - (unsigned long long)(negative?-value:value)); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %u */ -static void -print_num_u(char** at, size_t* left, int* ret, unsigned int value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_dec(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %lu */ -static void -print_num_lu(char** at, size_t* left, int* ret, unsigned long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_dec_l(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %llu */ -static void -print_num_llu(char** at, size_t* left, int* ret, unsigned long long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_dec_ll(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %x */ -static void -print_num_x(char** at, size_t* left, int* ret, unsigned int value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_hex(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %lx */ -static void -print_num_lx(char** at, size_t* left, int* ret, unsigned long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_hex_l(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %llx */ -static void -print_num_llx(char** at, size_t* left, int* ret, unsigned long long value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); - int len = print_hex_ll(buf, (int)sizeof(buf), value); - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/** print %llp */ -static void -print_num_llp(char** at, size_t* left, int* ret, void* value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_DEC_BUFSZ]; - int negative = 0; - int zero = (value == 0); -#if defined(SIZE_MAX) && defined(UINT32_MAX) && (UINT32_MAX == SIZE_MAX || INT32_MAX == SIZE_MAX) - /* avoid warning about upcast on 32bit systems */ - unsigned long long llvalue = (unsigned long)value; -#else - unsigned long long llvalue = (unsigned long long)value; -#endif - int len = print_hex_ll(buf, (int)sizeof(buf), llvalue); - if(zero) { - buf[0]=')'; - buf[1]='l'; - buf[2]='i'; - buf[3]='n'; - buf[4]='('; - len = 5; - } else { - /* put '0x' in front of the (reversed) buffer result */ - if(len < PRINT_DEC_BUFSZ) - buf[len++] = 'x'; - if(len < PRINT_DEC_BUFSZ) - buf[len++] = '0'; - } - print_num(at, left, ret, minw, precision, prgiven, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -#define PRINT_FLOAT_BUFSZ 64 /* xx.yy with 20.20 about the max */ -/** spool remainder after the decimal point to buffer, in reverse */ -static int -print_remainder(char* buf, int max, double r, int prec) -{ - unsigned long long cap = 1; - unsigned long long value; - int len, i; - if(prec > 19) prec = 19; /* max we can do */ - if(max < prec) return 0; - for(i=0; i= 5) { - value++; - /* that might carry to numbers before the comma, if so, - * just ignore that rounding. failure because 64bitprintout */ - if(value >= cap) - value = cap-1; - } - len = print_dec_ll(buf, max, value); - while(len < prec) { /* pad with zeroes, e.g. if 0.0012 */ - buf[len++] = '0'; - } - if(len < max) - buf[len++] = '.'; - return len; -} - -/** spool floating point to buffer */ -static int -print_float(char* buf, int max, double value, int prec) -{ - /* as xxx.xxx if prec==0, no '.', with prec decimals after . */ - /* no conversion for NAN and INF, because we do not want to require - linking with -lm. */ - /* Thus, the conversions use 64bit integers to convert the numbers, - * which makes 19 digits before and after the decimal point the max */ - unsigned long long whole = (unsigned long long)value; - double remain = value - (double)whole; - int len = 0; - if(prec != 0) - len = print_remainder(buf, max, remain, prec); - len += print_dec_ll(buf+len, max-len, whole); - return len; -} - -/** print %f */ -static void -print_num_f(char** at, size_t* left, int* ret, double value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_FLOAT_BUFSZ]; - int negative = (value < 0); - int zero = 0; - int len; - if(!prgiven) precision = 6; - len = print_float(buf, (int)sizeof(buf), negative?-value:value, - precision); - print_num(at, left, ret, minw, 1, 0, zeropad, minus, - plus, space, zero, negative, buf, len); -} - -/* rudimentary %g support */ -static int -print_float_g(char* buf, int max, double value, int prec) -{ - unsigned long long whole = (unsigned long long)value; - double remain = value - (double)whole; - int before = 0; - int len = 0; - - /* number of digits before the decimal point */ - while(whole > 0) { - before++; - whole /= 10; - } - whole = (unsigned long long)value; - - if(prec > before && remain != 0.0) { - /* see if the last decimals are zero, if so, skip them */ - len = print_remainder(buf, max, remain, prec-before); - while(len > 0 && buf[0]=='0') { - memmove(buf, buf+1, --len); - } - } - len += print_dec_ll(buf+len, max-len, whole); - return len; -} - - -/** print %g */ -static void -print_num_g(char** at, size_t* left, int* ret, double value, - int minw, int precision, int prgiven, int zeropad, int minus, - int plus, int space) -{ - char buf[PRINT_FLOAT_BUFSZ]; - int negative = (value < 0); - int zero = 0; - int len; - if(!prgiven) precision = 6; - if(precision == 0) precision = 1; - len = print_float_g(buf, (int)sizeof(buf), negative?-value:value, - precision); - print_num(at, left, ret, minw, 1, 0, zeropad, minus, - plus, space, zero, negative, buf, len); -} - - -/** strnlen (compat implementation) */ -static int -my_strnlen(const char* s, int max) -{ - int i; - for(i=0; i 1) { - *at++ = *fmt++; - left--; - } else fmt++; - ret++; - } - - /* see if we are at end */ - if(!*fmt) break; - - /* fetch next argument % designation from format string */ - fmt++; /* skip the '%' */ - - /********************************/ - /* get the argument designation */ - /********************************/ - /* we must do this vararg stuff inside this function for - * portability. Hence, get_designation, and print_designation - * are not their own functions. */ - - /* printout designation: - * conversion specifier: x, d, u, s, c, m, p - * flags: # not supported - * 0 zeropad (on the left) - * - left adjust (right by default) - * ' ' printspace for positive number (in - position). - * + alwayssign - * fieldwidth: [1-9][0-9]* minimum field width. - * if this is * then type int next argument specifies the minwidth. - * if this is negative, the - flag is set (with positive width). - * precision: period[digits]*, %.2x. - * if this is * then type int next argument specifies the precision. - * just '.' or negative value means precision=0. - * this is mindigits to print for d, i, u, x - * this is aftercomma digits for f - * this is max number significant digits for g - * maxnumber characters to be printed for s - * length: 0-none (int), 1-l (long), 2-ll (long long) - * notsupported: hh (char), h (short), L (long double), q, j, z, t - * Does not support %m$ and *m$ argument designation as array indices. - * Does not support %#x - * - */ - minw = 0; - precision = 1; - prgiven = 0; - zeropad = 0; - minus = 0; - plus = 0; - space = 0; - length = 0; - - /* get flags in any order */ - for(;;) { - if(*fmt == '0') - zeropad = 1; - else if(*fmt == '-') - minus = 1; - else if(*fmt == '+') - plus = 1; - else if(*fmt == ' ') - space = 1; - else break; - fmt++; - } - - /* field width */ - if(*fmt == '*') { - fmt++; /* skip char */ - minw = va_arg(arg, int); - if(minw < 0) { - minus = 1; - minw = -minw; - } - } else while(*fmt >= '0' && *fmt <= '9') { - minw = minw*10 + (*fmt++)-'0'; - } - - /* precision */ - if(*fmt == '.') { - fmt++; /* skip period */ - prgiven = 1; - precision = 0; - if(*fmt == '*') { - fmt++; /* skip char */ - precision = va_arg(arg, int); - if(precision < 0) - precision = 0; - } else while(*fmt >= '0' && *fmt <= '9') { - precision = precision*10 + (*fmt++)-'0'; - } - } - - /* length */ - if(*fmt == 'l') { - fmt++; /* skip char */ - length = 1; - if(*fmt == 'l') { - fmt++; /* skip char */ - length = 2; - } - } - - /* get the conversion */ - if(!*fmt) conv = 0; - else conv = *fmt++; - - /***********************************/ - /* print that argument designation */ - /***********************************/ - switch(conv) { - case 'i': - case 'd': - if(length == 0) - print_num_d(&at, &left, &ret, va_arg(arg, int), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 1) - print_num_ld(&at, &left, &ret, va_arg(arg, long), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 2) - print_num_lld(&at, &left, &ret, - va_arg(arg, long long), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - case 'u': - if(length == 0) - print_num_u(&at, &left, &ret, - va_arg(arg, unsigned int), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 1) - print_num_lu(&at, &left, &ret, - va_arg(arg, unsigned long), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 2) - print_num_llu(&at, &left, &ret, - va_arg(arg, unsigned long long), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - case 'x': - if(length == 0) - print_num_x(&at, &left, &ret, - va_arg(arg, unsigned int), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 1) - print_num_lx(&at, &left, &ret, - va_arg(arg, unsigned long), - minw, precision, prgiven, zeropad, minus, plus, space); - else if(length == 2) - print_num_llx(&at, &left, &ret, - va_arg(arg, unsigned long long), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - case 's': - print_str(&at, &left, &ret, va_arg(arg, char*), - minw, precision, prgiven, minus); - break; - case 'c': - print_char(&at, &left, &ret, va_arg(arg, int), - minw, minus); - break; - case 'n': - /* unsupported to harden against format string - * exploitation, - * handled like an unknown format specifier. */ - /* *va_arg(arg, int*) = ret; */ - break; - case 'm': - print_str(&at, &left, &ret, strerror(errno), - minw, precision, prgiven, minus); - break; - case 'p': - print_num_llp(&at, &left, &ret, va_arg(arg, void*), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - case '%': - print_pad(&at, &left, &ret, '%', 1); - break; - case 'f': - print_num_f(&at, &left, &ret, va_arg(arg, double), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - case 'g': - print_num_g(&at, &left, &ret, va_arg(arg, double), - minw, precision, prgiven, zeropad, minus, plus, space); - break; - /* unknown */ - default: - case 0: break; - } - } - - /* zero terminate */ - if(left > 0) - *at = 0; - return ret; -} - -#ifdef SNPRINTF_TEST - -/** do tests */ -#undef snprintf -#define DOTEST(bufsz, result, retval, ...) do { \ - char buf[bufsz]; \ - printf("now test %s\n", #__VA_ARGS__); \ - int r=my_snprintf(buf, sizeof(buf), __VA_ARGS__); \ - if(r != retval || strcmp(buf, result) != 0) { \ - printf("error test(%s) was \"%s\":%d\n", \ - ""#bufsz", "#result", "#retval", "#__VA_ARGS__, \ - buf, r); \ - exit(1); \ - } \ - r=snprintf(buf, sizeof(buf), __VA_ARGS__); \ - if(r != retval || strcmp(buf, result) != 0) { \ - printf("error test(%s) differs with system, \"%s\":%d\n", \ - ""#bufsz", "#result", "#retval", "#__VA_ARGS__, \ - buf, r); \ - exit(1); \ - } \ - printf("test(\"%s\":%d) passed\n", buf, r); \ - } while(0); - -/** test program */ -int main(void) -{ - int x = 0; - - /* bufsize, expectedstring, expectedretval, snprintf arguments */ - DOTEST(1024, "hello", 5, "hello"); - DOTEST(1024, "h", 1, "h"); - /* warning from gcc for format string, but it does work - * DOTEST(1024, "", 0, ""); */ - - DOTEST(3, "he", 5, "hello"); - DOTEST(1, "", 7, "%d", 7823089); - - /* test positive numbers */ - DOTEST(1024, "0", 1, "%d", 0); - DOTEST(1024, "1", 1, "%d", 1); - DOTEST(1024, "9", 1, "%d", 9); - DOTEST(1024, "15", 2, "%d", 15); - DOTEST(1024, "ab15cd", 6, "ab%dcd", 15); - DOTEST(1024, "167", 3, "%d", 167); - DOTEST(1024, "7823089", 7, "%d", 7823089); - DOTEST(1024, " 12", 3, "%3d", 12); - DOTEST(1024, "012", 3, "%.3d", 12); - DOTEST(1024, "012", 3, "%3.3d", 12); - DOTEST(1024, "012", 3, "%03d", 12); - DOTEST(1024, " 012", 4, "%4.3d", 12); - DOTEST(1024, "", 0, "%.0d", 0); - - /* test negative numbers */ - DOTEST(1024, "-1", 2, "%d", -1); - DOTEST(1024, "-12", 3, "%3d", -12); - DOTEST(1024, " -2", 3, "%3d", -2); - DOTEST(1024, "-012", 4, "%.3d", -12); - DOTEST(1024, "-012", 4, "%3.3d", -12); - DOTEST(1024, "-012", 4, "%4.3d", -12); - DOTEST(1024, " -012", 5, "%5.3d", -12); - DOTEST(1024, "-12", 3, "%03d", -12); - DOTEST(1024, "-02", 3, "%03d", -2); - DOTEST(1024, "-15", 3, "%d", -15); - DOTEST(1024, "-7307", 5, "%d", -7307); - DOTEST(1024, "-12 ", 5, "%-5d", -12); - DOTEST(1024, "-00012", 6, "%-.5d", -12); - - /* test + and space flags */ - DOTEST(1024, "+12", 3, "%+d", 12); - DOTEST(1024, " 12", 3, "% d", 12); - - /* test %u */ - DOTEST(1024, "12", 2, "%u", 12); - DOTEST(1024, "0", 1, "%u", 0); - DOTEST(1024, "4294967295", 10, "%u", 0xffffffff); - - /* test %x */ - DOTEST(1024, "0", 1, "%x", 0); - DOTEST(1024, "c", 1, "%x", 12); - DOTEST(1024, "12ab34cd", 8, "%x", 0x12ab34cd); - - /* test %llu, %lld */ - DOTEST(1024, "18446744073709551615", 20, "%llu", - (long long)0xffffffffffffffff); - DOTEST(1024, "-9223372036854775808", 20, "%lld", - (long long)0x8000000000000000); - DOTEST(1024, "9223372036854775808", 19, "%llu", - (long long)0x8000000000000000); - - /* test %s */ - DOTEST(1024, "hello", 5, "%s", "hello"); - DOTEST(1024, " hello", 10, "%10s", "hello"); - DOTEST(1024, "hello ", 10, "%-10s", "hello"); - DOTEST(1024, "he", 2, "%.2s", "hello"); - DOTEST(1024, " he", 4, "%4.2s", "hello"); - DOTEST(1024, " h", 4, "%4.2s", "h"); - - /* test %c */ - DOTEST(1024, "a", 1, "%c", 'a'); - /* warning from gcc for format string, but it does work - DOTEST(1024, " a", 5, "%5c", 'a'); - DOTEST(1024, "a", 1, "%.0c", 'a'); */ - - /* test %n */ - DOTEST(1024, "hello", 5, "hello%n", &x); - if(x != 5) { printf("the %%n failed\n"); exit(1); } - - /* test %m */ - errno = 0; - DOTEST(1024, "Success", 7, "%m"); - - /* test %p */ - DOTEST(1024, "0x10", 4, "%p", (void*)0x10); - DOTEST(1024, "(nil)", 5, "%p", (void*)0x0); - - /* test %% */ - DOTEST(1024, "%", 1, "%%"); - - /* test %f */ - DOTEST(1024, "0.000000", 8, "%f", 0.0); - DOTEST(1024, "0.00", 4, "%.2f", 0.0); - /* differs, "-0.00" DOTEST(1024, "0.00", 4, "%.2f", -0.0); */ - DOTEST(1024, "234.00", 6, "%.2f", 234.005); - DOTEST(1024, "8973497.1246", 12, "%.4f", 8973497.12456); - DOTEST(1024, "-12.000000", 10, "%f", -12.0); - DOTEST(1024, "6", 1, "%.0f", 6.0); - - DOTEST(1024, "6", 1, "%g", 6.0); - DOTEST(1024, "6.1", 3, "%g", 6.1); - DOTEST(1024, "6.15", 4, "%g", 6.15); - - /* These format strings are from the code of NSD, Unbound, ldns */ - - DOTEST(1024, "abcdef", 6, "%s", "abcdef"); - DOTEST(1024, "005", 3, "%03u", 5); - DOTEST(1024, "12345", 5, "%03u", 12345); - DOTEST(1024, "5", 1, "%d", 5); - DOTEST(1024, "(nil)", 5, "%p", NULL); - DOTEST(1024, "12345", 5, "%ld", (long)12345); - DOTEST(1024, "12345", 5, "%lu", (long)12345); - DOTEST(1024, " 12345", 12, "%12u", (unsigned)12345); - DOTEST(1024, "12345", 5, "%u", (unsigned)12345); - DOTEST(1024, "12345", 5, "%llu", (unsigned long long)12345); - DOTEST(1024, "12345", 5, "%x", 0x12345); - DOTEST(1024, "12345", 5, "%llx", (long long)0x12345); - DOTEST(1024, "012345", 6, "%6.6d", 12345); - DOTEST(1024, "012345", 6, "%6.6u", 12345); - DOTEST(1024, "1234.54", 7, "%g", 1234.54); - DOTEST(1024, "123456789.54", 12, "%.12g", 123456789.54); - DOTEST(1024, "3456789123456.54", 16, "%.16g", 3456789123456.54); - /* %24g does not work with 24 digits, not enough accuracy, - * the first 16 digits are correct */ - DOTEST(1024, "12345", 5, "%3.3d", 12345); - DOTEST(1024, "000", 3, "%3.3d", 0); - DOTEST(1024, "001", 3, "%3.3d", 1); - DOTEST(1024, "012", 3, "%3.3d", 12); - DOTEST(1024, "-012", 4, "%3.3d", -12); - DOTEST(1024, "he", 2, "%.2s", "hello"); - DOTEST(1024, "helloworld", 10, "%s%s", "hello", "world"); - DOTEST(1024, "he", 2, "%.*s", 2, "hello"); - DOTEST(1024, " hello", 7, "%*s", 7, "hello"); - DOTEST(1024, "hello ", 7, "%*s", -7, "hello"); - DOTEST(1024, "0", 1, "%c", '0'); - DOTEST(1024, "A", 1, "%c", 'A'); - DOTEST(1024, "", 1, "%c", 0); - DOTEST(1024, "\010", 1, "%c", 8); - DOTEST(1024, "%", 1, "%%"); - DOTEST(1024, "0a", 2, "%02x", 0x0a); - DOTEST(1024, "bd", 2, "%02x", 0xbd); - DOTEST(1024, "12", 2, "%02ld", (long)12); - DOTEST(1024, "02", 2, "%02ld", (long)2); - DOTEST(1024, "02", 2, "%02u", (unsigned)2); - DOTEST(1024, "765432", 6, "%05u", (unsigned)765432); - DOTEST(1024, "10.234", 6, "%0.3f", 10.23421); - DOTEST(1024, "123456.234", 10, "%0.3f", 123456.23421); - DOTEST(1024, "123456789.234", 13, "%0.3f", 123456789.23421); - DOTEST(1024, "123456.23", 9, "%.2f", 123456.23421); - DOTEST(1024, "123456", 6, "%.0f", 123456.23421); - DOTEST(1024, "0123", 4, "%.4x", 0x0123); - DOTEST(1024, "00000123", 8, "%.8x", 0x0123); - DOTEST(1024, "ffeb0cde", 8, "%.8x", 0xffeb0cde); - DOTEST(1024, " 987654321", 10, "%10lu", (unsigned long)987654321); - DOTEST(1024, " 987654321", 12, "%12lu", (unsigned long)987654321); - DOTEST(1024, "987654321", 9, "%i", 987654321); - DOTEST(1024, "-87654321", 9, "%i", -87654321); - DOTEST(1024, "hello ", 16, "%-16s", "hello"); - DOTEST(1024, " ", 16, "%-16s", ""); - DOTEST(1024, "a ", 16, "%-16s", "a"); - DOTEST(1024, "foobarfoobar ", 16, "%-16s", "foobarfoobar"); - DOTEST(1024, "foobarfoobarfoobar", 18, "%-16s", "foobarfoobarfoobar"); - - /* combined expressions */ - DOTEST(1024, "foo 1.0 size 512 edns", 21, - "foo %s size %d %s%s", "1.0", 512, "", "edns"); - DOTEST(15, "foo 1.0 size 5", 21, - "foo %s size %d %s%s", "1.0", 512, "", "edns"); - DOTEST(1024, "packet 1203ceff id", 18, - "packet %2.2x%2.2x%2.2x%2.2x id", 0x12, 0x03, 0xce, 0xff); - DOTEST(1024, "/tmp/testbound_123abcd.tmp", 26, "/tmp/testbound_%u%s%s.tmp", 123, "ab", "cd"); - - return 0; -} -#endif /* SNPRINTF_TEST */ diff --git a/crates/libunbound-sys/unbound/compat/strlcat.c b/crates/libunbound-sys/unbound/compat/strlcat.c deleted file mode 100644 index 0bea9250..00000000 --- a/crates/libunbound-sys/unbound/compat/strlcat.c +++ /dev/null @@ -1,73 +0,0 @@ -/* compat/strlcat.c */ - -/*- - * Copyright (c) 1998 Todd C. Miller - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ - -#include "config.h" -#ifndef HAVE_STRLCAT - -#include -#include - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - -#endif /* !HAVE_STRLCAT */ diff --git a/crates/libunbound-sys/unbound/compat/strlcpy.c b/crates/libunbound-sys/unbound/compat/strlcpy.c deleted file mode 100644 index acd306a1..00000000 --- a/crates/libunbound-sys/unbound/compat/strlcpy.c +++ /dev/null @@ -1,57 +0,0 @@ -/* from openssh 4.3p2 compat/strlcpy.c */ -/* - * Copyright (c) 1998 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ - -#include -#ifndef HAVE_STRLCPY - -#include -#include - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -#endif /* !HAVE_STRLCPY */ diff --git a/crates/libunbound-sys/unbound/compat/strptime.c b/crates/libunbound-sys/unbound/compat/strptime.c deleted file mode 100644 index 10ec3157..00000000 --- a/crates/libunbound-sys/unbound/compat/strptime.c +++ /dev/null @@ -1,345 +0,0 @@ -/** strptime workaround (for oa macos leopard) - * This strptime follows the man strptime (2001-11-12) - * conforming to SUSv2, POSIX.1-2001 - * - * This very simple version of strptime has no: - * - E alternatives - * - O alternatives - * - Glibc additions - * - Does not process week numbers - * - Does not properly processes year day - * - * LICENSE - * Copyright (c) 2008, NLnet Labs, Matthijs Mekking - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of NLnetLabs nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - **/ - -#include "config.h" - -#ifndef HAVE_CONFIG_H -#include -#endif - -#ifndef STRPTIME_WORKS - -#define TM_YEAR_BASE 1900 - -#include -#include - -static const char *abb_weekdays[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL -}; -static const char *full_weekdays[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", NULL -}; -static const char *abb_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL -}; -static const char *full_months[] = { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", NULL -}; -static const char *ampm[] = { - "am", "pm", NULL -}; - -static int -match_string(const char **buf, const char **strs) -{ - int i = 0; - - for (i = 0; strs[i] != NULL; i++) { - int len = strlen(strs[i]); - if (strncasecmp (*buf, strs[i], len) == 0) { - *buf += len; - return i; - } - } - return -1; -} - -static int -str2int(const char **buf, int max) -{ - int ret=0, count=0; - - while (*buf[0] != '\0' && isdigit((unsigned char)*buf[0]) && counttm_wday = ret; - break; - case 'b': /* month name, abbreviated or full */ - case 'B': - case 'h': - ret = match_string(&s, full_months); - if (ret < 0) - ret = match_string(&s, abb_months); - if (ret < 0) { - return NULL; - } - tm->tm_mon = ret; - break; - case 'c': /* date and time representation */ - if (!(s = unbound_strptime(s, "%x %X", tm))) { - return NULL; - } - break; - case 'C': /* century number */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 99) { /* must be in [00,99] */ - return NULL; - } - - if (split_year) { - tm->tm_year = ret*100 + (tm->tm_year%100); - } - else { - tm->tm_year = ret*100 - TM_YEAR_BASE; - split_year = 1; - } - break; - case 'd': /* day of month */ - case 'e': - ret = str2int(&s, 2); - if (ret < 1 || ret > 31) { /* must be in [01,31] */ - return NULL; - } - tm->tm_mday = ret; - break; - case 'D': /* equivalent to %m/%d/%y */ - if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { - return NULL; - } - break; - case 'H': /* hour */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 23) { /* must be in [00,23] */ - return NULL; - } - tm->tm_hour = ret; - break; - case 'I': /* 12hr clock hour */ - ret = str2int(&s, 2); - if (ret < 1 || ret > 12) { /* must be in [01,12] */ - return NULL; - } - if (ret == 12) /* actually [0,11] */ - ret = 0; - tm->tm_hour = ret; - break; - case 'j': /* day of year */ - ret = str2int(&s, 2); - if (ret < 1 || ret > 366) { /* must be in [001,366] */ - return NULL; - } - tm->tm_yday = ret; - break; - case 'm': /* month */ - ret = str2int(&s, 2); - if (ret < 1 || ret > 12) { /* must be in [01,12] */ - return NULL; - } - /* months go from 0-11 */ - tm->tm_mon = (ret-1); - break; - case 'M': /* minute */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 59) { /* must be in [00,59] */ - return NULL; - } - tm->tm_min = ret; - break; - case 'n': /* arbitrary whitespace */ - case 't': - while (isspace((unsigned char)*s)) - s++; - break; - case 'p': /* am pm */ - ret = match_string(&s, ampm); - if (ret < 0) { - return NULL; - } - if (tm->tm_hour < 0 || tm->tm_hour > 11) { /* %I */ - return NULL; - } - - if (ret == 1) /* pm */ - tm->tm_hour += 12; - break; - case 'r': /* equivalent of %I:%M:%S %p */ - if (!(s = unbound_strptime(s, "%I:%M:%S %p", tm))) { - return NULL; - } - break; - case 'R': /* equivalent of %H:%M */ - if (!(s = unbound_strptime(s, "%H:%M", tm))) { - return NULL; - } - break; - case 'S': /* seconds */ - ret = str2int(&s, 2); - /* 60 may occur for leap seconds */ - /* earlier 61 was also allowed */ - if (ret < 0 || ret > 60) { /* must be in [00,60] */ - return NULL; - } - tm->tm_sec = ret; - break; - case 'T': /* equivalent of %H:%M:%S */ - if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { - return NULL; - } - break; - case 'U': /* week number, with the first Sun of Jan being w1 */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 53) { /* must be in [00,53] */ - return NULL; - } - /** it is hard (and not necessary for nsd) to determine time - * data from week number. - **/ - break; - case 'w': /* day of week */ - ret = str2int(&s, 1); - if (ret < 0 || ret > 6) { /* must be in [0,6] */ - return NULL; - } - tm->tm_wday = ret; - break; - case 'W': /* week number, with the first Mon of Jan being w1 */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 53) { /* must be in [00,53] */ - return NULL; - } - /** it is hard (and not necessary for nsd) to determine time - * data from week number. - **/ - break; - case 'x': /* date format */ - if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { - return NULL; - } - break; - case 'X': /* time format */ - if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { - return NULL; - } - break; - case 'y': /* last two digits of a year */ - ret = str2int(&s, 2); - if (ret < 0 || ret > 99) { /* must be in [00,99] */ - return NULL; - } - if (split_year) { - tm->tm_year = ((tm->tm_year/100) * 100) + ret; - } - else { - split_year = 1; - - /** currently: - * if in [0,68] we are in 21th century, - * if in [69,99] we are in 20th century. - **/ - if (ret < 69) /* 2000 */ - ret += 100; - tm->tm_year = ret; - } - break; - case 'Y': /* year */ - ret = str2int(&s, 4); - if (ret < 0 || ret > 9999) { - return NULL; - } - tm->tm_year = ret - TM_YEAR_BASE; - break; - case '\0': - default: /* unsupported, cannot match format */ - return NULL; - break; - } - } - else { /* literal */ - /* if input cannot match format, return NULL */ - if (*s != c) - return NULL; - s++; - } - - format++; - } - - /* return pointer to remainder of s */ - return (char*) s; -} - -#endif /* STRPTIME_WORKS */ diff --git a/crates/libunbound-sys/unbound/compat/strsep.c b/crates/libunbound-sys/unbound/compat/strsep.c deleted file mode 100644 index 4e3f05c5..00000000 --- a/crates/libunbound-sys/unbound/compat/strsep.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * strsep implementation for compatibility. - * - * LICENSE - * Copyright (c) 2016, NLnet Labs - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of NLnetLabs nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - **/ - -#include "config.h" - -/** see if character is in the delimiter array */ -static int -in_delim(char c, const char* delim) -{ - const char* p; - if(!delim) - return 0; - for(p=delim; *p; p++) { - if(*p == c) - return 1; - } - return 0; -} - -char *strsep(char **stringp, const char *delim) -{ - char* s; - char* orig; - if(stringp == NULL || *stringp == NULL) - return NULL; - orig = *stringp; - s = *stringp; - while(*s && !in_delim(*s, delim)) - s++; - if(*s) { - *s = 0; - *stringp = s+1; - } else { - *stringp = NULL; - } - return orig; -} diff --git a/crates/libunbound-sys/unbound/config.h.in b/crates/libunbound-sys/unbound/config.h.in deleted file mode 100644 index f31354d0..00000000 --- a/crates/libunbound-sys/unbound/config.h.in +++ /dev/null @@ -1,1456 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* apply the noreturn attribute to a function that exits the program */ -#undef ATTR_NORETURN - -/* apply the weak attribute to a symbol */ -#undef ATTR_WEAK - -/* Directory to chroot to */ -#undef CHROOT_DIR - -/* Define this to enable client subnet option. */ -#undef CLIENT_SUBNET - -/* Do sha512 definitions in config.h */ -#undef COMPAT_SHA512 - -/* Command line arguments used with configure */ -#undef CONFCMDLINE - -/* Pathname to the Unbound configuration file */ -#undef CONFIGFILE - -/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work - */ -#undef DARWIN_BROKEN_SETREUID - -/* Whether daemon is deprecated */ -#undef DEPRECATED_DAEMON - -/* Deprecate RSA 1024 bit length, makes that an unsupported key */ -#undef DEPRECATE_RSA_1024 - -/* Define this to enable kernel based UDP source port randomization. */ -#undef DISABLE_EXPLICIT_PORT_RANDOMISATION - -/* default dnstap socket path */ -#undef DNSTAP_SOCKET_PATH - -/* Define if you want to use debug lock checking (slow). */ -#undef ENABLE_LOCK_CHECKS - -/* Define this if you enabled-allsymbols from libunbound to link binaries to - it for smaller install size, but the libunbound export table is polluted by - internal symbols */ -#undef EXPORT_ALL_SYMBOLS - -/* Define to 1 if you have the `accept4' function. */ -#undef HAVE_ACCEPT4 - -/* Define to 1 if you have the `arc4random' function. */ -#undef HAVE_ARC4RANDOM - -/* Define to 1 if you have the `arc4random_uniform' function. */ -#undef HAVE_ARC4RANDOM_UNIFORM - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* Whether the C compiler accepts the "format" attribute */ -#undef HAVE_ATTR_FORMAT - -/* Whether the C compiler accepts the "noreturn" attribute */ -#undef HAVE_ATTR_NORETURN - -/* Whether the C compiler accepts the "unused" attribute */ -#undef HAVE_ATTR_UNUSED - -/* Whether the C compiler accepts the "weak" attribute */ -#undef HAVE_ATTR_WEAK - -/* If we have be64toh */ -#undef HAVE_BE64TOH - -/* Define to 1 if you have the `BIO_set_callback_ex' function. */ -#undef HAVE_BIO_SET_CALLBACK_EX - -/* Define to 1 if you have the header file. */ -#undef HAVE_BSD_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_BSD_STRING_H - -/* Define to 1 if you have the `chown' function. */ -#undef HAVE_CHOWN - -/* Define to 1 if you have the `chroot' function. */ -#undef HAVE_CHROOT - -/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ -#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - -/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */ -#undef HAVE_CRYPTO_THREADID_SET_CALLBACK - -/* Define to 1 if you have the `ctime_r' function. */ -#undef HAVE_CTIME_R - -/* Define to 1 if you have the `daemon' function. */ -#undef HAVE_DAEMON - -/* Define to 1 if you have the declaration of `arc4random', and to 0 if you - don't. */ -#undef HAVE_DECL_ARC4RANDOM - -/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 - if you don't. */ -#undef HAVE_DECL_ARC4RANDOM_UNIFORM - -/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if - you don't. */ -#undef HAVE_DECL_EVSIGNAL_ASSIGN - -/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you - don't. */ -#undef HAVE_DECL_INET_NTOP - -/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you - don't. */ -#undef HAVE_DECL_INET_PTON - -/* Define to 1 if you have the declaration of `nghttp2_session_server_new', - and to 0 if you don't. */ -#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW - -/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_ED25519 - -/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_ED448 - -/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_SECP384R1 - -/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 - if you don't. */ -#undef HAVE_DECL_NID_X9_62_PRIME256V1 - -/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you - don't. */ -#undef HAVE_DECL_REALLOCARRAY - -/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you - don't. */ -#undef HAVE_DECL_REDISCONNECT - -/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 - if you don't. */ -#undef HAVE_DECL_SK_SSL_COMP_POP_FREE - -/* Define to 1 if you have the declaration of - `SSL_COMP_get_compression_methods', and to 0 if you don't. */ -#undef HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS - -/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to - 0 if you don't. */ -#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO - -/* Define to 1 if you have the declaration of `strlcat', and to 0 if you - don't. */ -#undef HAVE_DECL_STRLCAT - -/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you - don't. */ -#undef HAVE_DECL_STRLCPY - -/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if - you don't. */ -#undef HAVE_DECL_XML_STOPPARSER - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the `DSA_SIG_set0' function. */ -#undef HAVE_DSA_SIG_SET0 - -/* Define to 1 if you have the header file. */ -#undef HAVE_ENDIAN_H - -/* Define to 1 if you have the `endprotoent' function. */ -#undef HAVE_ENDPROTOENT - -/* Define to 1 if you have the `endpwent' function. */ -#undef HAVE_ENDPWENT - -/* Define to 1 if you have the `endservent' function. */ -#undef HAVE_ENDSERVENT - -/* Define to 1 if you have the `ENGINE_cleanup' function. */ -#undef HAVE_ENGINE_CLEANUP - -/* Define to 1 if you have the `ERR_free_strings' function. */ -#undef HAVE_ERR_FREE_STRINGS - -/* Define to 1 if you have the `ERR_load_crypto_strings' function. */ -#undef HAVE_ERR_LOAD_CRYPTO_STRINGS - -/* Define to 1 if you have the `event_assign' function. */ -#undef HAVE_EVENT_ASSIGN - -/* Define to 1 if you have the `event_base_free' function. */ -#undef HAVE_EVENT_BASE_FREE - -/* Define to 1 if you have the `event_base_get_method' function. */ -#undef HAVE_EVENT_BASE_GET_METHOD - -/* Define to 1 if you have the `event_base_new' function. */ -#undef HAVE_EVENT_BASE_NEW - -/* Define to 1 if you have the `event_base_once' function. */ -#undef HAVE_EVENT_BASE_ONCE - -/* Define to 1 if you have the header file. */ -#undef HAVE_EVENT_H - -/* Define to 1 if you have the `EVP_aes_256_cbc' function. */ -#undef HAVE_EVP_AES_256_CBC - -/* Define to 1 if you have the `EVP_cleanup' function. */ -#undef HAVE_EVP_CLEANUP - -/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled' - function. */ -#undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED - -/* Define to 1 if you have the `EVP_DigestVerify' function. */ -#undef HAVE_EVP_DIGESTVERIFY - -/* Define to 1 if you have the `EVP_dss1' function. */ -#undef HAVE_EVP_DSS1 - -/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ -#undef HAVE_EVP_ENCRYPTINIT_EX - -/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */ -#undef HAVE_EVP_MAC_CTX_SET_PARAMS - -/* Define to 1 if you have the `EVP_MD_CTX_new' function. */ -#undef HAVE_EVP_MD_CTX_NEW - -/* Define to 1 if you have the `EVP_sha1' function. */ -#undef HAVE_EVP_SHA1 - -/* Define to 1 if you have the `EVP_sha256' function. */ -#undef HAVE_EVP_SHA256 - -/* Define to 1 if you have the `EVP_sha512' function. */ -#undef HAVE_EVP_SHA512 - -/* Define to 1 if you have the `ev_default_loop' function. */ -#undef HAVE_EV_DEFAULT_LOOP - -/* Define to 1 if you have the `ev_loop' function. */ -#undef HAVE_EV_LOOP - -/* Define to 1 if you have the header file. */ -#undef HAVE_EXPAT_H - -/* Define to 1 if you have the `explicit_bzero' function. */ -#undef HAVE_EXPLICIT_BZERO - -/* Define to 1 if you have the `fcntl' function. */ -#undef HAVE_FCNTL - -/* Define to 1 if you have the `FIPS_mode' function. */ -#undef HAVE_FIPS_MODE - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ -#undef HAVE_FSEEKO - -/* Define to 1 if you have the `fsync' function. */ -#undef HAVE_FSYNC - -/* Whether getaddrinfo is available */ -#undef HAVE_GETADDRINFO - -/* Define to 1 if you have the `getauxval' function. */ -#undef HAVE_GETAUXVAL - -/* Define to 1 if you have the `getentropy' function. */ -#undef HAVE_GETENTROPY - -/* Define to 1 if you have the `getifaddrs' function. */ -#undef HAVE_GETIFADDRS - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the `getpwnam' function. */ -#undef HAVE_GETPWNAM - -/* Define to 1 if you have the `getrlimit' function. */ -#undef HAVE_GETRLIMIT - -/* Define to 1 if you have the `gettid' function. */ -#undef HAVE_GETTID - -/* Define to 1 if you have the `glob' function. */ -#undef HAVE_GLOB - -/* Define to 1 if you have the header file. */ -#undef HAVE_GLOB_H - -/* Define to 1 if you have the `gmtime_r' function. */ -#undef HAVE_GMTIME_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_GRP_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_HIREDIS_HIREDIS_H - -/* Define to 1 if you have the `HMAC_Init_ex' function. */ -#undef HAVE_HMAC_INIT_EX - -/* If we have htobe64 */ -#undef HAVE_HTOBE64 - -/* Define to 1 if you have the header file. */ -#undef HAVE_IFADDRS_H - -/* Define to 1 if you have the `if_nametoindex' function. */ -#undef HAVE_IF_NAMETOINDEX - -/* Define to 1 if you have the `inet_aton' function. */ -#undef HAVE_INET_ATON - -/* Define to 1 if you have the `inet_ntop' function. */ -#undef HAVE_INET_NTOP - -/* Define to 1 if you have the `inet_pton' function. */ -#undef HAVE_INET_PTON - -/* Define to 1 if you have the `initgroups' function. */ -#undef HAVE_INITGROUPS - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* if the function 'ioctlsocket' is available */ -#undef HAVE_IOCTLSOCKET - -/* Define to 1 if you have the header file. */ -#undef HAVE_IPHLPAPI_H - -/* Define to 1 if you have the `isblank' function. */ -#undef HAVE_ISBLANK - -/* Define to 1 if you have the `kill' function. */ -#undef HAVE_KILL - -/* Use portable libbsd functions */ -#undef HAVE_LIBBSD - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIBKERN_OSBYTEORDER_H - -/* Define if we have LibreSSL */ -#undef HAVE_LIBRESSL - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_NET_TSTAMP_H - -/* Define to 1 if you have the `localtime_r' function. */ -#undef HAVE_LOCALTIME_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_LOGIN_CAP_H - -/* If have GNU libc compatible malloc */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETDB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_TCP_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETIOAPI_H - -/* Use libnettle for crypto */ -#undef HAVE_NETTLE - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETTLE_DSA_COMPAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETTLE_EDDSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NET_IF_H - -/* Define this to use nghttp2 client. */ -#undef HAVE_NGHTTP2 - -/* Define to 1 if you have the header file. */ -#undef HAVE_NGHTTP2_NGHTTP2_H - -/* Use libnss for crypto */ -#undef HAVE_NSS - -/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */ -#undef HAVE_OPENSSL_ADD_ALL_DIGESTS - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_BN_H - -/* Define to 1 if you have the `OPENSSL_config' function. */ -#undef HAVE_OPENSSL_CONFIG - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_CONF_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_CORE_NAMES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_DH_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_DSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ENGINE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ERR_H - -/* Define to 1 if you have the `OPENSSL_init_crypto' function. */ -#undef HAVE_OPENSSL_INIT_CRYPTO - -/* Define to 1 if you have the `OPENSSL_init_ssl' function. */ -#undef HAVE_OPENSSL_INIT_SSL - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_PARAM_BUILD_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RAND_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_SSL_H - -/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */ -#undef HAVE_OSSL_PARAM_BLD_NEW - -/* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL - -/* Define to 1 if you have the header file. */ -#undef HAVE_POLL_H - -/* Define if you have POSIX threads libraries and header files. */ -#undef HAVE_PTHREAD - -/* Have PTHREAD_PRIO_INHERIT. */ -#undef HAVE_PTHREAD_PRIO_INHERIT - -/* Define to 1 if the system has the type `pthread_rwlock_t'. */ -#undef HAVE_PTHREAD_RWLOCK_T - -/* Define to 1 if the system has the type `pthread_spinlock_t'. */ -#undef HAVE_PTHREAD_SPINLOCK_T - -/* Define to 1 if you have the header file. */ -#undef HAVE_PWD_H - -/* Define if you have Python libraries and header files. */ -#undef HAVE_PYTHON - -/* Define to 1 if you have the `random' function. */ -#undef HAVE_RANDOM - -/* Define to 1 if you have the `RAND_cleanup' function. */ -#undef HAVE_RAND_CLEANUP - -/* If we have reallocarray(3) */ -#undef HAVE_REALLOCARRAY - -/* Define to 1 if you have the `recvmsg' function. */ -#undef HAVE_RECVMSG - -/* Define to 1 if you have the `sendmsg' function. */ -#undef HAVE_SENDMSG - -/* Define to 1 if you have the `setregid' function. */ -#undef HAVE_SETREGID - -/* Define to 1 if you have the `setresgid' function. */ -#undef HAVE_SETRESGID - -/* Define to 1 if you have the `setresuid' function. */ -#undef HAVE_SETRESUID - -/* Define to 1 if you have the `setreuid' function. */ -#undef HAVE_SETREUID - -/* Define to 1 if you have the `setrlimit' function. */ -#undef HAVE_SETRLIMIT - -/* Define to 1 if you have the `setsid' function. */ -#undef HAVE_SETSID - -/* Define to 1 if you have the `setusercontext' function. */ -#undef HAVE_SETUSERCONTEXT - -/* Define to 1 if you have the `SHA512_Update' function. */ -#undef HAVE_SHA512_UPDATE - -/* Define to 1 if you have the `shmget' function. */ -#undef HAVE_SHMGET - -/* Define to 1 if you have the `sigprocmask' function. */ -#undef HAVE_SIGPROCMASK - -/* Define to 1 if you have the `sleep' function. */ -#undef HAVE_SLEEP - -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - -/* Define to 1 if you have the `socketpair' function. */ -#undef HAVE_SOCKETPAIR - -/* Using Solaris threads */ -#undef HAVE_SOLARIS_THREADS - -/* Define to 1 if you have the `srandom' function. */ -#undef HAVE_SRANDOM - -/* Define if you have the SSL libraries installed. */ -#undef HAVE_SSL - -/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */ -#undef HAVE_SSL_CTX_SET_ALPN_PROTOS - -/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */ -#undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB - -/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */ -#undef HAVE_SSL_CTX_SET_CIPHERSUITES - -/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */ -#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL - -/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb' - function. */ -#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - -/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */ -#undef HAVE_SSL_GET0_ALPN_SELECTED - -/* Define to 1 if you have the `SSL_get0_peername' function. */ -#undef HAVE_SSL_GET0_PEERNAME - -/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */ -#undef HAVE_SSL_GET1_PEER_CERTIFICATE - -/* Define to 1 if you have the `SSL_set1_host' function. */ -#undef HAVE_SSL_SET1_HOST - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strftime' function. */ -#undef HAVE_STRFTIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strlcat' function. */ -#undef HAVE_STRLCAT - -/* Define to 1 if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - -/* Define to 1 if you have the `strptime' function. */ -#undef HAVE_STRPTIME - -/* Define to 1 if you have the `strsep' function. */ -#undef HAVE_STRSEP - -/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ -#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST - -/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ -#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - -/* Define if you have Swig libraries and header files. */ -#undef HAVE_SWIG - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if systemd should be used */ -#undef HAVE_SYSTEMD - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_ENDIAN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_IPC_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_RESOURCE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SELECT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SHA2_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SHM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SYSCTL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_UIO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_UN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TARGETCONDITIONALS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TIME_H - -/* Define to 1 if you have the `tzset' function. */ -#undef HAVE_TZSET - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `usleep' function. */ -#undef HAVE_USLEEP - -/* Define to 1 if you have the `vfork' function. */ -#undef HAVE_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_VFORK_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_WINDOWS_H - -/* Using Windows threads */ -#undef HAVE_WINDOWS_THREADS - -/* Define to 1 if you have the header file. */ -#undef HAVE_WINSOCK2_H - -/* Define to 1 if `fork' works. */ -#undef HAVE_WORKING_FORK - -/* Define to 1 if `vfork' works. */ -#undef HAVE_WORKING_VFORK - -/* Define to 1 if you have the `writev' function. */ -#undef HAVE_WRITEV - -/* Define to 1 if you have the header file. */ -#undef HAVE_WS2TCPIP_H - -/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */ -#undef HAVE_X509_VERIFY_PARAM_SET1_HOST - -/* Define to 1 if you have the `_beginthreadex' function. */ -#undef HAVE__BEGINTHREADEX - -/* If HMAC_Init_ex() returns void */ -#undef HMAC_INIT_EX_RETURNS_VOID - -/* if lex has yylex_destroy */ -#undef LEX_HAS_YYLEX_DESTROY - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#undef LT_OBJDIR - -/* Define to the maximum message length to pass to syslog. */ -#undef MAXSYSLOGMSGLEN - -/* Define if memcmp() does not compare unsigned bytes */ -#undef MEMCMP_IS_BROKEN - -/* Define if mkdir has one argument. */ -#undef MKDIR_HAS_ONE_ARG - -/* Define if the network stack does not fully support nonblocking io (causes - lower performance). */ -#undef NONBLOCKING_IS_BROKEN - -/* Put -D_ALL_SOURCE define in config.h */ -#undef OMITTED__D_ALL_SOURCE - -/* Put -D_BSD_SOURCE define in config.h */ -#undef OMITTED__D_BSD_SOURCE - -/* Put -D_DEFAULT_SOURCE define in config.h */ -#undef OMITTED__D_DEFAULT_SOURCE - -/* Put -D_GNU_SOURCE define in config.h */ -#undef OMITTED__D_GNU_SOURCE - -/* Put -D_LARGEFILE_SOURCE=1 define in config.h */ -#undef OMITTED__D_LARGEFILE_SOURCE_1 - -/* Put -D_POSIX_C_SOURCE=200112 define in config.h */ -#undef OMITTED__D_POSIX_C_SOURCE_200112 - -/* Put -D_XOPEN_SOURCE=600 define in config.h */ -#undef OMITTED__D_XOPEN_SOURCE_600 - -/* Put -D_XOPEN_SOURCE_EXTENDED=1 define in config.h */ -#undef OMITTED__D_XOPEN_SOURCE_EXTENDED_1 - -/* Put -D__EXTENSIONS__ define in config.h */ -#undef OMITTED__D__EXTENSIONS__ - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* default pidfile location */ -#undef PIDFILE - -/* Define to necessary symbol if this constant uses a non-standard name on - your system. */ -#undef PTHREAD_CREATE_JOINABLE - -/* Return type of signal handlers, but autoconf 2.70 says 'your code may - safely assume C89 semantics that RETSIGTYPE is void.' */ -#undef RETSIGTYPE - -/* if REUSEPORT is enabled by default */ -#undef REUSEPORT_DEFAULT - -/* default rootkey location */ -#undef ROOT_ANCHOR_FILE - -/* default rootcert location */ -#undef ROOT_CERT_FILE - -/* version number for resource files */ -#undef RSRC_PACKAGE_VERSION - -/* Directory to chdir to */ -#undef RUN_DIR - -/* Shared data */ -#undef SHARE_DIR - -/* The size of `pthread_t', as computed by sizeof. */ -#undef SIZEOF_PTHREAD_T - -/* The size of `size_t', as computed by sizeof. */ -#undef SIZEOF_SIZE_T - -/* The size of `time_t', as computed by sizeof. */ -#undef SIZEOF_TIME_T - -/* The size of `unsigned long', as computed by sizeof. */ -#undef SIZEOF_UNSIGNED_LONG - -/* define if (v)snprintf does not return length needed, (but length used) */ -#undef SNPRINTF_RET_BROKEN - -/* Define to 1 if libsodium supports sodium_set_misuse_handler */ -#undef SODIUM_MISUSE_HANDLER - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* use default strptime. */ -#undef STRPTIME_WORKS - -/* Use win32 resources and API */ -#undef UB_ON_WINDOWS - -/* the SYSLOG_FACILITY to use, default LOG_DAEMON */ -#undef UB_SYSLOG_FACILITY - -/* default username */ -#undef UB_USERNAME - -/* use to enable lightweight alloc assertions, for debug use */ -#undef UNBOUND_ALLOC_LITE - -/* use malloc not regions, for debug use */ -#undef UNBOUND_ALLOC_NONREGIONAL - -/* use statistics for allocs and frees, for debug use */ -#undef UNBOUND_ALLOC_STATS - -/* define this to enable debug checks. */ -#undef UNBOUND_DEBUG - -/* Define to 1 to use cachedb support */ -#undef USE_CACHEDB - -/* Define to 1 to enable dnscrypt support */ -#undef USE_DNSCRYPT - -/* Define to 1 to enable dnscrypt with xchacha20 support */ -#undef USE_DNSCRYPT_XCHACHA20 - -/* Define to 1 to enable dnstap support */ -#undef USE_DNSTAP - -/* Define this to enable DSA support. */ -#undef USE_DSA - -/* Define this to enable ECDSA support. */ -#undef USE_ECDSA - -/* Define this to enable an EVP workaround for older openssl */ -#undef USE_ECDSA_EVP_WORKAROUND - -/* Define this to enable ED25519 support. */ -#undef USE_ED25519 - -/* Define this to enable ED448 support. */ -#undef USE_ED448 - -/* Define this to enable GOST support. */ -#undef USE_GOST - -/* Define to 1 to use ipsecmod support. */ -#undef USE_IPSECMOD - -/* Define to 1 to use ipset support */ -#undef USE_IPSET - -/* Define if you enable libevent */ -#undef USE_LIBEVENT - -/* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a - default outgoing port range. This is only for the libunbound on Linux and - does not affect unbound resolving daemon itself. This may severely limit - the number of available outgoing ports and thus decrease randomness. Define - this only when the target system restricts (e.g. some of SELinux enabled - distributions) the use of non-ephemeral ports. */ -#undef USE_LINUX_IP_LOCAL_PORT_RANGE - -/* Define if you want to use internal select based events */ -#undef USE_MINI_EVENT - -/* Define this to enable client TCP Fast Open. */ -#undef USE_MSG_FASTOPEN - -/* Define this to enable client TCP Fast Open. */ -#undef USE_OSX_MSG_FASTOPEN - -/* Define this to use hiredis client. */ -#undef USE_REDIS - -/* Define this to enable SHA1 support. */ -#undef USE_SHA1 - -/* Define this to enable SHA256 and SHA512 support. */ -#undef USE_SHA2 - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - -/* Define this to enable server TCP Fast Open. */ -#undef USE_TCP_FASTOPEN - -/* Whether the windows socket API is used */ -#undef USE_WINSOCK - -/* the version of the windows API enabled */ -#undef WINVER - -/* Define if you want dynlib module. */ -#undef WITH_DYNLIBMODULE - -/* Define if you want Python module. */ -#undef WITH_PYTHONMODULE - -/* Define if you want PyUnbound. */ -#undef WITH_PYUNBOUND - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -#undef YYTEXT_POINTER - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#undef _FILE_OFFSET_BITS - -/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ -#undef _LARGEFILE_SOURCE - -/* Define for large files, on AIX-style hosts. */ -#undef _LARGE_FILES - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Enable for compile on Minix */ -#undef _NETBSD_SOURCE - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - -/* defined to use gcc ansi snprintf and sscanf that understands %lld when - compiled for windows. */ -#undef __USE_MINGW_ANSI_STDIO - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if doesn't define. */ -#undef gid_t - -/* in_addr_t */ -#undef in_addr_t - -/* in_port_t */ -#undef in_port_t - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `short' if does not define. */ -#undef int16_t - -/* Define to `int' if does not define. */ -#undef int32_t - -/* Define to `long long' if does not define. */ -#undef int64_t - -/* Define to `signed char' if does not define. */ -#undef int8_t - -/* Define if replacement function should be used. */ -#undef malloc - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Define to 'int' if not defined */ -#undef rlim_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to 'int' if not defined */ -#undef socklen_t - -/* Define to `int' if does not define. */ -#undef ssize_t - -/* Define to 'unsigned char if not defined */ -#undef u_char - -/* Define to `int' if doesn't define. */ -#undef uid_t - -/* Define to `unsigned short' if does not define. */ -#undef uint16_t - -/* Define to `unsigned int' if does not define. */ -#undef uint32_t - -/* Define to `unsigned long long' if does not define. */ -#undef uint64_t - -/* Define to `unsigned char' if does not define. */ -#undef uint8_t - -/* Define as `fork' if `vfork' does not work. */ -#undef vfork - -#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE) -#define _DEFAULT_SOURCE 1 -#endif - -#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__) -#define __EXTENSIONS__ 1 -#endif - -#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED) -#define _XOPEN_SOURCE_EXTENDED 1 -#endif - -#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE) -#define _ALL_SOURCE 1 -#endif - -#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE) -#define _LARGEFILE_SOURCE 1 -#endif - - - - -#ifndef _OPENBSD_SOURCE -#define _OPENBSD_SOURCE 1 -#endif - -#ifndef UNBOUND_DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -#endif - -/** Use small-ldns codebase */ -#define USE_SLDNS 1 -#ifdef HAVE_SSL -# define LDNS_BUILD_CONFIG_HAVE_SSL 1 -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -#include -#include -#endif - -#ifdef HAVE_STDARG_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - -#include - -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO) -#define ARG_LL "%ll" -#else -#define ARG_LL "%I64" -#endif - -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif - - - -#ifdef HAVE_ATTR_FORMAT -# define ATTR_FORMAT(archetype, string_index, first_to_check) \ - __attribute__ ((format (archetype, string_index, first_to_check))) -#else /* !HAVE_ATTR_FORMAT */ -# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ -#endif /* !HAVE_ATTR_FORMAT */ - - -#if defined(DOXYGEN) -# define ATTR_UNUSED(x) x -#elif defined(__cplusplus) -# define ATTR_UNUSED(x) -#elif defined(HAVE_ATTR_UNUSED) -# define ATTR_UNUSED(x) x __attribute__((unused)) -#else /* !HAVE_ATTR_UNUSED */ -# define ATTR_UNUSED(x) x -#endif /* !HAVE_ATTR_UNUSED */ - - -#ifndef HAVE_FSEEKO -#define fseeko fseek -#define ftello ftell -#endif /* HAVE_FSEEKO */ - - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 256 -#endif - -#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) -#define snprintf snprintf_unbound -#define vsnprintf vsnprintf_unbound -#include -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#endif /* HAVE_SNPRINTF or SNPRINTF_RET_BROKEN */ - -#ifndef HAVE_INET_PTON -#define inet_pton inet_pton_unbound -int inet_pton(int af, const char* src, void* dst); -#endif /* HAVE_INET_PTON */ - - -#ifndef HAVE_INET_NTOP -#define inet_ntop inet_ntop_unbound -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - - -#ifndef HAVE_INET_ATON -#define inet_aton inet_aton_unbound -int inet_aton(const char *cp, struct in_addr *addr); -#endif - - -#ifndef HAVE_MEMMOVE -#define memmove memmove_unbound -void *memmove(void *dest, const void *src, size_t n); -#endif - - -#ifndef HAVE_STRLCAT -#define strlcat strlcat_unbound -size_t strlcat(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_STRLCPY -#define strlcpy strlcpy_unbound -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_GMTIME_R -#define gmtime_r gmtime_r_unbound -struct tm *gmtime_r(const time_t *timep, struct tm *result); -#endif - - -#ifndef HAVE_REALLOCARRAY -#define reallocarray reallocarrayunbound -void* reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - - -#if !defined(HAVE_SLEEP) || defined(HAVE_WINDOWS_H) -#define sleep(x) Sleep((x)*1000) /* on win32 */ -#endif /* HAVE_SLEEP */ - - -#ifndef HAVE_USLEEP -#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ -#endif /* HAVE_USLEEP */ - - -#ifndef HAVE_RANDOM -#define random rand /* on win32, for tests only (bad random) */ -#endif /* HAVE_RANDOM */ - - -#ifndef HAVE_SRANDOM -#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ -#endif /* HAVE_SRANDOM */ - - -/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ -#ifdef HAVE_WINSOCK2_H -#define FD_SET_T (u_int) -#else -#define FD_SET_T -#endif - - -#ifndef IPV6_MIN_MTU -#define IPV6_MIN_MTU 1280 -#endif /* IPV6_MIN_MTU */ - - -#ifdef MEMCMP_IS_BROKEN -#include "compat/memcmp.h" -#define memcmp memcmp_unbound -int memcmp(const void *x, const void *y, size_t n); -#endif - - - -#ifndef HAVE_CTIME_R -#define ctime_r unbound_ctime_r -char *ctime_r(const time_t *timep, char *buf); -#endif - -#ifndef HAVE_STRSEP -#define strsep unbound_strsep -char *strsep(char **stringp, const char *delim); -#endif - -#ifndef HAVE_ISBLANK -#define isblank unbound_isblank -int isblank(int c); -#endif - -#ifndef HAVE_EXPLICIT_BZERO -#define explicit_bzero unbound_explicit_bzero -void explicit_bzero(void* buf, size_t len); -#endif - -#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - -#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON -int inet_pton(int af, const char* src, void* dst); -#endif - -#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) -#define strptime unbound_strptime -struct tm; -char *strptime(const char *s, const char *format, struct tm *tm); -#endif - -#if !HAVE_DECL_REALLOCARRAY -void *reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - -#ifdef HAVE_LIBBSD -#include -#include -#endif - -#ifdef HAVE_LIBRESSL -# if !HAVE_DECL_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_ARC4RANDOM && defined(HAVE_ARC4RANDOM) -uint32_t arc4random(void); -# endif -# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM) -uint32_t arc4random_uniform(uint32_t upper_bound); -# endif -#endif /* HAVE_LIBRESSL */ -#ifndef HAVE_ARC4RANDOM -int getentropy(void* buf, size_t len); -uint32_t arc4random(void); -void arc4random_buf(void* buf, size_t n); -void _ARC4_LOCK(void); -void _ARC4_UNLOCK(void); -void _ARC4_LOCK_DESTROY(void); -#endif -#ifndef HAVE_ARC4RANDOM_UNIFORM -uint32_t arc4random_uniform(uint32_t upper_bound); -#endif -#ifdef COMPAT_SHA512 -#ifndef SHA512_DIGEST_LENGTH -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA512_CTX; -#endif /* SHA512_DIGEST_LENGTH */ -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, void*, size_t); -void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); -#endif /* COMPAT_SHA512 */ - - - -#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) - /* using version of libevent that is not threadsafe. */ -# define LIBEVENT_SIGNAL_PROBLEM 1 -#endif - -#ifndef CHECKED_INET6 -# define CHECKED_INET6 -# ifdef AF_INET6 -# define INET6 -# else -# define AF_INET6 28 -# endif -#endif /* CHECKED_INET6 */ - -#ifndef HAVE_GETADDRINFO -struct sockaddr_storage; -#include "compat/fake-rfc2553.h" -#endif - -#ifdef UNBOUND_ALLOC_STATS -# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) -# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) -# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) -# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) -void *unbound_stat_malloc(size_t size); -void *unbound_stat_calloc(size_t nmemb, size_t size); -void unbound_stat_free(void *ptr); -void *unbound_stat_realloc(void *ptr, size_t size); -void *unbound_stat_malloc_log(size_t size, const char* file, int line, - const char* func); -void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, - int line, const char* func); -void unbound_stat_free_log(void *ptr, const char* file, int line, - const char* func); -void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, - int line, const char* func); -#elif defined(UNBOUND_ALLOC_LITE) -# include "util/alloc.h" -#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ - -/** default port for DNS traffic. */ -#define UNBOUND_DNS_PORT 53 -/** default port for DNS over TLS traffic. */ -#define UNBOUND_DNS_OVER_TLS_PORT 853 -/** default port for DNS over HTTPS traffic. */ -#define UNBOUND_DNS_OVER_HTTPS_PORT 443 -/** default port for unbound control traffic, registered port with IANA, - ub-dns-control 8953/tcp unbound dns nameserver control */ -#define UNBOUND_CONTROL_PORT 8953 -/** the version of unbound-control that this software implements */ -#define UNBOUND_CONTROL_VERSION 1 - - diff --git a/crates/libunbound-sys/unbound/config.h.in~ b/crates/libunbound-sys/unbound/config.h.in~ deleted file mode 100644 index f31354d0..00000000 --- a/crates/libunbound-sys/unbound/config.h.in~ +++ /dev/null @@ -1,1456 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* apply the noreturn attribute to a function that exits the program */ -#undef ATTR_NORETURN - -/* apply the weak attribute to a symbol */ -#undef ATTR_WEAK - -/* Directory to chroot to */ -#undef CHROOT_DIR - -/* Define this to enable client subnet option. */ -#undef CLIENT_SUBNET - -/* Do sha512 definitions in config.h */ -#undef COMPAT_SHA512 - -/* Command line arguments used with configure */ -#undef CONFCMDLINE - -/* Pathname to the Unbound configuration file */ -#undef CONFIGFILE - -/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work - */ -#undef DARWIN_BROKEN_SETREUID - -/* Whether daemon is deprecated */ -#undef DEPRECATED_DAEMON - -/* Deprecate RSA 1024 bit length, makes that an unsupported key */ -#undef DEPRECATE_RSA_1024 - -/* Define this to enable kernel based UDP source port randomization. */ -#undef DISABLE_EXPLICIT_PORT_RANDOMISATION - -/* default dnstap socket path */ -#undef DNSTAP_SOCKET_PATH - -/* Define if you want to use debug lock checking (slow). */ -#undef ENABLE_LOCK_CHECKS - -/* Define this if you enabled-allsymbols from libunbound to link binaries to - it for smaller install size, but the libunbound export table is polluted by - internal symbols */ -#undef EXPORT_ALL_SYMBOLS - -/* Define to 1 if you have the `accept4' function. */ -#undef HAVE_ACCEPT4 - -/* Define to 1 if you have the `arc4random' function. */ -#undef HAVE_ARC4RANDOM - -/* Define to 1 if you have the `arc4random_uniform' function. */ -#undef HAVE_ARC4RANDOM_UNIFORM - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* Whether the C compiler accepts the "format" attribute */ -#undef HAVE_ATTR_FORMAT - -/* Whether the C compiler accepts the "noreturn" attribute */ -#undef HAVE_ATTR_NORETURN - -/* Whether the C compiler accepts the "unused" attribute */ -#undef HAVE_ATTR_UNUSED - -/* Whether the C compiler accepts the "weak" attribute */ -#undef HAVE_ATTR_WEAK - -/* If we have be64toh */ -#undef HAVE_BE64TOH - -/* Define to 1 if you have the `BIO_set_callback_ex' function. */ -#undef HAVE_BIO_SET_CALLBACK_EX - -/* Define to 1 if you have the header file. */ -#undef HAVE_BSD_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_BSD_STRING_H - -/* Define to 1 if you have the `chown' function. */ -#undef HAVE_CHOWN - -/* Define to 1 if you have the `chroot' function. */ -#undef HAVE_CHROOT - -/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ -#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - -/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */ -#undef HAVE_CRYPTO_THREADID_SET_CALLBACK - -/* Define to 1 if you have the `ctime_r' function. */ -#undef HAVE_CTIME_R - -/* Define to 1 if you have the `daemon' function. */ -#undef HAVE_DAEMON - -/* Define to 1 if you have the declaration of `arc4random', and to 0 if you - don't. */ -#undef HAVE_DECL_ARC4RANDOM - -/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 - if you don't. */ -#undef HAVE_DECL_ARC4RANDOM_UNIFORM - -/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if - you don't. */ -#undef HAVE_DECL_EVSIGNAL_ASSIGN - -/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you - don't. */ -#undef HAVE_DECL_INET_NTOP - -/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you - don't. */ -#undef HAVE_DECL_INET_PTON - -/* Define to 1 if you have the declaration of `nghttp2_session_server_new', - and to 0 if you don't. */ -#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW - -/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_ED25519 - -/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_ED448 - -/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you - don't. */ -#undef HAVE_DECL_NID_SECP384R1 - -/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 - if you don't. */ -#undef HAVE_DECL_NID_X9_62_PRIME256V1 - -/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you - don't. */ -#undef HAVE_DECL_REALLOCARRAY - -/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you - don't. */ -#undef HAVE_DECL_REDISCONNECT - -/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 - if you don't. */ -#undef HAVE_DECL_SK_SSL_COMP_POP_FREE - -/* Define to 1 if you have the declaration of - `SSL_COMP_get_compression_methods', and to 0 if you don't. */ -#undef HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS - -/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to - 0 if you don't. */ -#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO - -/* Define to 1 if you have the declaration of `strlcat', and to 0 if you - don't. */ -#undef HAVE_DECL_STRLCAT - -/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you - don't. */ -#undef HAVE_DECL_STRLCPY - -/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if - you don't. */ -#undef HAVE_DECL_XML_STOPPARSER - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the `DSA_SIG_set0' function. */ -#undef HAVE_DSA_SIG_SET0 - -/* Define to 1 if you have the header file. */ -#undef HAVE_ENDIAN_H - -/* Define to 1 if you have the `endprotoent' function. */ -#undef HAVE_ENDPROTOENT - -/* Define to 1 if you have the `endpwent' function. */ -#undef HAVE_ENDPWENT - -/* Define to 1 if you have the `endservent' function. */ -#undef HAVE_ENDSERVENT - -/* Define to 1 if you have the `ENGINE_cleanup' function. */ -#undef HAVE_ENGINE_CLEANUP - -/* Define to 1 if you have the `ERR_free_strings' function. */ -#undef HAVE_ERR_FREE_STRINGS - -/* Define to 1 if you have the `ERR_load_crypto_strings' function. */ -#undef HAVE_ERR_LOAD_CRYPTO_STRINGS - -/* Define to 1 if you have the `event_assign' function. */ -#undef HAVE_EVENT_ASSIGN - -/* Define to 1 if you have the `event_base_free' function. */ -#undef HAVE_EVENT_BASE_FREE - -/* Define to 1 if you have the `event_base_get_method' function. */ -#undef HAVE_EVENT_BASE_GET_METHOD - -/* Define to 1 if you have the `event_base_new' function. */ -#undef HAVE_EVENT_BASE_NEW - -/* Define to 1 if you have the `event_base_once' function. */ -#undef HAVE_EVENT_BASE_ONCE - -/* Define to 1 if you have the header file. */ -#undef HAVE_EVENT_H - -/* Define to 1 if you have the `EVP_aes_256_cbc' function. */ -#undef HAVE_EVP_AES_256_CBC - -/* Define to 1 if you have the `EVP_cleanup' function. */ -#undef HAVE_EVP_CLEANUP - -/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled' - function. */ -#undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED - -/* Define to 1 if you have the `EVP_DigestVerify' function. */ -#undef HAVE_EVP_DIGESTVERIFY - -/* Define to 1 if you have the `EVP_dss1' function. */ -#undef HAVE_EVP_DSS1 - -/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ -#undef HAVE_EVP_ENCRYPTINIT_EX - -/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */ -#undef HAVE_EVP_MAC_CTX_SET_PARAMS - -/* Define to 1 if you have the `EVP_MD_CTX_new' function. */ -#undef HAVE_EVP_MD_CTX_NEW - -/* Define to 1 if you have the `EVP_sha1' function. */ -#undef HAVE_EVP_SHA1 - -/* Define to 1 if you have the `EVP_sha256' function. */ -#undef HAVE_EVP_SHA256 - -/* Define to 1 if you have the `EVP_sha512' function. */ -#undef HAVE_EVP_SHA512 - -/* Define to 1 if you have the `ev_default_loop' function. */ -#undef HAVE_EV_DEFAULT_LOOP - -/* Define to 1 if you have the `ev_loop' function. */ -#undef HAVE_EV_LOOP - -/* Define to 1 if you have the header file. */ -#undef HAVE_EXPAT_H - -/* Define to 1 if you have the `explicit_bzero' function. */ -#undef HAVE_EXPLICIT_BZERO - -/* Define to 1 if you have the `fcntl' function. */ -#undef HAVE_FCNTL - -/* Define to 1 if you have the `FIPS_mode' function. */ -#undef HAVE_FIPS_MODE - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ -#undef HAVE_FSEEKO - -/* Define to 1 if you have the `fsync' function. */ -#undef HAVE_FSYNC - -/* Whether getaddrinfo is available */ -#undef HAVE_GETADDRINFO - -/* Define to 1 if you have the `getauxval' function. */ -#undef HAVE_GETAUXVAL - -/* Define to 1 if you have the `getentropy' function. */ -#undef HAVE_GETENTROPY - -/* Define to 1 if you have the `getifaddrs' function. */ -#undef HAVE_GETIFADDRS - -/* Define to 1 if you have the header file. */ -#undef HAVE_GETOPT_H - -/* Define to 1 if you have the `getpwnam' function. */ -#undef HAVE_GETPWNAM - -/* Define to 1 if you have the `getrlimit' function. */ -#undef HAVE_GETRLIMIT - -/* Define to 1 if you have the `gettid' function. */ -#undef HAVE_GETTID - -/* Define to 1 if you have the `glob' function. */ -#undef HAVE_GLOB - -/* Define to 1 if you have the header file. */ -#undef HAVE_GLOB_H - -/* Define to 1 if you have the `gmtime_r' function. */ -#undef HAVE_GMTIME_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_GRP_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_HIREDIS_HIREDIS_H - -/* Define to 1 if you have the `HMAC_Init_ex' function. */ -#undef HAVE_HMAC_INIT_EX - -/* If we have htobe64 */ -#undef HAVE_HTOBE64 - -/* Define to 1 if you have the header file. */ -#undef HAVE_IFADDRS_H - -/* Define to 1 if you have the `if_nametoindex' function. */ -#undef HAVE_IF_NAMETOINDEX - -/* Define to 1 if you have the `inet_aton' function. */ -#undef HAVE_INET_ATON - -/* Define to 1 if you have the `inet_ntop' function. */ -#undef HAVE_INET_NTOP - -/* Define to 1 if you have the `inet_pton' function. */ -#undef HAVE_INET_PTON - -/* Define to 1 if you have the `initgroups' function. */ -#undef HAVE_INITGROUPS - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* if the function 'ioctlsocket' is available */ -#undef HAVE_IOCTLSOCKET - -/* Define to 1 if you have the header file. */ -#undef HAVE_IPHLPAPI_H - -/* Define to 1 if you have the `isblank' function. */ -#undef HAVE_ISBLANK - -/* Define to 1 if you have the `kill' function. */ -#undef HAVE_KILL - -/* Use portable libbsd functions */ -#undef HAVE_LIBBSD - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIBKERN_OSBYTEORDER_H - -/* Define if we have LibreSSL */ -#undef HAVE_LIBRESSL - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_NET_TSTAMP_H - -/* Define to 1 if you have the `localtime_r' function. */ -#undef HAVE_LOCALTIME_R - -/* Define to 1 if you have the header file. */ -#undef HAVE_LOGIN_CAP_H - -/* If have GNU libc compatible malloc */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETDB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_TCP_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETIOAPI_H - -/* Use libnettle for crypto */ -#undef HAVE_NETTLE - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETTLE_DSA_COMPAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETTLE_EDDSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NET_IF_H - -/* Define this to use nghttp2 client. */ -#undef HAVE_NGHTTP2 - -/* Define to 1 if you have the header file. */ -#undef HAVE_NGHTTP2_NGHTTP2_H - -/* Use libnss for crypto */ -#undef HAVE_NSS - -/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */ -#undef HAVE_OPENSSL_ADD_ALL_DIGESTS - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_BN_H - -/* Define to 1 if you have the `OPENSSL_config' function. */ -#undef HAVE_OPENSSL_CONFIG - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_CONF_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_CORE_NAMES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_DH_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_DSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ENGINE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ERR_H - -/* Define to 1 if you have the `OPENSSL_init_crypto' function. */ -#undef HAVE_OPENSSL_INIT_CRYPTO - -/* Define to 1 if you have the `OPENSSL_init_ssl' function. */ -#undef HAVE_OPENSSL_INIT_SSL - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_PARAM_BUILD_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RAND_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_RSA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_SSL_H - -/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */ -#undef HAVE_OSSL_PARAM_BLD_NEW - -/* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL - -/* Define to 1 if you have the header file. */ -#undef HAVE_POLL_H - -/* Define if you have POSIX threads libraries and header files. */ -#undef HAVE_PTHREAD - -/* Have PTHREAD_PRIO_INHERIT. */ -#undef HAVE_PTHREAD_PRIO_INHERIT - -/* Define to 1 if the system has the type `pthread_rwlock_t'. */ -#undef HAVE_PTHREAD_RWLOCK_T - -/* Define to 1 if the system has the type `pthread_spinlock_t'. */ -#undef HAVE_PTHREAD_SPINLOCK_T - -/* Define to 1 if you have the header file. */ -#undef HAVE_PWD_H - -/* Define if you have Python libraries and header files. */ -#undef HAVE_PYTHON - -/* Define to 1 if you have the `random' function. */ -#undef HAVE_RANDOM - -/* Define to 1 if you have the `RAND_cleanup' function. */ -#undef HAVE_RAND_CLEANUP - -/* If we have reallocarray(3) */ -#undef HAVE_REALLOCARRAY - -/* Define to 1 if you have the `recvmsg' function. */ -#undef HAVE_RECVMSG - -/* Define to 1 if you have the `sendmsg' function. */ -#undef HAVE_SENDMSG - -/* Define to 1 if you have the `setregid' function. */ -#undef HAVE_SETREGID - -/* Define to 1 if you have the `setresgid' function. */ -#undef HAVE_SETRESGID - -/* Define to 1 if you have the `setresuid' function. */ -#undef HAVE_SETRESUID - -/* Define to 1 if you have the `setreuid' function. */ -#undef HAVE_SETREUID - -/* Define to 1 if you have the `setrlimit' function. */ -#undef HAVE_SETRLIMIT - -/* Define to 1 if you have the `setsid' function. */ -#undef HAVE_SETSID - -/* Define to 1 if you have the `setusercontext' function. */ -#undef HAVE_SETUSERCONTEXT - -/* Define to 1 if you have the `SHA512_Update' function. */ -#undef HAVE_SHA512_UPDATE - -/* Define to 1 if you have the `shmget' function. */ -#undef HAVE_SHMGET - -/* Define to 1 if you have the `sigprocmask' function. */ -#undef HAVE_SIGPROCMASK - -/* Define to 1 if you have the `sleep' function. */ -#undef HAVE_SLEEP - -/* Define to 1 if you have the `snprintf' function. */ -#undef HAVE_SNPRINTF - -/* Define to 1 if you have the `socketpair' function. */ -#undef HAVE_SOCKETPAIR - -/* Using Solaris threads */ -#undef HAVE_SOLARIS_THREADS - -/* Define to 1 if you have the `srandom' function. */ -#undef HAVE_SRANDOM - -/* Define if you have the SSL libraries installed. */ -#undef HAVE_SSL - -/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */ -#undef HAVE_SSL_CTX_SET_ALPN_PROTOS - -/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */ -#undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB - -/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */ -#undef HAVE_SSL_CTX_SET_CIPHERSUITES - -/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */ -#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL - -/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb' - function. */ -#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - -/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */ -#undef HAVE_SSL_GET0_ALPN_SELECTED - -/* Define to 1 if you have the `SSL_get0_peername' function. */ -#undef HAVE_SSL_GET0_PEERNAME - -/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */ -#undef HAVE_SSL_GET1_PEER_CERTIFICATE - -/* Define to 1 if you have the `SSL_set1_host' function. */ -#undef HAVE_SSL_SET1_HOST - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDARG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDBOOL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strftime' function. */ -#undef HAVE_STRFTIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strlcat' function. */ -#undef HAVE_STRLCAT - -/* Define to 1 if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - -/* Define to 1 if you have the `strptime' function. */ -#undef HAVE_STRPTIME - -/* Define to 1 if you have the `strsep' function. */ -#undef HAVE_STRSEP - -/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ -#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST - -/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ -#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - -/* Define if you have Swig libraries and header files. */ -#undef HAVE_SWIG - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if systemd should be used */ -#undef HAVE_SYSTEMD - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_ENDIAN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_IPC_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_RESOURCE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SELECT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SHA2_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SHM_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SYSCTL_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_UIO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_UN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TARGETCONDITIONALS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TIME_H - -/* Define to 1 if you have the `tzset' function. */ -#undef HAVE_TZSET - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `usleep' function. */ -#undef HAVE_USLEEP - -/* Define to 1 if you have the `vfork' function. */ -#undef HAVE_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_VFORK_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_WINDOWS_H - -/* Using Windows threads */ -#undef HAVE_WINDOWS_THREADS - -/* Define to 1 if you have the header file. */ -#undef HAVE_WINSOCK2_H - -/* Define to 1 if `fork' works. */ -#undef HAVE_WORKING_FORK - -/* Define to 1 if `vfork' works. */ -#undef HAVE_WORKING_VFORK - -/* Define to 1 if you have the `writev' function. */ -#undef HAVE_WRITEV - -/* Define to 1 if you have the header file. */ -#undef HAVE_WS2TCPIP_H - -/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */ -#undef HAVE_X509_VERIFY_PARAM_SET1_HOST - -/* Define to 1 if you have the `_beginthreadex' function. */ -#undef HAVE__BEGINTHREADEX - -/* If HMAC_Init_ex() returns void */ -#undef HMAC_INIT_EX_RETURNS_VOID - -/* if lex has yylex_destroy */ -#undef LEX_HAS_YYLEX_DESTROY - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#undef LT_OBJDIR - -/* Define to the maximum message length to pass to syslog. */ -#undef MAXSYSLOGMSGLEN - -/* Define if memcmp() does not compare unsigned bytes */ -#undef MEMCMP_IS_BROKEN - -/* Define if mkdir has one argument. */ -#undef MKDIR_HAS_ONE_ARG - -/* Define if the network stack does not fully support nonblocking io (causes - lower performance). */ -#undef NONBLOCKING_IS_BROKEN - -/* Put -D_ALL_SOURCE define in config.h */ -#undef OMITTED__D_ALL_SOURCE - -/* Put -D_BSD_SOURCE define in config.h */ -#undef OMITTED__D_BSD_SOURCE - -/* Put -D_DEFAULT_SOURCE define in config.h */ -#undef OMITTED__D_DEFAULT_SOURCE - -/* Put -D_GNU_SOURCE define in config.h */ -#undef OMITTED__D_GNU_SOURCE - -/* Put -D_LARGEFILE_SOURCE=1 define in config.h */ -#undef OMITTED__D_LARGEFILE_SOURCE_1 - -/* Put -D_POSIX_C_SOURCE=200112 define in config.h */ -#undef OMITTED__D_POSIX_C_SOURCE_200112 - -/* Put -D_XOPEN_SOURCE=600 define in config.h */ -#undef OMITTED__D_XOPEN_SOURCE_600 - -/* Put -D_XOPEN_SOURCE_EXTENDED=1 define in config.h */ -#undef OMITTED__D_XOPEN_SOURCE_EXTENDED_1 - -/* Put -D__EXTENSIONS__ define in config.h */ -#undef OMITTED__D__EXTENSIONS__ - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* default pidfile location */ -#undef PIDFILE - -/* Define to necessary symbol if this constant uses a non-standard name on - your system. */ -#undef PTHREAD_CREATE_JOINABLE - -/* Return type of signal handlers, but autoconf 2.70 says 'your code may - safely assume C89 semantics that RETSIGTYPE is void.' */ -#undef RETSIGTYPE - -/* if REUSEPORT is enabled by default */ -#undef REUSEPORT_DEFAULT - -/* default rootkey location */ -#undef ROOT_ANCHOR_FILE - -/* default rootcert location */ -#undef ROOT_CERT_FILE - -/* version number for resource files */ -#undef RSRC_PACKAGE_VERSION - -/* Directory to chdir to */ -#undef RUN_DIR - -/* Shared data */ -#undef SHARE_DIR - -/* The size of `pthread_t', as computed by sizeof. */ -#undef SIZEOF_PTHREAD_T - -/* The size of `size_t', as computed by sizeof. */ -#undef SIZEOF_SIZE_T - -/* The size of `time_t', as computed by sizeof. */ -#undef SIZEOF_TIME_T - -/* The size of `unsigned long', as computed by sizeof. */ -#undef SIZEOF_UNSIGNED_LONG - -/* define if (v)snprintf does not return length needed, (but length used) */ -#undef SNPRINTF_RET_BROKEN - -/* Define to 1 if libsodium supports sodium_set_misuse_handler */ -#undef SODIUM_MISUSE_HANDLER - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* use default strptime. */ -#undef STRPTIME_WORKS - -/* Use win32 resources and API */ -#undef UB_ON_WINDOWS - -/* the SYSLOG_FACILITY to use, default LOG_DAEMON */ -#undef UB_SYSLOG_FACILITY - -/* default username */ -#undef UB_USERNAME - -/* use to enable lightweight alloc assertions, for debug use */ -#undef UNBOUND_ALLOC_LITE - -/* use malloc not regions, for debug use */ -#undef UNBOUND_ALLOC_NONREGIONAL - -/* use statistics for allocs and frees, for debug use */ -#undef UNBOUND_ALLOC_STATS - -/* define this to enable debug checks. */ -#undef UNBOUND_DEBUG - -/* Define to 1 to use cachedb support */ -#undef USE_CACHEDB - -/* Define to 1 to enable dnscrypt support */ -#undef USE_DNSCRYPT - -/* Define to 1 to enable dnscrypt with xchacha20 support */ -#undef USE_DNSCRYPT_XCHACHA20 - -/* Define to 1 to enable dnstap support */ -#undef USE_DNSTAP - -/* Define this to enable DSA support. */ -#undef USE_DSA - -/* Define this to enable ECDSA support. */ -#undef USE_ECDSA - -/* Define this to enable an EVP workaround for older openssl */ -#undef USE_ECDSA_EVP_WORKAROUND - -/* Define this to enable ED25519 support. */ -#undef USE_ED25519 - -/* Define this to enable ED448 support. */ -#undef USE_ED448 - -/* Define this to enable GOST support. */ -#undef USE_GOST - -/* Define to 1 to use ipsecmod support. */ -#undef USE_IPSECMOD - -/* Define to 1 to use ipset support */ -#undef USE_IPSET - -/* Define if you enable libevent */ -#undef USE_LIBEVENT - -/* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a - default outgoing port range. This is only for the libunbound on Linux and - does not affect unbound resolving daemon itself. This may severely limit - the number of available outgoing ports and thus decrease randomness. Define - this only when the target system restricts (e.g. some of SELinux enabled - distributions) the use of non-ephemeral ports. */ -#undef USE_LINUX_IP_LOCAL_PORT_RANGE - -/* Define if you want to use internal select based events */ -#undef USE_MINI_EVENT - -/* Define this to enable client TCP Fast Open. */ -#undef USE_MSG_FASTOPEN - -/* Define this to enable client TCP Fast Open. */ -#undef USE_OSX_MSG_FASTOPEN - -/* Define this to use hiredis client. */ -#undef USE_REDIS - -/* Define this to enable SHA1 support. */ -#undef USE_SHA1 - -/* Define this to enable SHA256 and SHA512 support. */ -#undef USE_SHA2 - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - -/* Define this to enable server TCP Fast Open. */ -#undef USE_TCP_FASTOPEN - -/* Whether the windows socket API is used */ -#undef USE_WINSOCK - -/* the version of the windows API enabled */ -#undef WINVER - -/* Define if you want dynlib module. */ -#undef WITH_DYNLIBMODULE - -/* Define if you want Python module. */ -#undef WITH_PYTHONMODULE - -/* Define if you want PyUnbound. */ -#undef WITH_PYUNBOUND - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -#undef YYTEXT_POINTER - -/* Enable large inode numbers on Mac OS X 10.5. */ -#ifndef _DARWIN_USE_64_BIT_INODE -# define _DARWIN_USE_64_BIT_INODE 1 -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#undef _FILE_OFFSET_BITS - -/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ -#undef _LARGEFILE_SOURCE - -/* Define for large files, on AIX-style hosts. */ -#undef _LARGE_FILES - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Enable for compile on Minix */ -#undef _NETBSD_SOURCE - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - -/* defined to use gcc ansi snprintf and sscanf that understands %lld when - compiled for windows. */ -#undef __USE_MINGW_ANSI_STDIO - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if doesn't define. */ -#undef gid_t - -/* in_addr_t */ -#undef in_addr_t - -/* in_port_t */ -#undef in_port_t - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to `short' if does not define. */ -#undef int16_t - -/* Define to `int' if does not define. */ -#undef int32_t - -/* Define to `long long' if does not define. */ -#undef int64_t - -/* Define to `signed char' if does not define. */ -#undef int8_t - -/* Define if replacement function should be used. */ -#undef malloc - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t - -/* Define to 'int' if not defined */ -#undef rlim_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to 'int' if not defined */ -#undef socklen_t - -/* Define to `int' if does not define. */ -#undef ssize_t - -/* Define to 'unsigned char if not defined */ -#undef u_char - -/* Define to `int' if doesn't define. */ -#undef uid_t - -/* Define to `unsigned short' if does not define. */ -#undef uint16_t - -/* Define to `unsigned int' if does not define. */ -#undef uint32_t - -/* Define to `unsigned long long' if does not define. */ -#undef uint64_t - -/* Define to `unsigned char' if does not define. */ -#undef uint8_t - -/* Define as `fork' if `vfork' does not work. */ -#undef vfork - -#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE) -#define _DEFAULT_SOURCE 1 -#endif - -#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__) -#define __EXTENSIONS__ 1 -#endif - -#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE) -#define _XOPEN_SOURCE 600 -#endif - -#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED) -#define _XOPEN_SOURCE_EXTENDED 1 -#endif - -#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE) -#define _ALL_SOURCE 1 -#endif - -#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE) -#define _LARGEFILE_SOURCE 1 -#endif - - - - -#ifndef _OPENBSD_SOURCE -#define _OPENBSD_SOURCE 1 -#endif - -#ifndef UNBOUND_DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -#endif - -/** Use small-ldns codebase */ -#define USE_SLDNS 1 -#ifdef HAVE_SSL -# define LDNS_BUILD_CONFIG_HAVE_SSL 1 -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -#include -#include -#endif - -#ifdef HAVE_STDARG_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - -#include - -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO) -#define ARG_LL "%ll" -#else -#define ARG_LL "%I64" -#endif - -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif - - - -#ifdef HAVE_ATTR_FORMAT -# define ATTR_FORMAT(archetype, string_index, first_to_check) \ - __attribute__ ((format (archetype, string_index, first_to_check))) -#else /* !HAVE_ATTR_FORMAT */ -# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ -#endif /* !HAVE_ATTR_FORMAT */ - - -#if defined(DOXYGEN) -# define ATTR_UNUSED(x) x -#elif defined(__cplusplus) -# define ATTR_UNUSED(x) -#elif defined(HAVE_ATTR_UNUSED) -# define ATTR_UNUSED(x) x __attribute__((unused)) -#else /* !HAVE_ATTR_UNUSED */ -# define ATTR_UNUSED(x) x -#endif /* !HAVE_ATTR_UNUSED */ - - -#ifndef HAVE_FSEEKO -#define fseeko fseek -#define ftello ftell -#endif /* HAVE_FSEEKO */ - - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 256 -#endif - -#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) -#define snprintf snprintf_unbound -#define vsnprintf vsnprintf_unbound -#include -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#endif /* HAVE_SNPRINTF or SNPRINTF_RET_BROKEN */ - -#ifndef HAVE_INET_PTON -#define inet_pton inet_pton_unbound -int inet_pton(int af, const char* src, void* dst); -#endif /* HAVE_INET_PTON */ - - -#ifndef HAVE_INET_NTOP -#define inet_ntop inet_ntop_unbound -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - - -#ifndef HAVE_INET_ATON -#define inet_aton inet_aton_unbound -int inet_aton(const char *cp, struct in_addr *addr); -#endif - - -#ifndef HAVE_MEMMOVE -#define memmove memmove_unbound -void *memmove(void *dest, const void *src, size_t n); -#endif - - -#ifndef HAVE_STRLCAT -#define strlcat strlcat_unbound -size_t strlcat(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_STRLCPY -#define strlcpy strlcpy_unbound -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif - - -#ifndef HAVE_GMTIME_R -#define gmtime_r gmtime_r_unbound -struct tm *gmtime_r(const time_t *timep, struct tm *result); -#endif - - -#ifndef HAVE_REALLOCARRAY -#define reallocarray reallocarrayunbound -void* reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - - -#if !defined(HAVE_SLEEP) || defined(HAVE_WINDOWS_H) -#define sleep(x) Sleep((x)*1000) /* on win32 */ -#endif /* HAVE_SLEEP */ - - -#ifndef HAVE_USLEEP -#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ -#endif /* HAVE_USLEEP */ - - -#ifndef HAVE_RANDOM -#define random rand /* on win32, for tests only (bad random) */ -#endif /* HAVE_RANDOM */ - - -#ifndef HAVE_SRANDOM -#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ -#endif /* HAVE_SRANDOM */ - - -/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ -#ifdef HAVE_WINSOCK2_H -#define FD_SET_T (u_int) -#else -#define FD_SET_T -#endif - - -#ifndef IPV6_MIN_MTU -#define IPV6_MIN_MTU 1280 -#endif /* IPV6_MIN_MTU */ - - -#ifdef MEMCMP_IS_BROKEN -#include "compat/memcmp.h" -#define memcmp memcmp_unbound -int memcmp(const void *x, const void *y, size_t n); -#endif - - - -#ifndef HAVE_CTIME_R -#define ctime_r unbound_ctime_r -char *ctime_r(const time_t *timep, char *buf); -#endif - -#ifndef HAVE_STRSEP -#define strsep unbound_strsep -char *strsep(char **stringp, const char *delim); -#endif - -#ifndef HAVE_ISBLANK -#define isblank unbound_isblank -int isblank(int c); -#endif - -#ifndef HAVE_EXPLICIT_BZERO -#define explicit_bzero unbound_explicit_bzero -void explicit_bzero(void* buf, size_t len); -#endif - -#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - -#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON -int inet_pton(int af, const char* src, void* dst); -#endif - -#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) -#define strptime unbound_strptime -struct tm; -char *strptime(const char *s, const char *format, struct tm *tm); -#endif - -#if !HAVE_DECL_REALLOCARRAY -void *reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - -#ifdef HAVE_LIBBSD -#include -#include -#endif - -#ifdef HAVE_LIBRESSL -# if !HAVE_DECL_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_ARC4RANDOM && defined(HAVE_ARC4RANDOM) -uint32_t arc4random(void); -# endif -# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM) -uint32_t arc4random_uniform(uint32_t upper_bound); -# endif -#endif /* HAVE_LIBRESSL */ -#ifndef HAVE_ARC4RANDOM -int getentropy(void* buf, size_t len); -uint32_t arc4random(void); -void arc4random_buf(void* buf, size_t n); -void _ARC4_LOCK(void); -void _ARC4_UNLOCK(void); -void _ARC4_LOCK_DESTROY(void); -#endif -#ifndef HAVE_ARC4RANDOM_UNIFORM -uint32_t arc4random_uniform(uint32_t upper_bound); -#endif -#ifdef COMPAT_SHA512 -#ifndef SHA512_DIGEST_LENGTH -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA512_CTX; -#endif /* SHA512_DIGEST_LENGTH */ -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, void*, size_t); -void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); -#endif /* COMPAT_SHA512 */ - - - -#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) - /* using version of libevent that is not threadsafe. */ -# define LIBEVENT_SIGNAL_PROBLEM 1 -#endif - -#ifndef CHECKED_INET6 -# define CHECKED_INET6 -# ifdef AF_INET6 -# define INET6 -# else -# define AF_INET6 28 -# endif -#endif /* CHECKED_INET6 */ - -#ifndef HAVE_GETADDRINFO -struct sockaddr_storage; -#include "compat/fake-rfc2553.h" -#endif - -#ifdef UNBOUND_ALLOC_STATS -# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) -# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) -# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) -# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) -void *unbound_stat_malloc(size_t size); -void *unbound_stat_calloc(size_t nmemb, size_t size); -void unbound_stat_free(void *ptr); -void *unbound_stat_realloc(void *ptr, size_t size); -void *unbound_stat_malloc_log(size_t size, const char* file, int line, - const char* func); -void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, - int line, const char* func); -void unbound_stat_free_log(void *ptr, const char* file, int line, - const char* func); -void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, - int line, const char* func); -#elif defined(UNBOUND_ALLOC_LITE) -# include "util/alloc.h" -#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ - -/** default port for DNS traffic. */ -#define UNBOUND_DNS_PORT 53 -/** default port for DNS over TLS traffic. */ -#define UNBOUND_DNS_OVER_TLS_PORT 853 -/** default port for DNS over HTTPS traffic. */ -#define UNBOUND_DNS_OVER_HTTPS_PORT 443 -/** default port for unbound control traffic, registered port with IANA, - ub-dns-control 8953/tcp unbound dns nameserver control */ -#define UNBOUND_CONTROL_PORT 8953 -/** the version of unbound-control that this software implements */ -#define UNBOUND_CONTROL_VERSION 1 - - diff --git a/crates/libunbound-sys/unbound/config.sub b/crates/libunbound-sys/unbound/config.sub deleted file mode 100755 index 6ae25027..00000000 --- a/crates/libunbound-sys/unbound/config.sub +++ /dev/null @@ -1,1895 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2023 Free Software Foundation, Inc. - -# shellcheck disable=SC2006,SC2268 # see below for rationale - -timestamp='2023-07-31' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -# The "shellcheck disable" line above the timestamp inhibits complaints -# about features and limitations of the classic Bourne shell that were -# superseded or lifted in POSIX. However, this script identifies a wide -# variety of pre-POSIX systems that do not have POSIX shells at all, and -# even some reasonably current systems (Solaris 10 as case-in-point) still -# have a pre-POSIX /bin/sh. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Options: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2023 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try '$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo "$1" - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Split fields of configuration type -# shellcheck disable=SC2162 -saved_IFS=$IFS -IFS="-" read field1 field2 field3 field4 <&2 - exit 1 - ;; - *-*-*-*) - basic_machine=$field1-$field2 - basic_os=$field3-$field4 - ;; - *-*-*) - # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two - # parts - maybe_os=$field2-$field3 - case $maybe_os in - nto-qnx* | linux-* | uclinux-uclibc* \ - | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ - | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ - | windows-* ) - basic_machine=$field1 - basic_os=$maybe_os - ;; - android-linux) - basic_machine=$field1-unknown - basic_os=linux-android - ;; - *) - basic_machine=$field1-$field2 - basic_os=$field3 - ;; - esac - ;; - *-*) - # A lone config we happen to match not fitting any pattern - case $field1-$field2 in - decstation-3100) - basic_machine=mips-dec - basic_os= - ;; - *-*) - # Second component is usually, but not always the OS - case $field2 in - # Prevent following clause from handling this valid os - sun*os*) - basic_machine=$field1 - basic_os=$field2 - ;; - zephyr*) - basic_machine=$field1-unknown - basic_os=$field2 - ;; - # Manufacturers - dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ - | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ - | unicom* | ibm* | next | hp | isi* | apollo | altos* \ - | convergent* | ncr* | news | 32* | 3600* | 3100* \ - | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ - | ultra | tti* | harris | dolphin | highlevel | gould \ - | cbm | ns | masscomp | apple | axis | knuth | cray \ - | microblaze* | sim | cisco \ - | oki | wec | wrs | winbond) - basic_machine=$field1-$field2 - basic_os= - ;; - *) - basic_machine=$field1 - basic_os=$field2 - ;; - esac - ;; - esac - ;; - *) - # Convert single-component short-hands not valid as part of - # multi-component configurations. - case $field1 in - 386bsd) - basic_machine=i386-pc - basic_os=bsd - ;; - a29khif) - basic_machine=a29k-amd - basic_os=udi - ;; - adobe68k) - basic_machine=m68010-adobe - basic_os=scout - ;; - alliant) - basic_machine=fx80-alliant - basic_os= - ;; - altos | altos3068) - basic_machine=m68k-altos - basic_os= - ;; - am29k) - basic_machine=a29k-none - basic_os=bsd - ;; - amdahl) - basic_machine=580-amdahl - basic_os=sysv - ;; - amiga) - basic_machine=m68k-unknown - basic_os= - ;; - amigaos | amigados) - basic_machine=m68k-unknown - basic_os=amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - basic_os=sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - basic_os=sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - basic_os=bsd - ;; - aros) - basic_machine=i386-pc - basic_os=aros - ;; - aux) - basic_machine=m68k-apple - basic_os=aux - ;; - balance) - basic_machine=ns32k-sequent - basic_os=dynix - ;; - blackfin) - basic_machine=bfin-unknown - basic_os=linux - ;; - cegcc) - basic_machine=arm-unknown - basic_os=cegcc - ;; - convex-c1) - basic_machine=c1-convex - basic_os=bsd - ;; - convex-c2) - basic_machine=c2-convex - basic_os=bsd - ;; - convex-c32) - basic_machine=c32-convex - basic_os=bsd - ;; - convex-c34) - basic_machine=c34-convex - basic_os=bsd - ;; - convex-c38) - basic_machine=c38-convex - basic_os=bsd - ;; - cray) - basic_machine=j90-cray - basic_os=unicos - ;; - crds | unos) - basic_machine=m68k-crds - basic_os= - ;; - da30) - basic_machine=m68k-da30 - basic_os= - ;; - decstation | pmax | pmin | dec3100 | decstatn) - basic_machine=mips-dec - basic_os= - ;; - delta88) - basic_machine=m88k-motorola - basic_os=sysv3 - ;; - dicos) - basic_machine=i686-pc - basic_os=dicos - ;; - djgpp) - basic_machine=i586-pc - basic_os=msdosdjgpp - ;; - ebmon29k) - basic_machine=a29k-amd - basic_os=ebmon - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - basic_os=ose - ;; - gmicro) - basic_machine=tron-gmicro - basic_os=sysv - ;; - go32) - basic_machine=i386-pc - basic_os=go32 - ;; - h8300hms) - basic_machine=h8300-hitachi - basic_os=hms - ;; - h8300xray) - basic_machine=h8300-hitachi - basic_os=xray - ;; - h8500hms) - basic_machine=h8500-hitachi - basic_os=hms - ;; - harris) - basic_machine=m88k-harris - basic_os=sysv3 - ;; - hp300 | hp300hpux) - basic_machine=m68k-hp - basic_os=hpux - ;; - hp300bsd) - basic_machine=m68k-hp - basic_os=bsd - ;; - hppaosf) - basic_machine=hppa1.1-hp - basic_os=osf - ;; - hppro) - basic_machine=hppa1.1-hp - basic_os=proelf - ;; - i386mach) - basic_machine=i386-mach - basic_os=mach - ;; - isi68 | isi) - basic_machine=m68k-isi - basic_os=sysv - ;; - m68knommu) - basic_machine=m68k-unknown - basic_os=linux - ;; - magnum | m3230) - basic_machine=mips-mips - basic_os=sysv - ;; - merlin) - basic_machine=ns32k-utek - basic_os=sysv - ;; - mingw64) - basic_machine=x86_64-pc - basic_os=mingw64 - ;; - mingw32) - basic_machine=i686-pc - basic_os=mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - basic_os=mingw32ce - ;; - monitor) - basic_machine=m68k-rom68k - basic_os=coff - ;; - morphos) - basic_machine=powerpc-unknown - basic_os=morphos - ;; - moxiebox) - basic_machine=moxie-unknown - basic_os=moxiebox - ;; - msdos) - basic_machine=i386-pc - basic_os=msdos - ;; - msys) - basic_machine=i686-pc - basic_os=msys - ;; - mvs) - basic_machine=i370-ibm - basic_os=mvs - ;; - nacl) - basic_machine=le32-unknown - basic_os=nacl - ;; - ncr3000) - basic_machine=i486-ncr - basic_os=sysv4 - ;; - netbsd386) - basic_machine=i386-pc - basic_os=netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - basic_os=linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - basic_os=newsos - ;; - news1000) - basic_machine=m68030-sony - basic_os=newsos - ;; - necv70) - basic_machine=v70-nec - basic_os=sysv - ;; - nh3000) - basic_machine=m68k-harris - basic_os=cxux - ;; - nh[45]000) - basic_machine=m88k-harris - basic_os=cxux - ;; - nindy960) - basic_machine=i960-intel - basic_os=nindy - ;; - mon960) - basic_machine=i960-intel - basic_os=mon960 - ;; - nonstopux) - basic_machine=mips-compaq - basic_os=nonstopux - ;; - os400) - basic_machine=powerpc-ibm - basic_os=os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - basic_os=ose - ;; - os68k) - basic_machine=m68k-none - basic_os=os68k - ;; - paragon) - basic_machine=i860-intel - basic_os=osf - ;; - parisc) - basic_machine=hppa-unknown - basic_os=linux - ;; - psp) - basic_machine=mipsallegrexel-sony - basic_os=psp - ;; - pw32) - basic_machine=i586-unknown - basic_os=pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - basic_os=rdos - ;; - rdos32) - basic_machine=i386-pc - basic_os=rdos - ;; - rom68k) - basic_machine=m68k-rom68k - basic_os=coff - ;; - sa29200) - basic_machine=a29k-amd - basic_os=udi - ;; - sei) - basic_machine=mips-sei - basic_os=seiux - ;; - sequent) - basic_machine=i386-sequent - basic_os= - ;; - sps7) - basic_machine=m68k-bull - basic_os=sysv2 - ;; - st2000) - basic_machine=m68k-tandem - basic_os= - ;; - stratus) - basic_machine=i860-stratus - basic_os=sysv4 - ;; - sun2) - basic_machine=m68000-sun - basic_os= - ;; - sun2os3) - basic_machine=m68000-sun - basic_os=sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - basic_os=sunos4 - ;; - sun3) - basic_machine=m68k-sun - basic_os= - ;; - sun3os3) - basic_machine=m68k-sun - basic_os=sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - basic_os=sunos4 - ;; - sun4) - basic_machine=sparc-sun - basic_os= - ;; - sun4os3) - basic_machine=sparc-sun - basic_os=sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - basic_os=sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - basic_os=solaris2 - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - basic_os= - ;; - sv1) - basic_machine=sv1-cray - basic_os=unicos - ;; - symmetry) - basic_machine=i386-sequent - basic_os=dynix - ;; - t3e) - basic_machine=alphaev5-cray - basic_os=unicos - ;; - t90) - basic_machine=t90-cray - basic_os=unicos - ;; - toad1) - basic_machine=pdp10-xkl - basic_os=tops20 - ;; - tpf) - basic_machine=s390x-ibm - basic_os=tpf - ;; - udi29k) - basic_machine=a29k-amd - basic_os=udi - ;; - ultra3) - basic_machine=a29k-nyu - basic_os=sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - basic_os=none - ;; - vaxv) - basic_machine=vax-dec - basic_os=sysv - ;; - vms) - basic_machine=vax-dec - basic_os=vms - ;; - vsta) - basic_machine=i386-pc - basic_os=vsta - ;; - vxworks960) - basic_machine=i960-wrs - basic_os=vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - basic_os=vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - basic_os=vxworks - ;; - xbox) - basic_machine=i686-pc - basic_os=mingw32 - ;; - ymp) - basic_machine=ymp-cray - basic_os=unicos - ;; - *) - basic_machine=$1 - basic_os= - ;; - esac - ;; -esac - -# Decode 1-component or ad-hoc basic machines -case $basic_machine in - # Here we handle the default manufacturer of certain CPU types. It is in - # some cases the only manufacturer, in others, it is the most popular. - w89k) - cpu=hppa1.1 - vendor=winbond - ;; - op50n) - cpu=hppa1.1 - vendor=oki - ;; - op60c) - cpu=hppa1.1 - vendor=oki - ;; - ibm*) - cpu=i370 - vendor=ibm - ;; - orion105) - cpu=clipper - vendor=highlevel - ;; - mac | mpw | mac-mpw) - cpu=m68k - vendor=apple - ;; - pmac | pmac-mpw) - cpu=powerpc - vendor=apple - ;; - - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - cpu=m68000 - vendor=att - ;; - 3b*) - cpu=we32k - vendor=att - ;; - bluegene*) - cpu=powerpc - vendor=ibm - basic_os=cnk - ;; - decsystem10* | dec10*) - cpu=pdp10 - vendor=dec - basic_os=tops10 - ;; - decsystem20* | dec20*) - cpu=pdp10 - vendor=dec - basic_os=tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - cpu=m68k - vendor=motorola - ;; - dpx2*) - cpu=m68k - vendor=bull - basic_os=sysv3 - ;; - encore | umax | mmax) - cpu=ns32k - vendor=encore - ;; - elxsi) - cpu=elxsi - vendor=elxsi - basic_os=${basic_os:-bsd} - ;; - fx2800) - cpu=i860 - vendor=alliant - ;; - genix) - cpu=ns32k - vendor=ns - ;; - h3050r* | hiux*) - cpu=hppa1.1 - vendor=hitachi - basic_os=hiuxwe2 - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - cpu=m68000 - vendor=hp - ;; - hp9k3[2-9][0-9]) - cpu=m68k - vendor=hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - cpu=hppa1.1 - vendor=hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - cpu=hppa1.1 - vendor=hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - cpu=hppa1.0 - vendor=hp - ;; - i*86v32) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - basic_os=sysv32 - ;; - i*86v4*) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - basic_os=sysv4 - ;; - i*86v) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - basic_os=sysv - ;; - i*86sol2) - cpu=`echo "$1" | sed -e 's/86.*/86/'` - vendor=pc - basic_os=solaris2 - ;; - j90 | j90-cray) - cpu=j90 - vendor=cray - basic_os=${basic_os:-unicos} - ;; - iris | iris4d) - cpu=mips - vendor=sgi - case $basic_os in - irix*) - ;; - *) - basic_os=irix4 - ;; - esac - ;; - miniframe) - cpu=m68000 - vendor=convergent - ;; - *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) - cpu=m68k - vendor=atari - basic_os=mint - ;; - news-3600 | risc-news) - cpu=mips - vendor=sony - basic_os=newsos - ;; - next | m*-next) - cpu=m68k - vendor=next - case $basic_os in - openstep*) - ;; - nextstep*) - ;; - ns2*) - basic_os=nextstep2 - ;; - *) - basic_os=nextstep3 - ;; - esac - ;; - np1) - cpu=np1 - vendor=gould - ;; - op50n-* | op60c-*) - cpu=hppa1.1 - vendor=oki - basic_os=proelf - ;; - pa-hitachi) - cpu=hppa1.1 - vendor=hitachi - basic_os=hiuxwe2 - ;; - pbd) - cpu=sparc - vendor=tti - ;; - pbb) - cpu=m68k - vendor=tti - ;; - pc532) - cpu=ns32k - vendor=pc532 - ;; - pn) - cpu=pn - vendor=gould - ;; - power) - cpu=power - vendor=ibm - ;; - ps2) - cpu=i386 - vendor=ibm - ;; - rm[46]00) - cpu=mips - vendor=siemens - ;; - rtpc | rtpc-*) - cpu=romp - vendor=ibm - ;; - sde) - cpu=mipsisa32 - vendor=sde - basic_os=${basic_os:-elf} - ;; - simso-wrs) - cpu=sparclite - vendor=wrs - basic_os=vxworks - ;; - tower | tower-32) - cpu=m68k - vendor=ncr - ;; - vpp*|vx|vx-*) - cpu=f301 - vendor=fujitsu - ;; - w65) - cpu=w65 - vendor=wdc - ;; - w89k-*) - cpu=hppa1.1 - vendor=winbond - basic_os=proelf - ;; - none) - cpu=none - vendor=none - ;; - leon|leon[3-9]) - cpu=sparc - vendor=$basic_machine - ;; - leon-*|leon[3-9]-*) - cpu=sparc - vendor=`echo "$basic_machine" | sed 's/-.*//'` - ;; - - *-*) - # shellcheck disable=SC2162 - saved_IFS=$IFS - IFS="-" read cpu vendor <&2 - exit 1 - ;; - esac - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $vendor in - digital*) - vendor=dec - ;; - commodore*) - vendor=cbm - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if test x$basic_os != x -then - -# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just -# set os. -case $basic_os in - gnu/linux*) - kernel=linux - os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` - ;; - os2-emx) - kernel=os2 - os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` - ;; - nto-qnx*) - kernel=nto - os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` - ;; - *-*) - # shellcheck disable=SC2162 - saved_IFS=$IFS - IFS="-" read kernel os <&2 - exit 1 - ;; -esac - -# As a final step for OS-related things, validate the OS-kernel combination -# (given a valid OS), if there is a kernel. -case $kernel-$os in - linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ - | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) - ;; - uclinux-uclibc* ) - ;; - managarm-mlibc* | managarm-kernel* ) - ;; - windows*-gnu* | windows*-msvc*) - ;; - -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) - # These are just libc implementations, not actual OSes, and thus - # require a kernel. - echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 - exit 1 - ;; - -kernel* ) - echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 - exit 1 - ;; - *-kernel* ) - echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 - exit 1 - ;; - *-msvc* ) - echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 - exit 1 - ;; - kfreebsd*-gnu* | kopensolaris*-gnu*) - ;; - vxworks-simlinux | vxworks-simwindows | vxworks-spe) - ;; - nto-qnx*) - ;; - os2-emx) - ;; - *-eabi* | *-gnueabi*) - ;; - none-coff* | none-elf*) - # None (no kernel, i.e. freestanding / bare metal), - # can be paired with an output format "OS" - ;; - -*) - # Blank kernel with real OS is always fine. - ;; - *-*) - echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 - exit 1 - ;; -esac - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -case $vendor in - unknown) - case $cpu-$os in - *-riscix*) - vendor=acorn - ;; - *-sunos*) - vendor=sun - ;; - *-cnk* | *-aix*) - vendor=ibm - ;; - *-beos*) - vendor=be - ;; - *-hpux*) - vendor=hp - ;; - *-mpeix*) - vendor=hp - ;; - *-hiux*) - vendor=hitachi - ;; - *-unos*) - vendor=crds - ;; - *-dgux*) - vendor=dg - ;; - *-luna*) - vendor=omron - ;; - *-genix*) - vendor=ns - ;; - *-clix*) - vendor=intergraph - ;; - *-mvs* | *-opened*) - vendor=ibm - ;; - *-os400*) - vendor=ibm - ;; - s390-* | s390x-*) - vendor=ibm - ;; - *-ptx*) - vendor=sequent - ;; - *-tpf*) - vendor=ibm - ;; - *-vxsim* | *-vxworks* | *-windiss*) - vendor=wrs - ;; - *-aux*) - vendor=apple - ;; - *-hms*) - vendor=hitachi - ;; - *-mpw* | *-macos*) - vendor=apple - ;; - *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) - vendor=atari - ;; - *-vos*) - vendor=stratus - ;; - esac - ;; -esac - -echo "$cpu-$vendor-${kernel:+$kernel-}$os" -exit - -# Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/crates/libunbound-sys/unbound/configure.ac b/crates/libunbound-sys/unbound/configure.ac deleted file mode 100644 index 098988f5..00000000 --- a/crates/libunbound-sys/unbound/configure.ac +++ /dev/null @@ -1,2286 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. -AC_PREREQ([2.56]) -sinclude(acx_nlnetlabs.m4) -sinclude(ax_pthread.m4) -sinclude(acx_python.m4) -sinclude(ac_pkg_swig.m4) -sinclude(dnstap/dnstap.m4) -sinclude(dnscrypt/dnscrypt.m4) - -# must be numbers. ac_defun because of later processing -m4_define([VERSION_MAJOR],[1]) -m4_define([VERSION_MINOR],[18]) -m4_define([VERSION_MICRO],[0]) -AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound]) -AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR]) -AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR]) -AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO]) - -LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=22 -LIBUNBOUND_AGE=1 -# 1.0.0 had 0:12:0 -# 1.0.1 had 0:13:0 -# 1.0.2 had 0:14:0 -# 1.1.0 had 0:15:0 -# 1.1.1 had 0:16:0 -# 1.2.0 had 0:17:0 -# 1.2.1 had 0:18:0 -# 1.3.0 had 1:0:0 # ub_cancel and -export-symbols. -# 1.3.1 had 1:1:0 -# 1.3.2 had 1:2:0 -# 1.3.3 had 1:3:0 -# 1.3.4 had 1:4:0 -# 1.4.0-snapshots had 1:5:0 -# 1.4.0 had 1:5:0 (not 2:0:0) # ub_result.why_bogus -# 1.4.1 had 2:1:0 -# 1.4.2 had 2:2:0 -# 1.4.3 had 2:3:0 -# 1.4.4 had 2:4:0 -# 1.4.5 had 2:5:0 -# 1.4.6 had 2:6:0 -# 1.4.7 had 2:7:0 -# 1.4.8 had 2:8:0 -# 1.4.9 had 2:9:0 -# 1.4.10 had 2:10:0 -# 1.4.11 had 2:11:0 -# 1.4.12 had 2:12:0 -# 1.4.13 had 2:13:0 -# and 1.4.13p1 and 1.4.13.p2 -# 1.4.14 had 2:14:0 -# 1.4.15 had 3:0:1 # adds ub_version() -# 1.4.16 had 3:1:1 -# 1.4.17 had 3:2:1 -# 1.4.18 had 3:3:1 -# 1.4.19 had 3:4:1 -# 1.4.20 had 4:0:2 # adds libunbound.ttl # but shipped 3:5:1 -# 1.4.21 had 4:1:2 -# 1.4.22 had 4:1:2 -# 1.5.0 had 5:3:3 # adds ub_ctx_add_ta_autr -# 1.5.1 had 5:3:3 -# 1.5.2 had 5:5:3 -# 1.5.3 had 5:6:3 -# 1.5.4 had 5:7:3 -# 1.5.5 had 5:8:3 -# 1.5.6 had 5:9:3 -# 1.5.7 had 5:10:3 -# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub -# 1.5.9 had 6:1:4 -# 1.5.10 had 6:2:4 -# 1.6.0 had 6:3:4 -# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type -# 1.6.2 had 7:1:5 -# 1.6.3 had 7:2:5 -# 1.6.4 had 7:3:5 -# 1.6.5 had 7:4:5 -# 1.6.6 had 7:5:5 -# 1.6.7 had 7:6:5 -# 1.6.8 had 7:7:5 -# 1.7.0 had 7:8:5 -# 1.7.1 had 7:9:5 -# 1.7.2 had 7:10:5 -# 1.7.3 had 7:11:5 -# 1.8.0 had 8:0:0 # changes the event callback function signature -# 1.8.1 had 8:1:0 -# 1.8.2 had 8:2:0 -# 1.8.3 had 8:3:0 -# 1.9.0 had 9:0:1 # add ub_ctx_set_tls -# 1.9.1 had 9:1:1 -# 1.9.2 had 9:2:1 -# 1.9.3 had 9:3:1 -# 1.9.4 had 9:4:1 -# 1.9.5 had 9:5:1 -# 1.9.6 had 9:6:1 -# 1.10.0 had 9:7:1 -# 1.10.1 had 9:8:1 -# 1.11.0 had 9:9:1 -# 1.12.0 had 9:10:1 -# 1.13.0 had 9:11:1 -# 1.13.1 had 9:12:1 -# 1.13.2 had 9:13:1 -# 1.14.0 had 9:14:1 -# 1.15.0 had 9:15:1 -# 1.16.0 had 9:16:1 -# 1.16.1 had 9:17:1 -# 1.16.2 had 9:18:1 -# 1.16.3 had 9:19:1 -# 1.17.0 had 9:20:1 -# 1.17.1 had 9:21:1 -# 1.18.0 had 9:22:1 - -# Current -- the number of the binary API that we're implementing -# Revision -- which iteration of the implementation of the binary -# API are we supplying? -# Age -- How many previous binary API versions do we also -# support? -# -# If we release a new version that does not change the binary API, -# increment Revision. -# -# If we release a new version that changes the binary API, but does -# not break programs compiled against the old binary API, increment -# Current and Age. Set Revision to 0, since this is the first -# implementation of the new API. -# -# Otherwise, we're changing the binary API and breaking backward -# compatibility with old binaries. Increment Current. Set Age to 0, -# since we're backward compatible with no previous APIs. Set Revision -# to 0 too. -AC_SUBST(LIBUNBOUND_CURRENT) -AC_SUBST(LIBUNBOUND_REVISION) -AC_SUBST(LIBUNBOUND_AGE) - - -cmdln="`echo $@ | sed -e 's/\\\\/\\\\\\\\/g' | sed -e 's/"/\\\\"/'g`" -AC_DEFINE_UNQUOTED(CONFCMDLINE, ["$cmdln"], [Command line arguments used with configure]) - -CFLAGS="$CFLAGS" -AC_USE_SYSTEM_EXTENSIONS -if test "$ac_cv_header_minix_config_h" = "yes"; then - AC_DEFINE(_NETBSD_SOURCE,1, [Enable for compile on Minix]) -fi - -dnl -dnl By default set prefix to /usr/local -dnl -case "$prefix" in - NONE) - prefix="/usr/local" - ;; -esac -case "$exec_prefix" in - NONE) - exec_prefix="$prefix" - ;; -esac - -# are we on MinGW? -if uname -s 2>&1 | grep MINGW >/dev/null; then on_mingw="yes" -else - if echo $host | grep mingw >/dev/null; then on_mingw="yes" - else on_mingw="no"; fi -fi - -# -# Determine configuration file -# the eval is to evaluate shell expansion twice -UNBOUND_SBIN_DIR=`eval echo "${sbindir}"` -AC_SUBST(UNBOUND_SBIN_DIR) -UNBOUND_SYSCONF_DIR=`eval echo "${sysconfdir}"` -AC_SUBST(UNBOUND_SYSCONF_DIR) -UNBOUND_LOCALSTATE_DIR=`eval echo "${localstatedir}"` -AC_SUBST(UNBOUND_LOCALSTATE_DIR) -if test $on_mingw = "no"; then - ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"` -else - ub_conf_file="C:\\Program Files\\Unbound\\service.conf" -fi -AC_ARG_WITH([conf_file], - AS_HELP_STRING([--with-conf-file=path],[Pathname to the Unbound configuration file]), - [ub_conf_file="$withval"]) -AC_SUBST(ub_conf_file) -ACX_ESCAPE_BACKSLASH($ub_conf_file, hdr_config) -AC_DEFINE_UNQUOTED(CONFIGFILE, ["$hdr_config"], [Pathname to the Unbound configuration file]) -ub_conf_dir=`AS_DIRNAME(["$ub_conf_file"])` -AC_SUBST(ub_conf_dir) - -# Determine run, chroot directory and pidfile locations -AC_ARG_WITH(run-dir, - AS_HELP_STRING([--with-run-dir=path],[set default directory to chdir to (by default dir part of cfg file)]), - UNBOUND_RUN_DIR="$withval", -if test $on_mingw = no; then - UNBOUND_RUN_DIR=`dirname "$ub_conf_file"` -else - UNBOUND_RUN_DIR="" -fi -) -AC_SUBST(UNBOUND_RUN_DIR) -ACX_ESCAPE_BACKSLASH($UNBOUND_RUN_DIR, hdr_run) -AC_DEFINE_UNQUOTED(RUN_DIR, ["$hdr_run"], [Directory to chdir to]) - -AC_ARG_WITH(chroot-dir, - AS_HELP_STRING([--with-chroot-dir=path],[set default directory to chroot to (by default same as run-dir)]), - UNBOUND_CHROOT_DIR="$withval", -if test $on_mingw = no; then - UNBOUND_CHROOT_DIR="$UNBOUND_RUN_DIR" -else - UNBOUND_CHROOT_DIR="" -fi -) -AC_SUBST(UNBOUND_CHROOT_DIR) -ACX_ESCAPE_BACKSLASH($UNBOUND_CHROOT_DIR, hdr_chroot) -AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$hdr_chroot"], [Directory to chroot to]) - -AC_ARG_WITH(share-dir, - AS_HELP_STRING([--with-share-dir=path],[set default directory with shared data (by default same as share/unbound)]), - UNBOUND_SHARE_DIR="$withval", - UNBOUND_SHARE_DIR="$UNBOUND_RUN_DIR") -AC_SUBST(UNBOUND_SHARE_DIR) -AC_DEFINE_UNQUOTED(SHARE_DIR, ["$UNBOUND_SHARE_DIR"], [Shared data]) - -AC_ARG_WITH(pidfile, - AS_HELP_STRING([--with-pidfile=filename],[set default pathname to unbound pidfile (default run-dir/unbound.pid)]), - UNBOUND_PIDFILE="$withval", -if test $on_mingw = no; then - UNBOUND_PIDFILE="$UNBOUND_RUN_DIR/unbound.pid" -else - UNBOUND_PIDFILE="" -fi -) -AC_SUBST(UNBOUND_PIDFILE) -ACX_ESCAPE_BACKSLASH($UNBOUND_PIDFILE, hdr_pid) -AC_DEFINE_UNQUOTED(PIDFILE, ["$hdr_pid"], [default pidfile location]) - -AC_ARG_WITH(rootkey-file, - AS_HELP_STRING([--with-rootkey-file=filename],[set default pathname to root key file (default run-dir/root.key). This file is read and written.]), - UNBOUND_ROOTKEY_FILE="$withval", -if test $on_mingw = no; then - UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key" -else - UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key" -fi -) -AC_SUBST(UNBOUND_ROOTKEY_FILE) -ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTKEY_FILE, hdr_rkey) -AC_DEFINE_UNQUOTED(ROOT_ANCHOR_FILE, ["$hdr_rkey"], [default rootkey location]) - -AC_ARG_WITH(rootcert-file, - AS_HELP_STRING([--with-rootcert-file=filename],[set default pathname to root update certificate file (default run-dir/icannbundle.pem). This file need not exist if you are content with the builtin.]), - UNBOUND_ROOTCERT_FILE="$withval", -if test $on_mingw = no; then - UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem" -else - UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem" -fi -) -AC_SUBST(UNBOUND_ROOTCERT_FILE) -ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTCERT_FILE, hdr_rpem) -AC_DEFINE_UNQUOTED(ROOT_CERT_FILE, ["$hdr_rpem"], [default rootcert location]) - -AC_ARG_WITH(username, - AS_HELP_STRING([--with-username=user],[set default user that unbound changes to (default user is unbound)]), - UNBOUND_USERNAME="$withval", - UNBOUND_USERNAME="unbound") -AC_SUBST(UNBOUND_USERNAME) -AC_DEFINE_UNQUOTED(UB_USERNAME, ["$UNBOUND_USERNAME"], [default username]) - -AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled]) -ACX_RSRC_VERSION(wnvs) -AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_LANG([C]) -# allow user to override the -g -O2 flags. -default_cflags=no -if test "x$CFLAGS" = "x" ; then -ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"]) -ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"]) -default_cflags=yes -fi -AC_PROG_CC -ACX_DEPFLAG -ACX_DETERMINE_EXT_FLAGS_UNBOUND - -# debug mode flags warnings -AC_ARG_ENABLE(checking, AS_HELP_STRING([--enable-checking],[Enable warnings, asserts, makefile-dependencies])) -AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[same as enable-checking])) -if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug"; -else debug_enabled="$enable_checking"; fi -AC_SUBST(debug_enabled) -case "$debug_enabled" in - yes) - ACX_CHECK_COMPILER_FLAG(W, [CFLAGS="$CFLAGS -W"]) - ACX_CHECK_COMPILER_FLAG(Wall, [CFLAGS="$CFLAGS -Wall"]) - ACX_CHECK_COMPILER_FLAG(Wextra, [CFLAGS="$CFLAGS -Wextra"]) - ACX_CHECK_COMPILER_FLAG(Wdeclaration-after-statement, [CFLAGS="$CFLAGS -Wdeclaration-after-statement"]) - AC_DEFINE([UNBOUND_DEBUG], [], [define this to enable debug checks.]) - ;; - no|*) - # nothing to do. - ;; -esac -if test "$default_cflags" = "yes"; then - # only when CFLAGS was "" at the start, if the users wants to - # override we shouldn't add default cflags, because they wouldn't - # be able to turn off these options and set the CFLAGS wanted. - ACX_CHECK_FLTO - ACX_CHECK_PIE - ACX_CHECK_RELRO_NOW -fi - -AC_C_INLINE -ACX_CHECK_FORMAT_ATTRIBUTE -ACX_CHECK_UNUSED_ATTRIBUTE - -AC_DEFUN([CHECK_WEAK_ATTRIBUTE], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "weak" attribute) -AC_CACHE_VAL(ac_cv_c_weak_attribute, -[ac_cv_c_weak_attribute=no -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -__attribute__((weak)) void f(int x) { printf("%d", x); } -]], [[ - f(1); -]])],[ac_cv_c_weak_attribute="yes"],[ac_cv_c_weak_attribute="no"]) -]) - -AC_MSG_RESULT($ac_cv_c_weak_attribute) -if test $ac_cv_c_weak_attribute = yes; then - AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute]) - AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol]) -fi -])dnl End of CHECK_WEAK_ATTRIBUTE - -CHECK_WEAK_ATTRIBUTE - -AC_DEFUN([CHECK_NORETURN_ATTRIBUTE], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribute) -AC_CACHE_VAL(ac_cv_c_noreturn_attribute, -[ac_cv_c_noreturn_attribute=no -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -__attribute__((noreturn)) void f(int x) { printf("%d", x); } -]], [[ - f(1); -]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"]) -]) - -AC_MSG_RESULT($ac_cv_c_noreturn_attribute) -if test $ac_cv_c_noreturn_attribute = yes; then - AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute]) - AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program]) -fi -])dnl End of CHECK_NORETURN_ATTRIBUTE - -CHECK_NORETURN_ATTRIBUTE - -if test "$srcdir" != "."; then - CPPFLAGS="$CPPFLAGS -I$srcdir" -fi - -AC_DEFUN([ACX_YYLEX_DESTROY], [ - AC_MSG_CHECKING([for yylex_destroy]) - if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then - AC_DEFINE(LEX_HAS_YYLEX_DESTROY, 1, [if lex has yylex_destroy]) - AC_MSG_RESULT(yes) - else AC_MSG_RESULT(no); - LEX=":" - fi -]) - -AC_DEFUN([ACX_YYLEX_OPTION], [ - AC_MSG_CHECKING([for lex %option]) - if cat <&1 | grep yy_delete_buffer >/dev/null 2>&1; then -%option nounput -%% -EOF - AC_MSG_RESULT(yes) - else AC_MSG_RESULT(no); - LEX=":" - fi -]) - -AC_PROG_LEX([noyywrap]) -if test "$LEX" != "" -a "$LEX" != ":"; then -ACX_YYLEX_DESTROY -fi -if test "$LEX" != "" -a "$LEX" != ":"; then -ACX_YYLEX_OPTION -fi -if test "$LEX" = "" -o "$LEX" = ":"; then - if test ! -f util/configlexer.c; then - AC_MSG_ERROR([no lex and no util/configlexer.c: need flex and bison to compile from source repository.]) - fi -fi -AC_PROG_YACC -if test "$YACC" = "" -o "$YACC" = ":"; then - if test ! -f util/configparser.c; then - AC_MSG_ERROR([no yacc and no util/configparser.c: need flex and bison to compile from source repository.]) - fi -fi -AC_CHECK_PROG(doxygen, doxygen, doxygen) -AC_CHECK_TOOL(STRIP, strip) -ACX_LIBTOOL_C_ONLY - -# pkg-config is only needed for these options, do not require it otherwise -if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then -PKG_PROG_PKG_CONFIG -fi - -# Checks for header files. -AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT]) -# net/if.h portability for Darwin see: -# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html -AC_CHECK_HEADERS([net/if.h],,, [ -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -]) - -# Check for Apple header. This uncovers TARGET_OS_IPHONE, TARGET_OS_TV or TARGET_OS_WATCH -AC_CHECK_HEADERS([TargetConditionals.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif -]) - -# Check for Linux timestamping headers -AC_CHECK_HEADERS([linux/net_tstamp.h],,, [AC_INCLUDES_DEFAULT]) - -# check for types. -# Using own tests for int64* because autoconf builtin only give 32bit. -AC_CHECK_TYPE(int8_t, signed char) -AC_CHECK_TYPE(int16_t, short) -AC_CHECK_TYPE(int32_t, int) -AC_CHECK_TYPE(int64_t, long long) -AC_CHECK_TYPE(uint8_t, unsigned char) -AC_CHECK_TYPE(uint16_t, unsigned short) -AC_CHECK_TYPE(uint32_t, unsigned int) -AC_CHECK_TYPE(uint64_t, unsigned long long) -AC_TYPE_SIZE_T -AC_CHECK_TYPE(ssize_t, int) -AC_TYPE_UID_T -AC_TYPE_PID_T -AC_TYPE_OFF_T -ACX_TYPE_U_CHAR -ACX_TYPE_RLIM_T -ACX_TYPE_SOCKLEN_T -ACX_TYPE_IN_ADDR_T -ACX_TYPE_IN_PORT_T -ACX_CHECK_MEMCMP_SIGNED - -AC_CHECK_SIZEOF(time_t,,[ -AC_INCLUDES_DEFAULT -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif -]) -AC_CHECK_SIZEOF(size_t) - -# add option to disable the evil rpath -ACX_ARG_RPATH -AC_SUBST(RUNTIME_PATH) - -# check to see if libraries are needed for these functions. -AC_SEARCH_LIBS([inet_pton], [nsl]) -AC_SEARCH_LIBS([socket], [socket]) - -# check whether strptime also works -AC_DEFUN([AC_CHECK_STRPTIME_WORKS], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING(whether strptime works) -if test c${cross_compiling} = cno; then -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#define _XOPEN_SOURCE 600 -#include -int main(void) { struct tm tm; char *res; -res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm); -if (!res) return 2; -res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm); -if (!res) return 1; return 0; } -]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"]) -else -eval "ac_cv_c_strptime_works=maybe" -fi -AC_MSG_RESULT($ac_cv_c_strptime_works) -if test $ac_cv_c_strptime_works = no; then -AC_LIBOBJ(strptime) -else -AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.]) -fi -])dnl - -# check some functions of the OS before linking libs (while still runnable). -AC_FUNC_CHOWN -AC_FUNC_FORK -AC_DEFINE(RETSIGTYPE,void,[Return type of signal handlers, but autoconf 2.70 says 'your code may safely assume C89 semantics that RETSIGTYPE is void.']) -AC_FUNC_FSEEKO -ACX_SYS_LARGEFILE -ACX_CHECK_NONBLOCKING_BROKEN -ACX_MKDIR_ONE_ARG -AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])]) - -# check if we can use SO_REUSEPORT -reuseport_default=0 -if echo "$host" | $GREP -i -e linux >/dev/null; then reuseport_default=1; fi -if echo "$host" | $GREP -i -e dragonfly >/dev/null; then reuseport_default=1; fi -if test "$reuseport_default" = 1; then - AC_DEFINE(REUSEPORT_DEFAULT, 1, [if REUSEPORT is enabled by default]) -else - AC_DEFINE(REUSEPORT_DEFAULT, 0, [if REUSEPORT is enabled by default]) -fi - -# Include systemd.m4 - begin -sinclude(systemd.m4) -# Include systemd.m4 - end - -# set memory allocation checking if requested -AC_ARG_ENABLE(alloc-checks, AS_HELP_STRING([--enable-alloc-checks],[ enable to memory allocation statistics, for debug purposes ]), - , ) -AC_ARG_ENABLE(alloc-lite, AS_HELP_STRING([--enable-alloc-lite],[ enable for lightweight alloc assertions, for debug purposes ]), - , ) -AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]), - , ) -if test x_$enable_alloc_nonregional = x_yes; then - AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use]) -fi -if test x_$enable_alloc_checks = x_yes; then - AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use]) - SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo" - AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ) - ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo" - AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ) -else - if test x_$enable_alloc_lite = x_yes; then - AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use]) - else - ACX_FUNC_MALLOC([unbound]) - fi -fi - -# check windows threads (we use them, not pthreads, on windows). -if test "$on_mingw" = "yes"; then -# check windows threads - AC_CHECK_HEADERS([windows.h],,, [AC_INCLUDES_DEFAULT]) - AC_MSG_CHECKING([for CreateThread]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ -#ifdef HAVE_WINDOWS_H -#include -#endif -], [ - HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL); -])], - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads]) -, - AC_MSG_RESULT(no) -) - -else -# not on mingw, check thread libraries. - -# check for thread library. -# check this first, so that the pthread lib does not get linked in via -# libssl or libpython, and thus distorts the tests, and we end up using -# the non-threadsafe C libraries. -AC_ARG_WITH(pthreads, AS_HELP_STRING([--with-pthreads],[use pthreads library, or --without-pthreads to disable threading support.]), - [ ],[ withval="yes" ]) -ub_have_pthreads=no -if test x_$withval != x_no; then - AX_PTHREAD([ - AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]) - if test -n "$PTHREAD_LIBS"; then - LIBS="$PTHREAD_LIBS $LIBS" - fi - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - CC="$PTHREAD_CC" - ub_have_pthreads=yes - AC_CHECK_TYPES([pthread_spinlock_t, pthread_rwlock_t],,,[#include ]) - AC_CHECK_SIZEOF([unsigned long]) - AC_CHECK_SIZEOF(pthread_t) - - if echo "$CFLAGS" | $GREP -e "-pthread" >/dev/null; then - AC_MSG_CHECKING([if -pthread unused during linking]) - # catch clang warning 'argument unused during compilation' - AC_LANG_CONFTEST([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT -[[ -int main(void) {return 0;} -]])]) - pthread_unused="yes" - # first compile - echo "$CC $CFLAGS -c conftest.c -o conftest.o" >&AS_MESSAGE_LOG_FD - $CC $CFLAGS -c conftest.c -o conftest.o 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD - if test $? = 0; then - # then link - echo "$CC $CFLAGS -Werror $LDFLAGS $LIBS -o conftest contest.o" >&AS_MESSAGE_LOG_FD - $CC $CFLAGS -Werror $LDFLAGS $LIBS -o conftest conftest.o 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD - if test $? -ne 0; then - AC_MSG_RESULT(yes) - CFLAGS=`echo "$CFLAGS" | sed -e 's/-pthread//'` - PTHREAD_CFLAGS_ONLY="-pthread" - AC_SUBST(PTHREAD_CFLAGS_ONLY) - else - AC_MSG_RESULT(no) - fi - else - AC_MSG_RESULT(no) - fi # endif cc successful - rm -f conftest conftest.c conftest.o - fi # endif -pthread in CFLAGS - - ]) -fi - -# check solaris thread library -AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ]) -ub_have_sol_threads=no -if test x_$withval != x_no; then - if test x_$ub_have_pthreads != x_no; then - AC_MSG_WARN([Have pthreads already, ignoring --with-solaris-threads]) - else - AC_SEARCH_LIBS(thr_create, [thread], - [ - AC_DEFINE(HAVE_SOLARIS_THREADS, 1, [Using Solaris threads]) - - ACX_CHECK_COMPILER_FLAG(mt, [CFLAGS="$CFLAGS -mt"], - [CFLAGS="$CFLAGS -D_REENTRANT"]) - ub_have_sol_threads=yes - ] , [ - AC_MSG_ERROR([no solaris threads found.]) - ]) - fi -fi - -fi # end of non-mingw check of thread libraries - -# Check for SYSLOG_FACILITY -AC_ARG_WITH(syslog-facility, AS_HELP_STRING([--with-syslog-facility=LOCAL0 - LOCAL7],[ set SYSLOG_FACILITY, default DAEMON ]), - [ UNBOUND_SYSLOG_FACILITY="$withval" ], []) -case "${UNBOUND_SYSLOG_FACILITY}" in - - LOCAL[[0-7]]) UNBOUND_SYSLOG_FACILITY="LOG_${UNBOUND_SYSLOG_FACILITY}" ;; - - *) UNBOUND_SYSLOG_FACILITY="LOG_DAEMON" ;; - -esac -AC_DEFINE_UNQUOTED(UB_SYSLOG_FACILITY,${UNBOUND_SYSLOG_FACILITY},[the SYSLOG_FACILITY to use, default LOG_DAEMON]) - -# Check for dynamic library module -AC_ARG_WITH(dynlibmodule, - AS_HELP_STRING([--with-dynlibmodule],[build dynamic library module, or --without-dynlibmodule to disable it. (default=no)]), - [], [ withval="no" ]) - -if test x_$withval != x_no; then - AC_DEFINE(WITH_DYNLIBMODULE, 1, [Define if you want dynlib module.]) - WITH_DYNLIBMODULE=yes - AC_SUBST(WITH_DYNLIBMODULE) - DYNLIBMOD_OBJ="dynlibmod.lo" - AC_SUBST(DYNLIBMOD_OBJ) - DYNLIBMOD_HEADER='$(srcdir)/dynlibmod/dynlibmod.h' - AC_SUBST(DYNLIBMOD_HEADER) - if test $on_mingw = "no"; then - # link with -ldl if not already there, for all executables because - # dlopen call is in the dynlib module. For unbound executable, also - # export symbols. - AC_SEARCH_LIBS([dlopen], [dl]) - DYNLIBMOD_EXTRALIBS="-export-dynamic" - else - DYNLIBMOD_EXTRALIBS="-Wl,--export-all-symbols,--out-implib,libunbound.dll.a" - fi - AC_SUBST(DYNLIBMOD_EXTRALIBS) -fi - -# Check for PyUnbound -AC_ARG_WITH(pyunbound, - AS_HELP_STRING([--with-pyunbound],[build PyUnbound, or --without-pyunbound to skip it. (default=no)]), - [], [ withval="no" ]) - -ub_test_python=no -ub_with_pyunbound=no -if test x_$withval != x_no; then - ub_with_pyunbound=yes - ub_test_python=yes -fi - -# Check for Python module -AC_ARG_WITH(pythonmodule, - AS_HELP_STRING([--with-pythonmodule],[build Python module, or --without-pythonmodule to disable script engine. (default=no)]), - [], [ withval="no" ]) - -ub_with_pythonmod=no -if test x_$withval != x_no; then - ub_with_pythonmod=yes - ub_test_python=yes -fi - -# Check for Python & SWIG only on PyUnbound or PyModule -if test x_$ub_test_python != x_no; then - - # Check for Python - ub_have_python=no - ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS - AC_PYTHON_DEVEL - if test ! -z "$PYTHON_VERSION"; then - badversion="no" - if test "$PYTHON_VERSION_MAJOR" -lt 2; then - badversion="yes" - fi - if test "$PYTHON_VERSION_MAJOR" -eq 2 -a "$PYTHON_VERSION_MINOR" -lt 4; then - badversion="yes" - fi - if test "$badversion" = "yes"; then - AC_MSG_ERROR([Python version >= 2.4.0 is required]) - fi - - [PY_MAJOR_VERSION="`$PYTHON -c \"import sys; print(sys.version_info[0])\"`"] - AC_SUBST(PY_MAJOR_VERSION) - # Have Python - AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.]) - if test x_$ub_with_pythonmod != x_no; then - if test -n "$LIBS"; then - LIBS="$PYTHON_LDFLAGS $LIBS" - else - LIBS="$PYTHON_LDFLAGS" - fi - fi - PYTHON_LIBS="$PYTHON_LDFLAGS" - AC_SUBST(PYTHON_LIBS) - if test -n "$CPPFLAGS"; then - CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" - else - CPPFLAGS="$PYTHON_CPPFLAGS" - fi - if test "$PYTHON_LIBDIR" != "/usr/lib" -a "$PYTHON_LIBDIR" != "" -a "$PYTHON_LIBDIR" != "/usr/lib64"; then - ACX_RUNTIME_PATH_ADD([$PYTHON_LIBDIR]) - fi - ub_have_python=yes - PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"], - [PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"], - [PC_PY_DEPENDENCY="python"]) - AC_SUBST(PC_PY_DEPENDENCY) - - # Check for SWIG - ub_have_swig=no - AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable])) - if test "$enable_swig_version_check" = "yes"; then - AC_PROG_SWIG(2.0.1) - else - AC_PROG_SWIG - fi - AC_MSG_CHECKING(SWIG) - if test ! -x "$SWIG"; then - AC_MSG_ERROR([failed to find swig tool, install it, or do not build Python module and PyUnbound]) - else - AC_DEFINE(HAVE_SWIG, 1, [Define if you have Swig libraries and header files.]) - AC_SUBST(swig, "$SWIG") - AC_MSG_RESULT(present) - - # If have Python & SWIG - # Declare PythonMod - if test x_$ub_with_pythonmod != x_no; then - AC_DEFINE(WITH_PYTHONMODULE, 1, [Define if you want Python module.]) - WITH_PYTHONMODULE=yes - AC_SUBST(WITH_PYTHONMODULE) - PYTHONMOD_OBJ="pythonmod.lo pythonmod_utils.lo" - AC_SUBST(PYTHONMOD_OBJ) - PYTHONMOD_HEADER='$(srcdir)/pythonmod/pythonmod.h' - AC_SUBST(PYTHONMOD_HEADER) - PYTHONMOD_INSTALL=pythonmod-install - AC_SUBST(PYTHONMOD_INSTALL) - PYTHONMOD_UNINSTALL=pythonmod-uninstall - AC_SUBST(PYTHONMOD_UNINSTALL) - fi - - # Declare PyUnbound - if test x_$ub_with_pyunbound != x_no; then - AC_DEFINE(WITH_PYUNBOUND, 1, [Define if you want PyUnbound.]) - WITH_PYUNBOUND=yes - AC_SUBST(WITH_PYUNBOUND) - PYUNBOUND_OBJ="libunbound_wrap.lo" - AC_SUBST(PYUNBOUND_OBJ) - PYUNBOUND_TARGET="_unbound.la" - AC_SUBST(PYUNBOUND_TARGET) - PYUNBOUND_INSTALL=pyunbound-install - AC_SUBST(PYUNBOUND_INSTALL) - PYUNBOUND_UNINSTALL=pyunbound-uninstall - AC_SUBST(PYUNBOUND_UNINSTALL) - fi - fi - else - AC_MSG_RESULT([*** Python libraries not found, won't build PythonMod or PyUnbound ***]) - ub_with_pyunbound=no - ub_with_pythonmod=no - fi -fi - -if test "`uname`" = "NetBSD"; then - NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_' - AC_SUBST(NETBSD_LINTFLAGS) -fi - -if test "`uname`" = "Linux"; then - # splint cannot parse modern c99 header files - GCC_DOCKER_LINTFLAGS='-syntax' - AC_SUBST(GCC_DOCKER_LINTFLAGS) -fi -CONFIG_DATE=`date +%Y%m%d` -AC_SUBST(CONFIG_DATE) - -# Checks for libraries. - -# libnss -USE_NSS="no" -AC_ARG_WITH([nss], AS_HELP_STRING([--with-nss=path],[use libnss instead of openssl, installed at path.]), - [ - USE_NSS="yes" - AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto]) - if test "$withval" != "" -a "$withval" != "yes"; then - CPPFLAGS="$CPPFLAGS -I$withval/include/nss3" - LDFLAGS="$LDFLAGS -L$withval/lib" - ACX_RUNTIME_PATH_ADD([$withval/lib]) - CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS" - else - CPPFLAGS="$CPPFLAGS -I/usr/include/nss3" - CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS" - fi - LIBS="$LIBS -lnss3 -lnspr4" - SSLLIB="" - PC_CRYPTO_DEPENDENCY="nss nspr" - AC_SUBST(PC_CRYPTO_DEPENDENCY) - ] -) - -# libnettle -USE_NETTLE="no" -AC_ARG_WITH([nettle], AS_HELP_STRING([--with-nettle=path],[use libnettle as crypto library, installed at path.]), - [ - USE_NETTLE="yes" - AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto]) - AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT]) - if test "$withval" != "" -a "$withval" != "yes"; then - CPPFLAGS="$CPPFLAGS -I$withval/include/nettle" - LDFLAGS="$LDFLAGS -L$withval/lib" - ACX_RUNTIME_PATH_ADD([$withval/lib]) - else - CPPFLAGS="$CPPFLAGS -I/usr/include/nettle" - fi - LIBS="$LIBS -lhogweed -lnettle -lgmp" - SSLLIB="" - PC_CRYPTO_DEPENDENCY="hogweed nettle" - AC_SUBST(PC_CRYPTO_DEPENDENCY) - ] -) - -# openssl -if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then -ACX_WITH_SSL -ACX_LIB_SSL -SSLLIB="-lssl" - -PC_CRYPTO_DEPENDENCY="" -AC_SUBST(PC_CRYPTO_DEPENDENCY) - -# check if -lcrypt32 is needed because CAPIENG needs that. (on windows) -BAKLIBS="$LIBS" -LIBS="-lssl $LIBS" -AC_MSG_CHECKING([if libssl needs -lcrypt32]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ - int EVP_sha256(void); - (void)EVP_sha256(); -]])], [ - AC_MSG_RESULT([no]) - LIBS="$BAKLIBS" -], [ - AC_MSG_RESULT([yes]) - LIBS="$BAKLIBS" - LIBS="$LIBS -lcrypt32" -]) - -AC_MSG_CHECKING([for LibreSSL]) -if grep VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL]) - # libressl provides these compat functions, but they may also be - # declared by the OS in libc. See if they have been declared. - AC_CHECK_DECLS([strlcpy,strlcat,arc4random,arc4random_uniform]) -else - AC_MSG_RESULT([no]) -fi -AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex]) - -# these check_funcs need -lssl -BAKLIBS="$LIBS" -LIBS="-lssl $LIBS" -AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb SSL_get0_alpn_selected SSL_CTX_set_alpn_protos SSL_get1_peer_certificate]) -LIBS="$BAKLIBS" - -AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [ -AC_INCLUDES_DEFAULT -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif -#include -#include -]) - -if test "$ac_cv_func_HMAC_Init_ex" = "yes"; then -# check function return type. -AC_MSG_CHECKING(the return type of HMAC_Init_ex) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif -#include -#include -], [ - HMAC_CTX* hmac_ctx = NULL; - void* hmac_key = NULL; - const EVP_MD* digest = NULL; - int x = HMAC_Init_ex(hmac_ctx, hmac_key, 32, digest, NULL); - (void)x; -])], [ - AC_MSG_RESULT(int) -], [ - AC_MSG_RESULT(void) - AC_DEFINE([HMAC_INIT_EX_RETURNS_VOID], 1, [If HMAC_Init_ex() returns void]) -]) -fi - -fi -AC_SUBST(SSLLIB) - -# libbsd -AC_ARG_WITH([libbsd], AS_HELP_STRING([--with-libbsd],[Use portable libbsd functions]), [ - AC_CHECK_HEADERS([bsd/string.h bsd/stdlib.h],,, [AC_INCLUDES_DEFAULT]) - if test "x$ac_cv_header_bsd_string_h" = xyes -a "x$ac_cv_header_bsd_stdlib_h" = xyes; then - for func in strlcpy strlcat arc4random arc4random_uniform reallocarray; do - AC_SEARCH_LIBS([$func], [bsd], [ - AC_DEFINE(HAVE_LIBBSD, 1, [Use portable libbsd functions]) - PC_LIBBSD_DEPENDENCY=libbsd - AC_SUBST(PC_LIBBSD_DEPENDENCY) - ]) - done - fi -]) - -AC_ARG_ENABLE(sha1, AS_HELP_STRING([--disable-sha1],[Disable SHA1 RRSIG support, does not disable nsec3 support])) -case "$enable_sha1" in - no) - ;; - yes|*) - AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.]) - ;; -esac - - -AC_ARG_ENABLE(sha2, AS_HELP_STRING([--disable-sha2],[Disable SHA256 and SHA512 RRSIG support])) -case "$enable_sha2" in - no) - ;; - yes|*) - AC_DEFINE([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.]) - ;; -esac - -AC_ARG_ENABLE(subnet, AS_HELP_STRING([--enable-subnet],[Enable client subnet])) -case "$enable_subnet" in - yes) - AC_DEFINE([CLIENT_SUBNET], [1], [Define this to enable client subnet option.]) - SUBNET_OBJ="edns-subnet.lo subnetmod.lo addrtree.lo subnet-whitelist.lo" - AC_SUBST(SUBNET_OBJ) - SUBNET_HEADER='$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/edns-subnet/addrtree.h' - AC_SUBST(SUBNET_HEADER) - ;; - no|*) - ;; -esac - -# check whether gost also works -AC_DEFUN([AC_CHECK_GOST_WORKS], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING([if GOST works]) -if test c${cross_compiling} = cno; then -BAKCFLAGS="$CFLAGS" -if test -n "$ssldir"; then - CFLAGS="$CFLAGS -Wl,-rpath,$ssldir_lib" -fi -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include -#include -#include -#include -#include -/* routine to load gost (from sldns) */ -int load_gost_id(void) -{ - static int gost_id = 0; - const EVP_PKEY_ASN1_METHOD* meth; - ENGINE* e; - - if(gost_id) return gost_id; - - /* see if configuration loaded gost implementation from other engine*/ - meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); - if(meth) { - EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); - return gost_id; - } - - /* see if engine can be loaded already */ - e = ENGINE_by_id("gost"); - if(!e) { - /* load it ourself, in case statically linked */ - ENGINE_load_builtin_engines(); - ENGINE_load_dynamic(); - e = ENGINE_by_id("gost"); - } - if(!e) { - /* no gost engine in openssl */ - return 0; - } - if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { - ENGINE_finish(e); - ENGINE_free(e); - return 0; - } - - meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); - if(!meth) { - /* algo not found */ - ENGINE_finish(e); - ENGINE_free(e); - return 0; - } - EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); - return gost_id; -} -int main(void) { - EVP_MD_CTX* ctx; - const EVP_MD* md; - unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */ - const char* str = "Hello world"; - const unsigned char check[] = { - 0x40 , 0xed , 0xf8 , 0x56 , 0x5a , 0xc5 , 0x36 , 0xe1 , - 0x33 , 0x7c , 0x7e , 0x87 , 0x62 , 0x1c , 0x42 , 0xe0 , - 0x17 , 0x1b , 0x5e , 0xce , 0xa8 , 0x46 , 0x65 , 0x4d , - 0x8d , 0x3e , 0x22 , 0x9b , 0xe1 , 0x30 , 0x19 , 0x9d - }; - OPENSSL_config(NULL); - (void)load_gost_id(); - md = EVP_get_digestbyname("md_gost94"); - if(!md) return 1; - memset(digest, 0, sizeof(digest)); - ctx = EVP_MD_CTX_create(); - if(!ctx) return 2; - if(!EVP_DigestInit_ex(ctx, md, NULL)) return 3; - if(!EVP_DigestUpdate(ctx, str, 10)) return 4; - if(!EVP_DigestFinal_ex(ctx, digest, NULL)) return 5; - /* uncomment to see the hash calculated. - {int i; - for(i=0; i<32; i++) - printf(" %2.2x", (int)digest[i]); - printf("\n");} - */ - if(memcmp(digest, check, sizeof(check)) != 0) - return 6; - return 0; -} -]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"]) -CFLAGS="$BAKCFLAGS" -else -eval "ac_cv_c_gost_works=maybe" -fi -AC_MSG_RESULT($ac_cv_c_gost_works) -])dnl - -AC_ARG_ENABLE(gost, AS_HELP_STRING([--disable-gost],[Disable GOST support])) -use_gost="no" -if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then -case "$enable_gost" in - no) - ;; - *) - AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])]) - AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])]) - AC_CHECK_GOST_WORKS - if test "$ac_cv_c_gost_works" != no; then - use_gost="yes" - AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.]) - fi - ;; -esac -fi dnl !USE_NSS && !USE_NETTLE - -AC_ARG_ENABLE(ecdsa, AS_HELP_STRING([--disable-ecdsa],[Disable ECDSA support])) -use_ecdsa="no" -case "$enable_ecdsa" in - no) - ;; - *) - if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then - AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])]) - AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])]) - AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT -#include - ]) - # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency) - AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP]) - if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then - if grep OPENSSL_VERSION_NUMBER $ssldir_include/openssl/opensslv.h | grep 0x0 >/dev/null; then - AC_MSG_RESULT([no]) - AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl]) - else - AC_MSG_RESULT([yes]) - fi - else - # not OpenSSL, thus likely LibreSSL, which supports it - AC_MSG_RESULT([yes]) - fi - fi - # we now know we have ECDSA and the required curves. - AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.]) - use_ecdsa="yes" - ;; -esac - -AC_ARG_ENABLE(dsa, AS_HELP_STRING([--disable-dsa],[Disable DSA support])) -use_dsa="no" -case "$enable_dsa" in - yes) - # detect if DSA is supported, and turn it off if not. - if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then - AC_CHECK_FUNC(DSA_SIG_new, [ - AC_CHECK_TYPE(DSA_SIG*, [ - AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.]) - ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.]) - fi ], [ -AC_INCLUDES_DEFAULT -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif - ]) - ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.]) - fi ]) - else - AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.]) - fi - ;; - *) - # disable dsa by default, RFC 8624 section 3.1, validators MUST NOT - # support DSA for DNSSEC Validation. - ;; -esac - -AC_ARG_WITH(deprecate-rsa-1024, AS_HELP_STRING([--with-deprecate-rsa-1024],[Deprecate RSA 1024 bit length, makes that an unsupported key, for use when OpenSSL FIPS refuses 1024 bit verification])) -if test "$with_deprecate_rsa_1024" = "yes"; then - AC_DEFINE([DEPRECATE_RSA_1024], [1], [Deprecate RSA 1024 bit length, makes that an unsupported key]) -fi - -AC_ARG_ENABLE(ed25519, AS_HELP_STRING([--disable-ed25519],[Disable ED25519 support])) -use_ed25519="no" -case "$enable_ed25519" in - no) - ;; - *) - if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then - AC_CHECK_DECLS([NID_ED25519], [ - use_ed25519="yes" - ], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.]) - fi ], [AC_INCLUDES_DEFAULT -#include - ]) - fi - if test $USE_NETTLE = "yes"; then - AC_CHECK_HEADERS([nettle/eddsa.h], use_ed25519="yes",, [AC_INCLUDES_DEFAULT]) - fi - if test $use_ed25519 = "yes"; then - AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.]) - fi - ;; -esac - -AC_ARG_ENABLE(ed448, AS_HELP_STRING([--disable-ed448],[Disable ED448 support])) -use_ed448="no" -case "$enable_ed448" in - no) - ;; - *) - if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then - AC_CHECK_DECLS([NID_ED448], [ - use_ed448="yes" - ], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.]) - fi ], [AC_INCLUDES_DEFAULT -#include - ]) - fi - if test $use_ed448 = "yes"; then - AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.]) - fi - ;; -esac - -AC_ARG_ENABLE(event-api, AS_HELP_STRING([--enable-event-api],[Enable (experimental) pluggable event base libunbound API installed to unbound-event.h])) -case "$enable_event_api" in - yes) - AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install]) - AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall]) - ;; - *) - ;; -esac - -AC_ARG_ENABLE(tfo-client, AS_HELP_STRING([--enable-tfo-client],[Enable TCP Fast Open for client mode])) -case "$enable_tfo_client" in - yes) - case "$host_os" in - linux*) AC_CHECK_DECL([MSG_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])], - [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])], - [AC_INCLUDES_DEFAULT -#include -]) - AC_DEFINE_UNQUOTED([USE_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.]) - ;; - darwin*) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])], - [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])], - [AC_INCLUDES_DEFAULT -#include -]) - AC_DEFINE_UNQUOTED([USE_OSX_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.]) - ;; - esac - ;; - no|*) - ;; -esac - -AC_ARG_ENABLE(tfo-server, AS_HELP_STRING([--enable-tfo-server],[Enable TCP Fast Open for server mode])) -case "$enable_tfo_server" in - yes) - AC_CHECK_DECL([TCP_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO])], [AC_MSG_ERROR([TCP Fast Open is not available for server mode: please rerun without --enable-tfo-server])], [AC_INCLUDES_DEFAULT -#include - ]) - AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable server TCP Fast Open.]) - ;; - no|*) - ;; -esac - -# check for libevent -AC_ARG_WITH(libevent, AS_HELP_STRING([--with-libevent=pathname],[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]), - [ ],[ with_libevent="no" ]) -if test "x_$with_libevent" != x_no; then - AC_DEFINE([USE_LIBEVENT], [1], [Define if you enable libevent]) - AC_MSG_CHECKING(for libevent) - if test "x_$with_libevent" = x_ -o "x_$with_libevent" = x_yes; then - with_libevent="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $with_libevent; do - thedir="$dir" - if test -f "$dir/include/event.h" -o -f "$dir/include/event2/event.h"; then - found_libevent="yes" - dnl assume /usr is in default path. - if test "$thedir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$thedir/include" - fi - break; - fi - done - if test x_$found_libevent != x_yes; then - if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then - # libevent source directory - AC_MSG_RESULT(found in $thedir) - CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include" - BAK_LDFLAGS_SET="1" - BAK_LDFLAGS="$LDFLAGS" - # remove evdns from linking - mkdir build >/dev/null 2>&1 - mkdir build/libevent >/dev/null 2>&1 - mkdir build/libevent/.libs >/dev/null 2>&1 - ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` - ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo | grep -v bufferevent_openssl\.lo` - ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` - cp $ev_files_o build/libevent - cp $ev_files_lo build/libevent - cp $ev_files_libso build/libevent/.libs - LATE_LDFLAGS="build/libevent/*.lo -lm" - LDFLAGS="build/libevent/*.o $LDFLAGS -lm" - else - AC_MSG_ERROR([Cannot find the libevent library in $with_libevent -You can restart ./configure --with-libevent=no to use a builtin alternative. -Please note that this alternative is not as capable as libevent when using -large outgoing port ranges. ]) - fi - else - AC_MSG_RESULT(found in $thedir) - dnl if event2 exists and no event lib in dir itself, use subdir - if test ! -f $thedir/lib/libevent.a -a ! -f $thedir/lib/libevent.so -a -d "$thedir/lib/event2"; then - LDFLAGS="$LDFLAGS -L$thedir/lib/event2" - ACX_RUNTIME_PATH_ADD([$thedir/lib/event2]) - else - dnl assume /usr is in default path, do not add "". - if test "$thedir" != "/usr" -a "$thedir" != ""; then - LDFLAGS="$LDFLAGS -L$thedir/lib" - ACX_RUNTIME_PATH_ADD([$thedir/lib]) - fi - fi - fi - # check for library used by libevent after 1.3c - AC_SEARCH_LIBS([clock_gettime], [rt]) - - # is the event.h header libev or libevent? - AC_CHECK_HEADERS([event.h],,, [AC_INCLUDES_DEFAULT]) - AC_CHECK_DECL(EV_VERSION_MAJOR, [ - AC_SEARCH_LIBS(event_set, [ev]) - ],[ - AC_SEARCH_LIBS(event_set, [event]) - ],[AC_INCLUDES_DEFAULT -#include - ]) - AC_CHECK_FUNCS([event_base_free]) # only in libevent 1.2 and later - AC_CHECK_FUNCS([event_base_once]) # only in libevent 1.4.1 and later - AC_CHECK_FUNCS([event_base_new]) # only in libevent 1.4.1 and later - AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later - AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51) - AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00) - AC_CHECK_FUNCS([event_assign]) # in libevent, for thread-safety - AC_CHECK_DECLS([evsignal_assign], [], [], [AC_INCLUDES_DEFAULT -#ifdef HAVE_EVENT_H -# include -#else -# include "event2/event.h" -#endif - ]) - PC_LIBEVENT_DEPENDENCY="libevent" - AC_SUBST(PC_LIBEVENT_DEPENDENCY) - if test -n "$BAK_LDFLAGS_SET"; then - LDFLAGS="$BAK_LDFLAGS" - fi -else - AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events]) -fi - -# check for libexpat -AC_ARG_WITH(libexpat, AS_HELP_STRING([--with-libexpat=path],[specify explicit path for libexpat.]), - [ ],[ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" ]) -AC_MSG_CHECKING(for libexpat) -found_libexpat="no" -for dir in $withval ; do - if test -f "$dir/include/expat.h"; then - found_libexpat="yes" - dnl assume /usr is in default path. - if test "$dir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - AC_MSG_RESULT(found in $dir) - break; - fi -done -if test x_$found_libexpat != x_yes; then - AC_MSG_ERROR([Could not find libexpat, expat.h]) -fi -AC_CHECK_HEADERS([expat.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT -#include -]) - -# hiredis (redis C client for cachedb) -AC_ARG_WITH(libhiredis, AS_HELP_STRING([--with-libhiredis=path],[specify explicit path for libhiredis.]), - [ ],[ withval="no" ]) -found_libhiredis="no" -if test x_$withval = x_yes -o x_$withval != x_no; then - AC_MSG_CHECKING(for libhiredis) - if test x_$withval = x_ -o x_$withval = x_yes; then - withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $withval ; do - if test -f "$dir/include/hiredis/hiredis.h"; then - found_libhiredis="yes" - dnl assume /usr is in default path. - if test "$dir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - AC_MSG_RESULT(found in $dir) - AC_DEFINE([USE_REDIS], [1], [Define this to use hiredis client.]) - LIBS="$LIBS -lhiredis" - break; - fi - done - if test x_$found_libhiredis != x_yes; then - AC_MSG_ERROR([Could not find libhiredis, hiredis.h]) - fi - AC_CHECK_HEADERS([hiredis/hiredis.h],,, [AC_INCLUDES_DEFAULT]) - AC_CHECK_DECLS([redisConnect], [], [], [AC_INCLUDES_DEFAULT - #include - ]) -fi - -# nghttp2 -AC_ARG_WITH(libnghttp2, AS_HELP_STRING([--with-libnghttp2=path],[specify explicit path for libnghttp2.]), - [ ],[ withval="no" ]) -found_libnghttp2="no" -if test x_$withval = x_yes -o x_$withval != x_no; then - AC_MSG_CHECKING(for libnghttp2) - if test x_$withval = x_ -o x_$withval = x_yes; then - withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $withval ; do - if test -f "$dir/include/nghttp2/nghttp2.h"; then - found_libnghttp2="yes" - dnl assume /usr is in default path. - if test "$dir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - AC_MSG_RESULT(found in $dir) - AC_DEFINE([HAVE_NGHTTP2], [1], [Define this to use nghttp2 client.]) - LIBS="$LIBS -lnghttp2" - break; - fi - done - if test x_$found_libnghttp2 != x_yes; then - AC_MSG_ERROR([Could not find libnghttp2, nghttp2.h]) - fi - AC_CHECK_HEADERS([nghttp2/nghttp2.h],,, [AC_INCLUDES_DEFAULT]) - AC_CHECK_DECLS([nghttp2_session_server_new], [], [], [AC_INCLUDES_DEFAULT - #include - ]) -fi - -# set static linking for uninstalled libraries if requested -AC_SUBST(staticexe) -staticexe="" -AC_ARG_ENABLE(static-exe, AS_HELP_STRING([--enable-static-exe],[ enable to compile executables statically against (event) uninstalled libs, for debug purposes ]), - , ) -if test x_$enable_static_exe = x_yes; then - staticexe="-static" - if test "$on_mingw" = yes; then - staticexe="-all-static" - # for static compile, include gdi32 and zlib here. - if echo $LIBS | grep 'lgdi32' >/dev/null; then - : - else - LIBS="$LIBS -lgdi32" - fi - AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ]) - LIBS="$LIBS -l:libssp.a" - fi -fi - -# set full static linking if requested -AC_ARG_ENABLE(fully-static, AS_HELP_STRING([--enable-fully-static],[ enable to compile fully static ]), - , ) -if test x_$enable_fully_static = x_yes; then - staticexe="-all-static" - if test "$on_mingw" = yes; then - # for static compile, include gdi32 and zlib here. - if echo $LIBS | grep 'lgdi32' >/dev/null; then - : - else - LIBS="$LIBS -lgdi32" - fi - AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ]) - LIBS="$LIBS -l:libssp.a" - fi -fi - -# set lock checking if requested -AC_ARG_ENABLE(lock_checks, AS_HELP_STRING([--enable-lock-checks],[ enable to check lock and unlock calls, for debug purposes ]), - , ) -if test x_$enable_lock_checks = x_yes; then - AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).]) - CHECKLOCK_OBJ="checklocks.lo" - AC_SUBST(CHECKLOCK_OBJ) -fi - -ACX_CHECK_GETADDRINFO_WITH_INCLUDES -if test "$USE_WINSOCK" = 1; then - AC_DEFINE(UB_ON_WINDOWS, 1, [Use win32 resources and API]) - AC_CHECK_HEADERS([iphlpapi.h],,, [AC_INCLUDES_DEFAULT -#include - ]) - AC_CHECK_TOOL(WINDRES, windres) - LIBS="$LIBS -liphlpapi -lcrypt32" - WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe" - AC_SUBST(WINAPPS) - WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c" - AC_SUBST(WIN_DAEMON_SRC) - WIN_DAEMON_OBJ="win_svc.lo w_inst.lo" - AC_SUBST(WIN_DAEMON_OBJ) - WIN_DAEMON_OBJ_LINK="rsrc_unbound.o" - AC_SUBST(WIN_DAEMON_OBJ_LINK) - WIN_HOST_OBJ_LINK="rsrc_unbound_host.o" - AC_SUBST(WIN_HOST_OBJ_LINK) - WIN_UBANCHOR_OBJ_LINK="rsrc_unbound_anchor.o log.lo locks.lo" - AC_SUBST(WIN_UBANCHOR_OBJ_LINK) - WIN_CONTROL_OBJ_LINK="rsrc_unbound_control.o" - AC_SUBST(WIN_CONTROL_OBJ_LINK) - WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o" - AC_SUBST(WIN_CHECKCONF_OBJ_LINK) - AC_DEFINE(__USE_MINGW_ANSI_STDIO, 1, [defined to use gcc ansi snprintf and sscanf that understands %lld when compiled for windows.]) -fi -if test $ac_cv_func_getaddrinfo = no; then - AC_LIBOBJ([fake-rfc2553]) -fi -# check after getaddrinfo for its libraries -ACX_FUNC_IOCTLSOCKET - -# see if daemon(3) exists, and if it is deprecated. -AC_CHECK_FUNCS([daemon]) -if test $ac_cv_func_daemon = yes; then - ACX_FUNC_DEPRECATED([daemon], [(void)daemon(0, 0);], [ -#include -#include -]) -fi - -AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[ -AC_INCLUDES_DEFAULT -#ifdef HAVE_SYS_UN_H -#include -#endif -]) -AC_CHECK_MEMBERS([struct in_pktinfo.ipi_spec_dst],,,[ -AC_INCLUDES_DEFAULT -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif -]) - -AC_MSG_CHECKING([for htobe64]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#ifdef HAVE_ENDIAN_H -# include -#endif -#ifdef HAVE_SYS_ENDIAN_H -# include -#endif -], [unsigned long long x = htobe64(0); printf("%u", (unsigned)x);])], - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_HTOBE64, 1, [If we have htobe64]), - AC_MSG_RESULT(no)) - -AC_MSG_CHECKING([for be64toh]) -AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#ifdef HAVE_ENDIAN_H -# include -#endif -#ifdef HAVE_SYS_ENDIAN_H -# include -#endif -], [unsigned long long x = be64toh(0); printf("%u", (unsigned)x);])], - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_BE64TOH, 1, [If we have be64toh]), - AC_MSG_RESULT(no)) - -AC_SEARCH_LIBS([setusercontext], [util]) -AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll gettid]) -AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])]) -AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])]) - -# check if setreuid en setregid fail, on MacOSX10.4(darwin8). -if echo $host_os | grep darwin8 > /dev/null; then - AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work]) -fi -AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [ -AC_INCLUDES_DEFAULT -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif -]) -AC_REPLACE_FUNCS(inet_aton) -AC_REPLACE_FUNCS(inet_pton) -AC_REPLACE_FUNCS(inet_ntop) -AC_REPLACE_FUNCS(snprintf) -# test if snprintf return the proper length -if test "x$ac_cv_func_snprintf" = xyes; then - if test c${cross_compiling} = cno; then - AC_MSG_CHECKING([for correct snprintf return value]) - AC_RUN_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT -[[ -int main(void) { return !(snprintf(NULL, 0, "test") == 4); } -]])], [AC_MSG_RESULT(yes)], [ - AC_MSG_RESULT(no) - AC_DEFINE([SNPRINTF_RET_BROKEN], [], [define if (v)snprintf does not return length needed, (but length used)]) - AC_LIBOBJ(snprintf) - ]) - fi -fi -AC_REPLACE_FUNCS(strlcat) -AC_REPLACE_FUNCS(strlcpy) -AC_REPLACE_FUNCS(memmove) -AC_REPLACE_FUNCS(gmtime_r) -AC_REPLACE_FUNCS(isblank) -AC_REPLACE_FUNCS(explicit_bzero) -dnl without CTIME, ARC4-functions and without reallocarray. -LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS" -AC_SUBST(LIBOBJ_WITHOUT_CTIMEARC4) -AC_MSG_CHECKING([for reallocarray]) -AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT -[[ -#ifndef _OPENBSD_SOURCE -#define _OPENBSD_SOURCE 1 -#endif -#include -int main(void) { - void* p = reallocarray(NULL, 10, 100); - free(p); - return 0; -} -]])], [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)]) -], [ - AC_MSG_RESULT(no) - AC_LIBOBJ(reallocarray) -]) -AC_CHECK_DECLS([reallocarray]) -if test "$USE_NSS" = "no"; then - AC_REPLACE_FUNCS(arc4random) - AC_REPLACE_FUNCS(arc4random_uniform) - if test "$ac_cv_func_arc4random" = "no"; then - AC_LIBOBJ(arc4_lock) - AC_CHECK_FUNCS([getentropy],,[ - if test "$USE_WINSOCK" = 1; then - AC_LIBOBJ(getentropy_win) - else - case "$host" in - Darwin|*darwin*) - AC_LIBOBJ(getentropy_osx) - ;; - *solaris*|*sunos*|SunOS) - AC_LIBOBJ(getentropy_solaris) - AC_CHECK_HEADERS([sys/sha2.h],, [ - AC_CHECK_FUNCS([SHA512_Update],,[ - AC_LIBOBJ(sha512) - ]) - ], [AC_INCLUDES_DEFAULT]) - if test "$ac_cv_header_sys_sha2_h" = "yes"; then - # this lib needed for sha2 on solaris - LIBS="$LIBS -lmd" - fi - AC_SEARCH_LIBS([clock_gettime], [rt]) - ;; - *freebsd*|*FreeBSD) - AC_LIBOBJ(getentropy_freebsd) - ;; - *linux*|Linux|*) - AC_LIBOBJ(getentropy_linux) - AC_CHECK_FUNCS([SHA512_Update],,[ - AC_DEFINE([COMPAT_SHA512], [1], [Do sha512 definitions in config.h]) - AC_LIBOBJ(sha512) - ]) - AC_CHECK_HEADERS([sys/sysctl.h],,, [AC_INCLUDES_DEFAULT]) - AC_CHECK_FUNCS([getauxval]) - AC_SEARCH_LIBS([clock_gettime], [rt]) - ;; - esac - fi - ]) - fi -fi -LIBOBJ_WITHOUT_CTIME="$LIBOBJS" -AC_SUBST(LIBOBJ_WITHOUT_CTIME) -AC_REPLACE_FUNCS(ctime_r) -AC_REPLACE_FUNCS(strsep) - -AC_ARG_ENABLE(allsymbols, AS_HELP_STRING([--enable-allsymbols],[export all symbols from libunbound and link binaries to it, smaller install size but libunbound export table is polluted by internal symbols])) -case "$enable_allsymbols" in - yes) - COMMON_OBJ_ALL_SYMBOLS="" - UBSYMS="" - EXTRALINK="libunbound.la" - AC_DEFINE(EXPORT_ALL_SYMBOLS, 1, [Define this if you enabled-allsymbols from libunbound to link binaries to it for smaller install size, but the libunbound export table is polluted by internal symbols]) - ;; - no|*) - COMMON_OBJ_ALL_SYMBOLS='$(COMMON_OBJ)' - UBSYMS='-export-symbols $(srcdir)/libunbound/ubsyms.def' - EXTRALINK="" - ;; -esac -AC_SUBST(COMMON_OBJ_ALL_SYMBOLS) -AC_SUBST(EXTRALINK) -AC_SUBST(UBSYMS) -if test x_$enable_lock_checks = x_yes; then - UBSYMS="-export-symbols clubsyms.def" - cp ${srcdir}/libunbound/ubsyms.def clubsyms.def - echo lock_protect >> clubsyms.def - echo lock_unprotect >> clubsyms.def - echo lock_get_mem >> clubsyms.def - echo checklock_start >> clubsyms.def - echo checklock_stop >> clubsyms.def - echo checklock_lock >> clubsyms.def - echo checklock_unlock >> clubsyms.def - echo checklock_init >> clubsyms.def - echo checklock_thrcreate >> clubsyms.def - echo checklock_thrjoin >> clubsyms.def -fi - -# check for dnstap if requested -dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock], - [ - AC_DEFINE([USE_DNSTAP], [1], [Define to 1 to enable dnstap support]) - AC_SUBST([ENABLE_DNSTAP], [1]) - - AC_SUBST([opt_dnstap_socket_path]) - ACX_ESCAPE_BACKSLASH($opt_dnstap_socket_path, hdr_dnstap_socket_path) - AC_DEFINE_UNQUOTED(DNSTAP_SOCKET_PATH, - ["$hdr_dnstap_socket_path"], [default dnstap socket path]) - AC_SUBST(DNSTAP_SOCKET_PATH,["$hdr_dnstap_socket_path"]) - AC_SUBST(DNSTAP_SOCKET_TESTBIN,['unbound-dnstap-socket$(EXEEXT)']) - AC_SUBST([DNSTAP_SRC], ["dnstap/dnstap.c dnstap/dnstap.pb-c.c dnstap/dnstap_fstrm.c dnstap/dtstream.c"]) - AC_SUBST([DNSTAP_OBJ], ["dnstap.lo dnstap.pb-c.lo dnstap_fstrm.lo dtstream.lo"]) - ], - [ - AC_SUBST([ENABLE_DNSTAP], [0]) - ] -) - -# check for dnscrypt if requested -dnsc_DNSCRYPT([ - AC_DEFINE([USE_DNSCRYPT], [1], [Define to 1 to enable dnscrypt support]) - AC_SUBST([ENABLE_DNSCRYPT], [1]) - - AC_SUBST([DNSCRYPT_SRC], ["dnscrypt/dnscrypt.c"]) - AC_SUBST([DNSCRYPT_OBJ], ["dnscrypt.lo"]) - ], - [ - AC_SUBST([ENABLE_DNSCRYPT], [0]) - ] -) - -# check for cachedb if requested -AC_ARG_ENABLE(cachedb, AS_HELP_STRING([--enable-cachedb],[enable cachedb module that can use external cache storage])) -# turn on cachedb when hiredis support is enabled. -if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi -case "$enable_cachedb" in - yes) - AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support]) - AC_SUBST([CACHEDB_SRC], ["cachedb/cachedb.c cachedb/redis.c"]) - AC_SUBST([CACHEDB_OBJ], ["cachedb.lo redis.lo"]) - ;; - no|*) - # nothing - ;; -esac - -# check for ipsecmod if requested -AC_ARG_ENABLE(ipsecmod, AS_HELP_STRING([--enable-ipsecmod],[Enable ipsecmod module that facilitates opportunistic IPsec])) -case "$enable_ipsecmod" in - yes) - AC_DEFINE([USE_IPSECMOD], [1], [Define to 1 to use ipsecmod support.]) - IPSECMOD_OBJ="ipsecmod.lo ipsecmod-whitelist.lo" - AC_SUBST(IPSECMOD_OBJ) - IPSECMOD_HEADER='$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h' - AC_SUBST(IPSECMOD_HEADER) - ;; - no|*) - # nothing - ;; -esac - -# check for ipset if requested -AC_ARG_ENABLE(ipset, AS_HELP_STRING([--enable-ipset],[enable ipset module])) -case "$enable_ipset" in - yes) - AC_DEFINE([USE_IPSET], [1], [Define to 1 to use ipset support]) - IPSET_SRC="ipset/ipset.c" - AC_SUBST(IPSET_SRC) - IPSET_OBJ="ipset.lo" - AC_SUBST(IPSET_OBJ) - - # mnl - AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]), - [ ],[ withval="yes" ]) - found_libmnl="no" - AC_MSG_CHECKING(for libmnl) - if test x_$withval = x_ -o x_$withval = x_yes; then - withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $withval ; do - if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then - found_libmnl="yes" - dnl assume /usr is in default path. - extralibmnl="" - if test -f "$dir/include/libmnl/libmnl/libmnl.h"; then - extralibmnl="/libmnl" - fi - if test "$dir" != "/usr" -o -n "$extralibmnl"; then - CPPFLAGS="$CPPFLAGS -I$dir/include$extralibmnl" - fi - if test "$dir" != "/usr"; then - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - AC_MSG_RESULT(found in $dir) - LIBS="$LIBS -lmnl" - break; - fi - done - if test x_$found_libmnl != x_yes; then - AC_MSG_ERROR([Could not find libmnl, libmnl.h]) - fi - ;; - no|*) - # nothing - ;; -esac -AC_ARG_ENABLE(explicit-port-randomisation, AS_HELP_STRING([--disable-explicit-port-randomisation],[disable explicit source port randomisation and rely on the kernel to provide random source ports])) -case "$enable_explicit_port_randomisation" in - no) - AC_DEFINE([DISABLE_EXPLICIT_PORT_RANDOMISATION], [1], [Define this to enable kernel based UDP source port randomization.]) - ;; - yes|*) - ;; -esac - -if echo "$host" | $GREP -i -e linux >/dev/null; then - AC_ARG_ENABLE(linux-ip-local-port-range, AC_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])) - case "$enable_linux_ip_local_port_range" in - yes) - AC_DEFINE([USE_LINUX_IP_LOCAL_PORT_RANGE], [1], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]) - ;; - no|*) - ;; - esac -fi - - -AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope]) -# on openBSD, the implicit rule make $< work. -# on Solaris, it does not work ($? is changed sources, $^ lists dependencies). -# gmake works. -cat >conftest.make </dev/null -rm -f conftest.make conftest.c conftest.dir/conftest.c -rm -rf conftest.dir -if test ! -f conftest.lo; then - AC_MSG_RESULT(no) - SOURCEDETERMINE='echo "$^" | awk "-F " "{print \$$1;}" > .source' - SOURCEFILE='`cat .source`' -else - AC_MSG_RESULT(yes) - SOURCEDETERMINE=':' - SOURCEFILE='$<' -fi -rm -f conftest.lo -AC_SUBST(SOURCEDETERMINE) -AC_SUBST(SOURCEFILE) - -# see if we want to build the library or everything -ALLTARGET="alltargets" -INSTALLTARGET="install-all" -AC_ARG_WITH(libunbound-only, AS_HELP_STRING([--with-libunbound-only],[do not build daemon and tool programs]), - [ - if test "$withval" = "yes"; then - ALLTARGET="lib" - INSTALLTARGET="install-lib" - fi -]) -if test $ALLTARGET = "alltargets"; then - if test $USE_NSS = "yes"; then - AC_MSG_ERROR([--with-nss can only be used in combination with --with-libunbound-only.]) - fi - if test $USE_NETTLE = "yes"; then - AC_MSG_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.]) - fi -fi - -AC_SUBST(ALLTARGET) -AC_SUBST(INSTALLTARGET) - -ACX_STRIP_EXT_FLAGS -if test -n "$LATE_LDFLAGS"; then - LDFLAGS="$LATE_LDFLAGS $LDFLAGS" -fi -# remove start spaces -LDFLAGS=`echo "$LDFLAGS"|sed -e 's/^ *//'` -LIBS=`echo "$LIBS"|sed -e 's/^ *//'` - -AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [10240], [Define to the maximum message length to pass to syslog.]) - -AH_BOTTOM( -dnl this must be first AH_CONFIG, to define the flags before any includes. -AHX_CONFIG_EXT_FLAGS - -dnl includes -[ -#ifndef _OPENBSD_SOURCE -#define _OPENBSD_SOURCE 1 -#endif - -#ifndef UNBOUND_DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -#endif - -/** Use small-ldns codebase */ -#define USE_SLDNS 1 -#ifdef HAVE_SSL -# define LDNS_BUILD_CONFIG_HAVE_SSL 1 -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -#include -#include -#endif - -#ifdef HAVE_STDARG_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - -#include - -#if HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#ifdef HAVE_NETINET_TCP_H -#include -#endif - -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#ifdef HAVE_WINSOCK2_H -#include -#endif - -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO) -#define ARG_LL "%ll" -#else -#define ARG_LL "%I64" -#endif - -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif -] - -AHX_CONFIG_FORMAT_ATTRIBUTE -AHX_CONFIG_UNUSED_ATTRIBUTE -AHX_CONFIG_FSEEKO -AHX_CONFIG_MAXHOSTNAMELEN -#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) -#define snprintf snprintf_unbound -#define vsnprintf vsnprintf_unbound -#include -int snprintf (char *str, size_t count, const char *fmt, ...); -int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#endif /* HAVE_SNPRINTF or SNPRINTF_RET_BROKEN */ -AHX_CONFIG_INET_PTON(unbound) -AHX_CONFIG_INET_NTOP(unbound) -AHX_CONFIG_INET_ATON(unbound) -AHX_CONFIG_MEMMOVE(unbound) -AHX_CONFIG_STRLCAT(unbound) -AHX_CONFIG_STRLCPY(unbound) -AHX_CONFIG_GMTIME_R(unbound) -AHX_CONFIG_REALLOCARRAY(unbound) -AHX_CONFIG_W32_SLEEP -AHX_CONFIG_W32_USLEEP -AHX_CONFIG_W32_RANDOM -AHX_CONFIG_W32_SRANDOM -AHX_CONFIG_W32_FD_SET_T -AHX_CONFIG_IPV6_MIN_MTU -AHX_MEMCMP_BROKEN(unbound) - -[ -#ifndef HAVE_CTIME_R -#define ctime_r unbound_ctime_r -char *ctime_r(const time_t *timep, char *buf); -#endif - -#ifndef HAVE_STRSEP -#define strsep unbound_strsep -char *strsep(char **stringp, const char *delim); -#endif - -#ifndef HAVE_ISBLANK -#define isblank unbound_isblank -int isblank(int c); -#endif - -#ifndef HAVE_EXPLICIT_BZERO -#define explicit_bzero unbound_explicit_bzero -void explicit_bzero(void* buf, size_t len); -#endif - -#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - -#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON -int inet_pton(int af, const char* src, void* dst); -#endif - -#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) -#define strptime unbound_strptime -struct tm; -char *strptime(const char *s, const char *format, struct tm *tm); -#endif - -#if !HAVE_DECL_REALLOCARRAY -void *reallocarray(void *ptr, size_t nmemb, size_t size); -#endif - -#ifdef HAVE_LIBBSD -#include -#include -#endif - -#ifdef HAVE_LIBRESSL -# if !HAVE_DECL_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz); -# endif -# if !HAVE_DECL_ARC4RANDOM && defined(HAVE_ARC4RANDOM) -uint32_t arc4random(void); -# endif -# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM) -uint32_t arc4random_uniform(uint32_t upper_bound); -# endif -#endif /* HAVE_LIBRESSL */ -#ifndef HAVE_ARC4RANDOM -int getentropy(void* buf, size_t len); -uint32_t arc4random(void); -void arc4random_buf(void* buf, size_t n); -void _ARC4_LOCK(void); -void _ARC4_UNLOCK(void); -void _ARC4_LOCK_DESTROY(void); -#endif -#ifndef HAVE_ARC4RANDOM_UNIFORM -uint32_t arc4random_uniform(uint32_t upper_bound); -#endif -#ifdef COMPAT_SHA512 -#ifndef SHA512_DIGEST_LENGTH -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - uint8_t buffer[SHA512_BLOCK_LENGTH]; -} SHA512_CTX; -#endif /* SHA512_DIGEST_LENGTH */ -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, void*, size_t); -void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); -#endif /* COMPAT_SHA512 */ - - - -#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) - /* using version of libevent that is not threadsafe. */ -# define LIBEVENT_SIGNAL_PROBLEM 1 -#endif - -#ifndef CHECKED_INET6 -# define CHECKED_INET6 -# ifdef AF_INET6 -# define INET6 -# else -# define AF_INET6 28 -# endif -#endif /* CHECKED_INET6 */ - -#ifndef HAVE_GETADDRINFO -struct sockaddr_storage; -#include "compat/fake-rfc2553.h" -#endif - -#ifdef UNBOUND_ALLOC_STATS -# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) -# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) -# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) -# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) -void *unbound_stat_malloc(size_t size); -void *unbound_stat_calloc(size_t nmemb, size_t size); -void unbound_stat_free(void *ptr); -void *unbound_stat_realloc(void *ptr, size_t size); -void *unbound_stat_malloc_log(size_t size, const char* file, int line, - const char* func); -void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, - int line, const char* func); -void unbound_stat_free_log(void *ptr, const char* file, int line, - const char* func); -void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, - int line, const char* func); -#elif defined(UNBOUND_ALLOC_LITE) -# include "util/alloc.h" -#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ - -/** default port for DNS traffic. */ -#define UNBOUND_DNS_PORT 53 -/** default port for DNS over TLS traffic. */ -#define UNBOUND_DNS_OVER_TLS_PORT 853 -/** default port for DNS over HTTPS traffic. */ -#define UNBOUND_DNS_OVER_HTTPS_PORT 443 -/** default port for unbound control traffic, registered port with IANA, - ub-dns-control 8953/tcp unbound dns nameserver control */ -#define UNBOUND_CONTROL_PORT 8953 -/** the version of unbound-control that this software implements */ -#define UNBOUND_CONTROL_VERSION 1 - -]) - -dnl if we build from source tree, the man pages need @date@ and @version@ -dnl if this is a distro tarball, that was already done by makedist.sh -AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO]) -AC_SUBST(date, [`date +'%b %e, %Y'`]) - -AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service]) -AC_CONFIG_HEADERS([config.h]) -AC_OUTPUT diff --git a/crates/libunbound-sys/unbound/daemon/acl_list.c b/crates/libunbound-sys/unbound/daemon/acl_list.c deleted file mode 100644 index 83cfd7dd..00000000 --- a/crates/libunbound-sys/unbound/daemon/acl_list.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * daemon/acl_list.h - client access control storage for the server. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file helps the server keep out queries from outside sources, that - * should not be answered. - */ -#include "config.h" -#include "daemon/acl_list.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "services/localzone.h" -#include "services/listen_dnsport.h" -#include "sldns/str2wire.h" - -struct acl_list* -acl_list_create(void) -{ - struct acl_list* acl = (struct acl_list*)calloc(1, - sizeof(struct acl_list)); - if(!acl) - return NULL; - acl->region = regional_create(); - if(!acl->region) { - acl_list_delete(acl); - return NULL; - } - return acl; -} - -void -acl_list_delete(struct acl_list* acl) -{ - if(!acl) - return; - regional_destroy(acl->region); - free(acl); -} - -/** insert new address into acl_list structure */ -static struct acl_addr* -acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr, - socklen_t addrlen, int net, enum acl_access control, - int complain_duplicates) -{ - struct acl_addr* node = regional_alloc_zero(acl->region, - sizeof(struct acl_addr)); - if(!node) - return NULL; - node->control = control; - if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) { - if(complain_duplicates) - verbose(VERB_QUERY, "duplicate acl address ignored."); - } - return node; -} - -/** parse str to acl_access enum */ -static int -parse_acl_access(const char* str, enum acl_access* control) -{ - if(strcmp(str, "allow") == 0) - *control = acl_allow; - else if(strcmp(str, "deny") == 0) - *control = acl_deny; - else if(strcmp(str, "refuse") == 0) - *control = acl_refuse; - else if(strcmp(str, "deny_non_local") == 0) - *control = acl_deny_non_local; - else if(strcmp(str, "refuse_non_local") == 0) - *control = acl_refuse_non_local; - else if(strcmp(str, "allow_snoop") == 0) - *control = acl_allow_snoop; - else if(strcmp(str, "allow_setrd") == 0) - *control = acl_allow_setrd; - else if (strcmp(str, "allow_cookie") == 0) - *control = acl_allow_cookie; - else { - log_err("access control type %s unknown", str); - return 0; - } - return 1; -} - -/** apply acl_list string */ -static int -acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2, - int complain_duplicates) -{ - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - enum acl_access control; - if(!parse_acl_access(s2, &control)) { - return 0; - } - if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { - log_err("cannot parse access control: %s %s", str, s2); - return 0; - } - if(!acl_list_insert(acl, &addr, addrlen, net, control, - complain_duplicates)) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** find or create node (NULL on parse or error) */ -static struct acl_addr* -acl_find_or_create_str2addr(struct acl_list* acl, const char* str, - int is_interface, int port) -{ - struct acl_addr* node; - struct sockaddr_storage addr; - socklen_t addrlen; - int net = (str_is_ip6(str)?128:32); - if(is_interface) { - if(!extstrtoaddr(str, &addr, &addrlen, port)) { - log_err("cannot parse interface: %s", str); - return NULL; - } - } else { - if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { - log_err("cannot parse netblock: %s", str); - return NULL; - } - } - /* find or create node */ - if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr, - addrlen, net)) && !is_interface) { - /* create node, type 'allow' since otherwise tags are - * pointless, can override with specific access-control: cfg */ - if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr, - addrlen, net, acl_allow, 1))) { - log_err("out of memory"); - return NULL; - } - } - return node; -} - -/** find or create node (NULL on error) */ -static struct acl_addr* -acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr, - socklen_t addrlen, enum acl_access control) -{ - struct acl_addr* node; - int net = (addr_is_ip6(addr, addrlen)?128:32); - /* find or create node */ - if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr, - addrlen, net))) { - /* create node; - * can override with specific access-control: cfg */ - if(!(node=(struct acl_addr*)acl_list_insert(acl, addr, - addrlen, net, control, 1))) { - log_err("out of memory"); - return NULL; - } - } - return node; -} - -/** apply acl_interface string */ -static int -acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface, - const char* s2, int port) -{ - struct acl_addr* node; - enum acl_access control; - if(!parse_acl_access(s2, &control)) { - return 0; - } - if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) { - log_err("cannot update ACL on non-configured interface: %s %d", - iface, port); - return 0; - } - node->control = control; - return 1; -} - -struct acl_addr* -acl_interface_insert(struct acl_list* acl_interface, - struct sockaddr_storage* addr, socklen_t addrlen, - enum acl_access control) -{ - return acl_find_or_create(acl_interface, addr, addrlen, control); -} - -/** apply acl_tag string */ -static int -acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap, - size_t bitmaplen, int is_interface, int port) -{ - struct acl_addr* node; - if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { - if(is_interface) - log_err("non-configured interface: %s", str); - return 0; - } - node->taglen = bitmaplen; - node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen); - if(!node->taglist) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** apply acl_view string */ -static int -acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2, - struct views* vs, int is_interface, int port) -{ - struct acl_addr* node; - if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { - if(is_interface) - log_err("non-configured interface: %s", str); - return 0; - } - node->view = views_find_view(vs, str2, 0 /* get read lock*/); - if(!node->view) { - log_err("no view with name: %s", str2); - return 0; - } - lock_rw_unlock(&node->view->lock); - return 1; -} - -/** apply acl_tag_action string */ -static int -acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg, - const char* str, const char* tag, const char* action, - int is_interface, int port) -{ - struct acl_addr* node; - int tagid; - enum localzone_type t; - if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { - if(is_interface) - log_err("non-configured interface: %s", str); - return 0; - } - /* allocate array if not yet */ - if(!node->tag_actions) { - node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region, - sizeof(*node->tag_actions)*cfg->num_tags); - if(!node->tag_actions) { - log_err("out of memory"); - return 0; - } - node->tag_actions_size = (size_t)cfg->num_tags; - } - /* parse tag */ - if((tagid=find_tag_id(cfg, tag)) == -1) { - log_err("cannot parse tag (define-tag it): %s %s", str, tag); - return 0; - } - if((size_t)tagid >= node->tag_actions_size) { - log_err("tagid too large for array %s %s", str, tag); - return 0; - } - if(!local_zone_str2type(action, &t)) { - log_err("cannot parse access control action type: %s %s %s", - str, tag, action); - return 0; - } - node->tag_actions[tagid] = (uint8_t)t; - return 1; -} - -/** check wire data parse */ -static int -check_data(const char* data, const struct config_strlist* head) -{ - char buf[65536]; - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t len = sizeof(rr); - int res; - /* '.' is sufficient for validation, and it makes the call to - * sldns_wirerr_get_type() simpler below. */ - snprintf(buf, sizeof(buf), "%s %s", ".", data); - res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0, - NULL, 0); - - /* Reject it if we would end up having CNAME and other data (including - * another CNAME) for the same tag. */ - if(res == 0 && head) { - const char* err_data = NULL; - - if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) { - /* adding CNAME while other data already exists. */ - err_data = data; - } else { - snprintf(buf, sizeof(buf), "%s %s", ".", head->str); - len = sizeof(rr); - res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, - NULL, 0, NULL, 0); - if(res != 0) { - /* This should be impossible here as head->str - * has been validated, but we check it just in - * case. */ - return 0; - } - if(sldns_wirerr_get_type(rr, len, 1) == - LDNS_RR_TYPE_CNAME) /* already have CNAME */ - err_data = head->str; - } - if(err_data) { - log_err("redirect tag data '%s' must not coexist with " - "other data.", err_data); - return 0; - } - } - if(res == 0) - return 1; - log_err("rr data [char %d] parse error %s", - (int)LDNS_WIREPARSE_OFFSET(res)-2, - sldns_get_errorstr_parse(res)); - return 0; -} - -/** apply acl_tag_data string */ -static int -acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg, - const char* str, const char* tag, const char* data, - int is_interface, int port) -{ - struct acl_addr* node; - int tagid; - char* dupdata; - if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { - if(is_interface) - log_err("non-configured interface: %s", str); - return 0; - } - /* allocate array if not yet */ - if(!node->tag_datas) { - node->tag_datas = (struct config_strlist**)regional_alloc_zero( - acl->region, sizeof(*node->tag_datas)*cfg->num_tags); - if(!node->tag_datas) { - log_err("out of memory"); - return 0; - } - node->tag_datas_size = (size_t)cfg->num_tags; - } - /* parse tag */ - if((tagid=find_tag_id(cfg, tag)) == -1) { - log_err("cannot parse tag (define-tag it): %s %s", str, tag); - return 0; - } - if((size_t)tagid >= node->tag_datas_size) { - log_err("tagid too large for array %s %s", str, tag); - return 0; - } - - /* check data? */ - if(!check_data(data, node->tag_datas[tagid])) { - log_err("cannot parse access-control-tag data: %s %s '%s'", - str, tag, data); - return 0; - } - - dupdata = regional_strdup(acl->region, data); - if(!dupdata) { - log_err("out of memory"); - return 0; - } - if(!cfg_region_strlist_insert(acl->region, - &(node->tag_datas[tagid]), dupdata)) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** read acl_list config */ -static int -read_acl_list(struct acl_list* acl, struct config_str2list* acls) -{ - struct config_str2list* p; - for(p = acls; p; p = p->next) { - log_assert(p->str && p->str2); - if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) - return 0; - } - return 1; -} - -/** read acl view config */ -static int -read_acl_view(struct acl_list* acl, struct config_str2list** acl_view, - struct views* v) -{ - struct config_str2list* np, *p = *acl_view; - *acl_view = NULL; - while(p) { - log_assert(p->str && p->str2); - if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) { - config_deldblstrlist(p); - return 0; - } - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p); - p = np; - } - return 1; -} - -/** read acl tags config */ -static int -read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags) -{ - struct config_strbytelist* np, *p = *acl_tags; - *acl_tags = NULL; - while(p) { - log_assert(p->str && p->str2); - if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) { - config_del_strbytelist(p); - return 0; - } - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p); - p = np; - } - return 1; -} - -/** read acl tag actions config */ -static int -read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg, - struct config_str3list** acl_tag_actions) -{ - struct config_str3list* p, *np; - p = *acl_tag_actions; - *acl_tag_actions = NULL; - while(p) { - log_assert(p->str && p->str2 && p->str3); - if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2, - p->str3, 0, 0)) { - config_deltrplstrlist(p); - return 0; - } - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p->str3); - free(p); - p = np; - } - return 1; -} - -/** read acl tag datas config */ -static int -read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg, - struct config_str3list** acl_tag_datas) -{ - struct config_str3list* p, *np; - p = *acl_tag_datas; - *acl_tag_datas = NULL; - while(p) { - log_assert(p->str && p->str2 && p->str3); - if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3, - 0, 0)) { - config_deltrplstrlist(p); - return 0; - } - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p->str3); - free(p); - p = np; - } - return 1; -} - -int -acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, - struct views* v) -{ - regional_free_all(acl->region); - addr_tree_init(&acl->tree); - if(!read_acl_list(acl, cfg->acls)) - return 0; - if(!read_acl_view(acl, &cfg->acl_view, v)) - return 0; - if(!read_acl_tags(acl, &cfg->acl_tags)) - return 0; - if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions)) - return 0; - if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas)) - return 0; - /* insert defaults, with '0' to ignore them if they are duplicates */ - /* the 'refuse' defaults for /0 are now done per interface instead */ - if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) - return 0; - if(cfg->do_ip6) { - if(!acl_list_str_cfg(acl, "::1", "allow", 0)) - return 0; - if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) - return 0; - } - addr_tree_init_parents(&acl->tree); - return 1; -} - -int -acl_interface_compare(const void* k1, const void* k2) -{ - struct addr_tree_node* n1 = (struct addr_tree_node*)k1; - struct addr_tree_node* n2 = (struct addr_tree_node*)k2; - return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, - n2->addrlen); - /* We don't care about comparing node->net. All addresses in the - * acl_interface tree have either 32 (ipv4) or 128 (ipv6). */ -} - -void -acl_interface_init(struct acl_list* acl_interface) -{ - regional_free_all(acl_interface->region); - /* We want comparison in the tree to include only address and port. - * We don't care about comparing node->net. All addresses in the - * acl_interface->tree should have either 32 (ipv4) or 128 (ipv6). - * Initialise with the appropriate compare function but keep treating - * it as an addr_tree. */ - addr_tree_addrport_init(&acl_interface->tree); -} - -static int -read_acl_interface_action(struct acl_list* acl_interface, - struct config_str2list* acls, int port) -{ - struct config_str2list* p; - for(p = acls; p; p = p->next) { - char** resif = NULL; - int num_resif = 0; - int i; - log_assert(p->str && p->str2); - if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) - return 0; - for(i = 0; istr2, port)){ - config_del_strarray(resif, num_resif); - return 0; - } - } - config_del_strarray(resif, num_resif); - } - return 1; -} - -/** read acl view config for interface */ -static int -read_acl_interface_view(struct acl_list* acl_interface, - struct config_str2list** acl_view, - struct views* v, int port) -{ - struct config_str2list* np, *p = *acl_view; - *acl_view = NULL; - while(p) { - char** resif = NULL; - int num_resif = 0; - int i; - log_assert(p->str && p->str2); - if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { - config_deldblstrlist(p); - return 0; - } - for(i = 0; istr2, - v, 1, port)) { - config_del_strarray(resif, num_resif); - config_deldblstrlist(p); - return 0; - } - } - config_del_strarray(resif, num_resif); - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p); - p = np; - } - return 1; -} - -/** read acl tags config for interface */ -static int -read_acl_interface_tags(struct acl_list* acl_interface, - struct config_strbytelist** acl_tags, int port) -{ - struct config_strbytelist* np, *p = *acl_tags; - *acl_tags = NULL; - while(p) { - char** resif = NULL; - int num_resif = 0; - int i; - log_assert(p->str && p->str2); - if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { - config_del_strbytelist(p); - return 0; - } - for(i = 0; istr2, - p->str2len, 1, port)) { - config_del_strbytelist(p); - config_del_strarray(resif, num_resif); - return 0; - } - } - config_del_strarray(resif, num_resif); - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p); - p = np; - } - return 1; -} - -/** read acl tag actions config for interface*/ -static int -read_acl_interface_tag_actions(struct acl_list* acl_interface, - struct config_file* cfg, - struct config_str3list** acl_tag_actions, int port) -{ - struct config_str3list* p, *np; - p = *acl_tag_actions; - *acl_tag_actions = NULL; - while(p) { - char** resif = NULL; - int num_resif = 0; - int i; - log_assert(p->str && p->str2 && p->str3); - if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { - config_deltrplstrlist(p); - return 0; - } - for(i = 0; istr2, p->str3, 1, port)) { - config_deltrplstrlist(p); - config_del_strarray(resif, num_resif); - return 0; - } - } - config_del_strarray(resif, num_resif); - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p->str3); - free(p); - p = np; - } - return 1; -} - -/** read acl tag datas config for interface */ -static int -read_acl_interface_tag_datas(struct acl_list* acl_interface, - struct config_file* cfg, - struct config_str3list** acl_tag_datas, int port) -{ - struct config_str3list* p, *np; - p = *acl_tag_datas; - *acl_tag_datas = NULL; - while(p) { - char** resif = NULL; - int num_resif = 0; - int i; - log_assert(p->str && p->str2 && p->str3); - if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { - config_deltrplstrlist(p); - return 0; - } - for(i = 0; istr2, p->str3, 1, port)) { - config_deltrplstrlist(p); - config_del_strarray(resif, num_resif); - return 0; - } - } - config_del_strarray(resif, num_resif); - /* free the items as we go to free up memory */ - np = p->next; - free(p->str); - free(p->str2); - free(p->str3); - free(p); - p = np; - } - return 1; -} - -int -acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg, - struct views* v) -{ - if(!read_acl_interface_action(acl_interface, cfg->interface_actions, - cfg->port)) - return 0; - if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v, - cfg->port)) - return 0; - if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags, - cfg->port)) - return 0; - if(!read_acl_interface_tag_actions(acl_interface, cfg, - &cfg->interface_tag_actions, cfg->port)) - return 0; - if(!read_acl_interface_tag_datas(acl_interface, cfg, - &cfg->interface_tag_datas, cfg->port)) - return 0; - addr_tree_init_parents(&acl_interface->tree); - return 1; -} - -enum acl_access -acl_get_control(struct acl_addr* acl) -{ - if(acl) return acl->control; - return acl_deny; -} - -struct acl_addr* -acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - return (struct acl_addr*)addr_tree_lookup(&acl->tree, - addr, addrlen); -} - -size_t -acl_list_get_mem(struct acl_list* acl) -{ - if(!acl) return 0; - return sizeof(*acl) + regional_get_mem(acl->region); -} - -const char* acl_access_to_str(enum acl_access acl) -{ - switch(acl) { - case acl_deny: return "deny"; - case acl_refuse: return "refuse"; - case acl_deny_non_local: return "deny_non_local"; - case acl_refuse_non_local: return "refuse_non_local"; - case acl_allow: return "allow"; - case acl_allow_snoop: return "allow_snoop"; - case acl_allow_setrd: return "allow_setrd"; - default: break; - } - return "unknown"; -} - -void -log_acl_action(const char* action, struct sockaddr_storage* addr, - socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr) -{ - char a[128], n[128]; - uint16_t port; - addr_to_str(addr, addrlen, a, sizeof(a)); - port = ntohs(((struct sockaddr_in*)addr)->sin_port); - if(acladdr) { - addr_to_str(&acladdr->node.addr, acladdr->node.addrlen, - n, sizeof(n)); - verbose(VERB_ALGO, "%s query from %s port %d because of " - "%s/%d %s", action, a, (int)port, n, acladdr->node.net, - acl_access_to_str(acl)); - } else { - verbose(VERB_ALGO, "%s query from %s port %d", action, a, - (int)port); - } -} diff --git a/crates/libunbound-sys/unbound/daemon/acl_list.h b/crates/libunbound-sys/unbound/daemon/acl_list.h deleted file mode 100644 index 9da43bef..00000000 --- a/crates/libunbound-sys/unbound/daemon/acl_list.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * daemon/acl_list.h - client access control storage for the server. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file keeps track of the list of clients that are allowed to - * access the server. - */ - -#ifndef DAEMON_ACL_LIST_H -#define DAEMON_ACL_LIST_H -#include "util/storage/dnstree.h" -#include "services/view.h" -struct config_file; -struct regional; - -/** - * Enumeration of access control options for an address range. - * Allow or deny access. - */ -enum acl_access { - /** disallow any access whatsoever, drop it */ - acl_deny = 0, - /** disallow access, send a polite 'REFUSED' reply */ - acl_refuse, - /** disallow any access to zones that aren't local, drop it */ - acl_deny_non_local, - /** disallow access to zones that aren't local, 'REFUSED' reply */ - acl_refuse_non_local, - /** allow full access for recursion (+RD) queries */ - acl_allow, - /** allow full access for all queries, recursion and cache snooping */ - acl_allow_snoop, - /** allow full access for recursion queries and set RD flag regardless - * of request */ - acl_allow_setrd, - /** allow full access for recursion (+RD) queries if valid cookie - * present or stateful transport */ - acl_allow_cookie -}; - -/** - * Access control storage structure - */ -struct acl_list { - /** regional for allocation */ - struct regional* region; - /** - * Tree of the addresses that are allowed/blocked. - * contents of type acl_addr. - */ - rbtree_type tree; -}; - -/** - * - * An address span with access control information - */ -struct acl_addr { - /** node in address tree */ - struct addr_tree_node node; - /** access control on this netblock */ - enum acl_access control; - /** tag bitlist */ - uint8_t* taglist; - /** length of the taglist (in bytes) */ - size_t taglen; - /** array per tagnumber of localzonetype(in one byte). NULL if none. */ - uint8_t* tag_actions; - /** size of the tag_actions_array */ - size_t tag_actions_size; - /** array per tagnumber, with per tag a list of rdata strings. - * NULL if none. strings are like 'A 127.0.0.1' 'AAAA ::1' */ - struct config_strlist** tag_datas; - /** size of the tag_datas array */ - size_t tag_datas_size; - /* view element, NULL if none */ - struct view* view; -}; - -/** - * Create acl structure - * @return new structure or NULL on error. - */ -struct acl_list* acl_list_create(void); - -/** - * Delete acl structure. - * @param acl: to delete. - */ -void acl_list_delete(struct acl_list* acl); - -/** - * Insert interface in the acl_list. This should happen when the listening - * interface is setup. - * @param acl_interface: acl_list to insert to. - * @param addr: interface IP. - * @param addrlen: length of the interface IP. - * @param control: acl_access. - * @return new structure or NULL on error. - */ -struct acl_addr* -acl_interface_insert(struct acl_list* acl_interface, - struct sockaddr_storage* addr, socklen_t addrlen, - enum acl_access control); - -/** - * Process access control config. - * @param acl: where to store. - * @param cfg: config options. - * @param v: views structure - * @return 0 on error. - */ -int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, - struct views* v); - -/** compare ACL interface "addr_tree" nodes (+port) */ -int acl_interface_compare(const void* k1, const void* k2); - -/** - * Initialise (also clean) the acl_interface struct. - * @param acl_interface: where to store. - */ -void acl_interface_init(struct acl_list* acl_interface); - -/** - * Process interface control config. - * @param acl_interface: where to store. - * @param cfg: config options. - * @param v: views structure - * @return 0 on error. - */ -int acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg, - struct views* v); - -/** - * Lookup access control status for acl structure. - * @param acl: structure for acl storage. - * @return: what to do with message from this address. - */ -enum acl_access acl_get_control(struct acl_addr* acl); - -/** - * Lookup address to see its acl structure - * @param acl: structure for address storage. - * @param addr: address to check - * @param addrlen: length of addr. - * @return: acl structure from this address. - */ -struct acl_addr* -acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, - socklen_t addrlen); - -/** - * Get memory used by acl structure. - * @param acl: structure for address storage. - * @return bytes in use. - */ -size_t acl_list_get_mem(struct acl_list* acl); - -/* - * Get string for acl access specification - * @param acl: access type value - * @return string - */ -const char* acl_access_to_str(enum acl_access acl); - -/* log acl and addr for action */ -void log_acl_action(const char* action, struct sockaddr_storage* addr, - socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr); - -#endif /* DAEMON_ACL_LIST_H */ diff --git a/crates/libunbound-sys/unbound/daemon/cachedump.c b/crates/libunbound-sys/unbound/daemon/cachedump.c deleted file mode 100644 index 61ee1d29..00000000 --- a/crates/libunbound-sys/unbound/daemon/cachedump.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - * daemon/cachedump.c - dump the cache to text format. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to read and write the cache(s) - * to text format. - */ -#include "config.h" -#include -#include "daemon/cachedump.h" -#include "daemon/remote.h" -#include "daemon/worker.h" -#include "services/cache/rrset.h" -#include "services/cache/dns.h" -#include "services/cache/infra.h" -#include "services/outside_network.h" -#include "util/data/msgreply.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "util/config_file.h" -#include "iterator/iterator.h" -#include "iterator/iter_delegpt.h" -#include "iterator/iter_utils.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_hints.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" - -/** dump one rrset zonefile line */ -static int -dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i) -{ - char s[65535]; - if(!packed_rr_to_string(k, i, now, s, sizeof(s))) { - return ssl_printf(ssl, "BADRR\n"); - } - return ssl_printf(ssl, "%s", s); -} - -/** dump rrset key and data info */ -static int -dump_rrset(RES* ssl, struct ub_packed_rrset_key* k, - struct packed_rrset_data* d, time_t now) -{ - size_t i; - /* rd lock held by caller */ - if(!k || !d) return 1; - if(k->id == 0) return 1; /* deleted */ - if(d->ttl < now) return 1; /* expired */ - - /* meta line */ - if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n", - (k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"", - (long long)(d->ttl - now), - (unsigned)d->count, (unsigned)d->rrsig_count, - (int)d->trust, (int)d->security - )) - return 0; - for(i=0; icount + d->rrsig_count; i++) { - if(!dump_rrset_line(ssl, k, now, i)) - return 0; - } - return 1; -} - -/** dump lruhash rrset cache */ -static int -dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now) -{ - struct lruhash_entry* e; - /* lruhash already locked by caller */ - /* walk in order of lru; best first */ - for(e=h->lru_start; e; e = e->lru_next) { - lock_rw_rdlock(&e->lock); - if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key, - (struct packed_rrset_data*)e->data, now)) { - lock_rw_unlock(&e->lock); - return 0; - } - lock_rw_unlock(&e->lock); - } - return 1; -} - -/** dump rrset cache */ -static int -dump_rrset_cache(RES* ssl, struct worker* worker) -{ - struct rrset_cache* r = worker->env.rrset_cache; - size_t slab; - if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0; - for(slab=0; slabtable.size; slab++) { - lock_quick_lock(&r->table.array[slab]->lock); - if(!dump_rrset_lruhash(ssl, r->table.array[slab], - *worker->env.now)) { - lock_quick_unlock(&r->table.array[slab]->lock); - return 0; - } - lock_quick_unlock(&r->table.array[slab]->lock); - } - return ssl_printf(ssl, "END_RRSET_CACHE\n"); -} - -/** dump message to rrset reference */ -static int -dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k) -{ - char* nm, *tp, *cl; - nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len); - tp = sldns_wire2str_type(ntohs(k->rk.type)); - cl = sldns_wire2str_class(ntohs(k->rk.rrset_class)); - if(!nm || !cl || !tp) { - free(nm); - free(tp); - free(cl); - return ssl_printf(ssl, "BADREF\n"); - } - if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) { - free(nm); - free(tp); - free(cl); - return 0; - } - free(nm); - free(tp); - free(cl); - - return 1; -} - -/** dump message entry */ -static int -dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now) -{ - size_t i; - char* nm, *tp, *cl; - if(!k || !d) return 1; - if(d->ttl < now) return 1; /* expired */ - - nm = sldns_wire2str_dname(k->qname, k->qname_len); - tp = sldns_wire2str_type(k->qtype); - cl = sldns_wire2str_class(k->qclass); - if(!nm || !tp || !cl) { - free(nm); - free(tp); - free(cl); - return 1; /* skip this entry */ - } - if(!rrset_array_lock(d->ref, d->rrset_count, now)) { - /* rrsets have timed out or do not exist */ - free(nm); - free(tp); - free(cl); - return 1; /* skip this entry */ - } - - /* meta line */ - if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n", - nm, cl, tp, - (int)d->flags, (int)d->qdcount, - (long long)(d->ttl-now), (int)d->security, - (unsigned)d->an_numrrsets, - (unsigned)d->ns_numrrsets, - (unsigned)d->ar_numrrsets, - (int)d->reason_bogus, - d->reason_bogus_str?d->reason_bogus_str:"")) { - free(nm); - free(tp); - free(cl); - rrset_array_unlock(d->ref, d->rrset_count); - return 0; - } - free(nm); - free(tp); - free(cl); - - for(i=0; irrset_count; i++) { - if(!dump_msg_ref(ssl, d->rrsets[i])) { - rrset_array_unlock(d->ref, d->rrset_count); - return 0; - } - } - rrset_array_unlock(d->ref, d->rrset_count); - - return 1; -} - -/** copy msg to worker pad */ -static int -copy_msg(struct regional* region, struct lruhash_entry* e, - struct query_info** k, struct reply_info** d) -{ - struct reply_info* rep = (struct reply_info*)e->data; - if(rep->rrset_count > RR_COUNT_MAX) - return 0; /* to protect against integer overflow */ - *d = (struct reply_info*)regional_alloc_init(region, e->data, - sizeof(struct reply_info) + - sizeof(struct rrset_ref) * (rep->rrset_count-1) + - sizeof(struct ub_packed_rrset_key*) * rep->rrset_count); - if(!*d) - return 0; - (*d)->rrsets = (struct ub_packed_rrset_key**)(void *)( - (uint8_t*)(&((*d)->ref[0])) + - sizeof(struct rrset_ref) * rep->rrset_count); - *k = (struct query_info*)regional_alloc_init(region, - e->key, sizeof(struct query_info)); - if(!*k) - return 0; - (*k)->qname = regional_alloc_init(region, - (*k)->qname, (*k)->qname_len); - return (*k)->qname != NULL; -} - -/** dump lruhash msg cache */ -static int -dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h) -{ - struct lruhash_entry* e; - struct query_info* k; - struct reply_info* d; - - /* lruhash already locked by caller */ - /* walk in order of lru; best first */ - for(e=h->lru_start; e; e = e->lru_next) { - regional_free_all(worker->scratchpad); - lock_rw_rdlock(&e->lock); - /* make copy of rrset in worker buffer */ - if(!copy_msg(worker->scratchpad, e, &k, &d)) { - lock_rw_unlock(&e->lock); - return 0; - } - lock_rw_unlock(&e->lock); - /* release lock so we can lookup the rrset references - * in the rrset cache */ - if(!dump_msg(ssl, k, d, *worker->env.now)) { - return 0; - } - } - return 1; -} - -/** dump msg cache */ -static int -dump_msg_cache(RES* ssl, struct worker* worker) -{ - struct slabhash* sh = worker->env.msg_cache; - size_t slab; - if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0; - for(slab=0; slabsize; slab++) { - lock_quick_lock(&sh->array[slab]->lock); - if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) { - lock_quick_unlock(&sh->array[slab]->lock); - return 0; - } - lock_quick_unlock(&sh->array[slab]->lock); - } - return ssl_printf(ssl, "END_MSG_CACHE\n"); -} - -int -dump_cache(RES* ssl, struct worker* worker) -{ - if(!dump_rrset_cache(ssl, worker)) - return 0; - if(!dump_msg_cache(ssl, worker)) - return 0; - return ssl_printf(ssl, "EOF\n"); -} - -/** read a line from ssl into buffer */ -static int -ssl_read_buf(RES* ssl, sldns_buffer* buf) -{ - return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf), - sldns_buffer_capacity(buf)); -} - -/** check fixed text on line */ -static int -read_fixed(RES* ssl, sldns_buffer* buf, const char* str) -{ - if(!ssl_read_buf(ssl, buf)) return 0; - return (strcmp((char*)sldns_buffer_begin(buf), str) == 0); -} - -/** load an RR into rrset */ -static int -load_rr(RES* ssl, sldns_buffer* buf, struct regional* region, - struct ub_packed_rrset_key* rk, struct packed_rrset_data* d, - unsigned int i, int is_rrsig, int* go_on, time_t now) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t rr_len = sizeof(rr), dname_len = 0; - int status; - - /* read the line */ - if(!ssl_read_buf(ssl, buf)) - return 0; - if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) { - *go_on = 0; - return 1; - } - status = sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr, - &rr_len, &dname_len, 3600, NULL, 0, NULL, 0); - if(status != 0) { - log_warn("error cannot parse rr: %s: %s", - sldns_get_errorstr_parse(status), - (char*)sldns_buffer_begin(buf)); - return 0; - } - if(is_rrsig && sldns_wirerr_get_type(rr, rr_len, dname_len) - != LDNS_RR_TYPE_RRSIG) { - log_warn("error expected rrsig but got %s", - (char*)sldns_buffer_begin(buf)); - return 0; - } - - /* convert ldns rr into packed_rr */ - d->rr_ttl[i] = (time_t)sldns_wirerr_get_ttl(rr, rr_len, dname_len) + now; - sldns_buffer_clear(buf); - d->rr_len[i] = sldns_wirerr_get_rdatalen(rr, rr_len, dname_len)+2; - d->rr_data[i] = (uint8_t*)regional_alloc_init(region, - sldns_wirerr_get_rdatawl(rr, rr_len, dname_len), d->rr_len[i]); - if(!d->rr_data[i]) { - log_warn("error out of memory"); - return 0; - } - - /* if first entry, fill the key structure */ - if(i==0) { - rk->rk.type = htons(sldns_wirerr_get_type(rr, rr_len, dname_len)); - rk->rk.rrset_class = htons(sldns_wirerr_get_class(rr, rr_len, dname_len)); - rk->rk.dname_len = dname_len; - rk->rk.dname = regional_alloc_init(region, rr, dname_len); - if(!rk->rk.dname) { - log_warn("error out of memory"); - return 0; - } - } - - return 1; -} - -/** move entry into cache */ -static int -move_into_cache(struct ub_packed_rrset_key* k, - struct packed_rrset_data* d, struct worker* worker) -{ - struct ub_packed_rrset_key* ak; - struct packed_rrset_data* ad; - size_t s, i, num = d->count + d->rrsig_count; - struct rrset_ref ref; - uint8_t* p; - - ak = alloc_special_obtain(worker->alloc); - if(!ak) { - log_warn("error out of memory"); - return 0; - } - ak->entry.data = NULL; - ak->rk = k->rk; - ak->entry.hash = rrset_key_hash(&k->rk); - ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len); - if(!ak->rk.dname) { - log_warn("error out of memory"); - ub_packed_rrset_parsedelete(ak, worker->alloc); - return 0; - } - s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) + - sizeof(time_t))* num; - for(i=0; irr_len[i]; - ad = (struct packed_rrset_data*)malloc(s); - if(!ad) { - log_warn("error out of memory"); - ub_packed_rrset_parsedelete(ak, worker->alloc); - return 0; - } - p = (uint8_t*)ad; - memmove(p, d, sizeof(*ad)); - p += sizeof(*ad); - memmove(p, &d->rr_len[0], sizeof(size_t)*num); - p += sizeof(size_t)*num; - memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num); - p += sizeof(uint8_t*)*num; - memmove(p, &d->rr_ttl[0], sizeof(time_t)*num); - p += sizeof(time_t)*num; - for(i=0; irr_data[i], d->rr_len[i]); - p += d->rr_len[i]; - } - packed_rrset_ptr_fixup(ad); - - ak->entry.data = ad; - - ref.key = ak; - ref.id = ak->id; - (void)rrset_cache_update(worker->env.rrset_cache, &ref, - worker->alloc, *worker->env.now); - - return 1; -} - -/** load an rrset entry */ -static int -load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker) -{ - char* s = (char*)sldns_buffer_begin(buf); - struct regional* region = worker->scratchpad; - struct ub_packed_rrset_key* rk; - struct packed_rrset_data* d; - unsigned int rr_count, rrsig_count, trust, security; - long long ttl; - unsigned int i; - int go_on = 1; - regional_free_all(region); - - rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region, - sizeof(*rk)); - d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d)); - if(!rk || !d) { - log_warn("error out of memory"); - return 0; - } - - if(strncmp(s, ";rrset", 6) != 0) { - log_warn("error expected ';rrset' but got %s", s); - return 0; - } - s += 6; - if(strncmp(s, " nsec_apex", 10) == 0) { - s += 10; - rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX; - } - if(sscanf(s, " " ARG_LL "d %u %u %u %u", &ttl, &rr_count, &rrsig_count, - &trust, &security) != 5) { - log_warn("error bad rrset spec %s", s); - return 0; - } - if(rr_count == 0 && rrsig_count == 0) { - log_warn("bad rrset without contents"); - return 0; - } - if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) { - log_warn("bad rrset with too many rrs"); - return 0; - } - d->count = (size_t)rr_count; - d->rrsig_count = (size_t)rrsig_count; - d->security = (enum sec_status)security; - d->trust = (enum rrset_trust)trust; - d->ttl = (time_t)ttl + *worker->env.now; - - d->rr_len = regional_alloc_zero(region, - sizeof(size_t)*(d->count+d->rrsig_count)); - d->rr_ttl = regional_alloc_zero(region, - sizeof(time_t)*(d->count+d->rrsig_count)); - d->rr_data = regional_alloc_zero(region, - sizeof(uint8_t*)*(d->count+d->rrsig_count)); - if(!d->rr_len || !d->rr_ttl || !d->rr_data) { - log_warn("error out of memory"); - return 0; - } - - /* read the rr's themselves */ - for(i=0; ienv.now)) { - log_warn("could not read rr %u", i); - return 0; - } - } - for(i=0; ienv.now)) { - log_warn("could not read rrsig %u", i); - return 0; - } - } - if(!go_on) { - /* skip this entry */ - return 1; - } - - return move_into_cache(rk, d, worker); -} - -/** load rrset cache */ -static int -load_rrset_cache(RES* ssl, struct worker* worker) -{ - sldns_buffer* buf = worker->env.scratch_buffer; - if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0; - while(ssl_read_buf(ssl, buf) && - strcmp((char*)sldns_buffer_begin(buf), "END_RRSET_CACHE")!=0) { - if(!load_rrset(ssl, buf, worker)) - return 0; - } - return 1; -} - -/** read qinfo from next three words */ -static char* -load_qinfo(char* str, struct query_info* qinfo, struct regional* region) -{ - /* s is part of the buf */ - char* s = str; - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t rr_len = sizeof(rr), dname_len = 0; - int status; - - /* skip three words */ - s = strchr(str, ' '); - if(s) s = strchr(s+1, ' '); - if(s) s = strchr(s+1, ' '); - if(!s) { - log_warn("error line too short, %s", str); - return NULL; - } - s[0] = 0; - s++; - - /* parse them */ - status = sldns_str2wire_rr_question_buf(str, rr, &rr_len, &dname_len, - NULL, 0, NULL, 0); - if(status != 0) { - log_warn("error cannot parse: %s %s", - sldns_get_errorstr_parse(status), str); - return NULL; - } - qinfo->qtype = sldns_wirerr_get_type(rr, rr_len, dname_len); - qinfo->qclass = sldns_wirerr_get_class(rr, rr_len, dname_len); - qinfo->qname_len = dname_len; - qinfo->qname = (uint8_t*)regional_alloc_init(region, rr, dname_len); - qinfo->local_alias = NULL; - if(!qinfo->qname) { - log_warn("error out of memory"); - return NULL; - } - - return s; -} - -/** load a msg rrset reference */ -static int -load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker, - struct regional *region, struct ub_packed_rrset_key** rrset, - int* go_on) -{ - char* s = (char*)sldns_buffer_begin(buf); - struct query_info qinfo; - unsigned int flags; - struct ub_packed_rrset_key* k; - - /* read line */ - if(!ssl_read_buf(ssl, buf)) - return 0; - if(strncmp(s, "BADREF", 6) == 0) { - *go_on = 0; /* its bad, skip it and skip message */ - return 1; - } - - s = load_qinfo(s, &qinfo, region); - if(!s) { - return 0; - } - if(sscanf(s, " %u", &flags) != 1) { - log_warn("error cannot parse flags: %s", s); - return 0; - } - - /* lookup in cache */ - k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname, - qinfo.qname_len, qinfo.qtype, qinfo.qclass, - (uint32_t)flags, *worker->env.now, 0); - if(!k) { - /* not found or expired */ - *go_on = 0; - return 1; - } - - /* store in result */ - *rrset = packed_rrset_copy_region(k, region, *worker->env.now); - lock_rw_unlock(&k->entry.lock); - - return (*rrset != NULL); -} - -/** load a msg entry */ -static int -load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker) -{ - struct regional* region = worker->scratchpad; - struct query_info qinf; - struct reply_info rep; - char* s = (char*)sldns_buffer_begin(buf); - unsigned int flags, qdcount, security, an, ns, ar; - long long ttl; - size_t i; - int go_on = 1; - int ede; - int consumed = 0; - char* ede_str = NULL; - - regional_free_all(region); - - if(strncmp(s, "msg ", 4) != 0) { - log_warn("error expected msg but got %s", s); - return 0; - } - s += 4; - s = load_qinfo(s, &qinf, region); - if(!s) { - return 0; - } - - /* read remainder of line */ - /* note the last space before any possible EDE text */ - if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl, - &security, &an, &ns, &ar, &ede, &consumed) != 8) { - log_warn("error cannot parse numbers: %s", s); - return 0; - } - /* there may be EDE text after the numbers */ - if(consumed > 0 && (size_t)consumed < strlen(s)) - ede_str = s + consumed; - memset(&rep, 0, sizeof(rep)); - rep.flags = (uint16_t)flags; - rep.qdcount = (uint16_t)qdcount; - rep.ttl = (time_t)ttl; - rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl); - rep.serve_expired_ttl = rep.ttl + SERVE_EXPIRED_TTL; - rep.security = (enum sec_status)security; - if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) { - log_warn("error too many rrsets"); - return 0; /* protect against integer overflow in alloc */ - } - rep.an_numrrsets = (size_t)an; - rep.ns_numrrsets = (size_t)ns; - rep.ar_numrrsets = (size_t)ar; - rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar; - rep.reason_bogus = (sldns_ede_code)ede; - rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL; - rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero( - region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count); - - /* fill repinfo with references */ - for(i=0; ienv, &qinf, &rep, 0, 0, 0, NULL, flags, - *worker->env.now)) { - log_warn("error out of memory"); - return 0; - } - return 1; -} - -/** load msg cache */ -static int -load_msg_cache(RES* ssl, struct worker* worker) -{ - sldns_buffer* buf = worker->env.scratch_buffer; - if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0; - while(ssl_read_buf(ssl, buf) && - strcmp((char*)sldns_buffer_begin(buf), "END_MSG_CACHE")!=0) { - if(!load_msg(ssl, buf, worker)) - return 0; - } - return 1; -} - -int -load_cache(RES* ssl, struct worker* worker) -{ - if(!load_rrset_cache(ssl, worker)) - return 0; - if(!load_msg_cache(ssl, worker)) - return 0; - return read_fixed(ssl, worker->env.scratch_buffer, "EOF"); -} - -/** print details on a delegation point */ -static void -print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp) -{ - char buf[257]; - struct delegpt_addr* a; - int lame, dlame, rlame, rto, edns_vs, to, delay, - tA = 0, tAAAA = 0, tother = 0; - long long entry_ttl; - struct rtt_info ri; - uint8_t edns_lame_known; - for(a = dp->target_list; a; a = a->next_target) { - addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); - if(!ssl_printf(ssl, "%-16s\t", buf)) - return; - if(a->bogus) { - if(!ssl_printf(ssl, "Address is BOGUS. ")) - return; - } - /* lookup in infra cache */ - delay=0; - entry_ttl = infra_get_host_rto(worker->env.infra_cache, - &a->addr, a->addrlen, dp->name, dp->namelen, - &ri, &delay, *worker->env.now, &tA, &tAAAA, &tother); - if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) { - if(!ssl_printf(ssl, "expired, rto %d msec, tA %d " - "tAAAA %d tother %d.\n", ri.rto, tA, tAAAA, - tother)) - return; - continue; - } - if(entry_ttl == -1 || entry_ttl == -2) { - if(!ssl_printf(ssl, "not in infra cache.\n")) - return; - continue; /* skip stuff not in infra cache */ - } - - /* uses type_A because most often looked up, but other - * lameness won't be reported then */ - if(!infra_get_lame_rtt(worker->env.infra_cache, - &a->addr, a->addrlen, dp->name, dp->namelen, - LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto, - *worker->env.now)) { - if(!ssl_printf(ssl, "not in infra cache.\n")) - return; - continue; /* skip stuff not in infra cache */ - } - if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl " ARG_LL "d, " - "ping %d var %d rtt %d, tA %d, tAAAA %d, tother %d", - lame?"LAME ":"", dlame?"NoDNSSEC ":"", - a->lame?"AddrWasParentSide ":"", - rlame?"NoAuthButRecursive ":"", rto, entry_ttl, - ri.srtt, ri.rttvar, rtt_notimeout(&ri), - tA, tAAAA, tother)) - return; - if(delay) - if(!ssl_printf(ssl, ", probedelay %d", delay)) - return; - if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen, - dp->name, dp->namelen, *worker->env.now, &edns_vs, - &edns_lame_known, &to)) { - if(edns_vs == -1) { - if(!ssl_printf(ssl, ", noEDNS%s.", - edns_lame_known?" probed":" assumed")) - return; - } else { - if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs, - edns_lame_known?" probed":" assumed")) - return; - } - } - if(!ssl_printf(ssl, "\n")) - return; - } -} - -/** print main dp info */ -static void -print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg) -{ - size_t i, n_ns, n_miss, n_addr, n_res, n_avail; - - /* print the dp */ - if(msg) - for(i=0; irep->rrset_count; i++) { - struct ub_packed_rrset_key* k = msg->rep->rrsets[i]; - struct packed_rrset_data* d = - (struct packed_rrset_data*)k->entry.data; - if(d->security == sec_status_bogus) { - if(!ssl_printf(ssl, "Address is BOGUS:\n")) - return; - } - if(!dump_rrset(ssl, k, d, 0)) - return; - } - delegpt_count_ns(dp, &n_ns, &n_miss); - delegpt_count_addr(dp, &n_addr, &n_res, &n_avail); - /* since dp has not been used by iterator, all are available*/ - if(!ssl_printf(ssl, "Delegation with %d names, of which %d " - "can be examined to query further addresses.\n" - "%sIt provides %d IP addresses.\n", - (int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""), - (int)n_addr)) - return; -} - -int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm, - size_t nmlen, int ATTR_UNUSED(nmlabs)) -{ - /* deep links into the iterator module */ - struct delegpt* dp; - struct dns_msg* msg; - struct regional* region = worker->scratchpad; - char b[260]; - struct query_info qinfo; - struct iter_hints_stub* stub; - regional_free_all(region); - qinfo.qname = nm; - qinfo.qname_len = nmlen; - qinfo.qtype = LDNS_RR_TYPE_A; - qinfo.qclass = LDNS_RR_CLASS_IN; - qinfo.local_alias = NULL; - - dname_str(nm, b); - if(!ssl_printf(ssl, "The following name servers are used for lookup " - "of %s\n", b)) - return 0; - - dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass); - if(dp) { - if(!ssl_printf(ssl, "forwarding request:\n")) - return 0; - print_dp_main(ssl, dp, NULL); - print_dp_details(ssl, worker, dp); - return 1; - } - - while(1) { - dp = dns_cache_find_delegation(&worker->env, nm, nmlen, - qinfo.qtype, qinfo.qclass, region, &msg, - *worker->env.now, 0, NULL, 0); - if(!dp) { - return ssl_printf(ssl, "no delegation from " - "cache; goes to configured roots\n"); - } - /* go up? */ - if(iter_dp_is_useless(&qinfo, BIT_RD, dp, - (worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0), - (worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0), - worker->env.cfg->do_nat64)) { - print_dp_main(ssl, dp, msg); - print_dp_details(ssl, worker, dp); - if(!ssl_printf(ssl, "cache delegation was " - "useless (no IP addresses)\n")) - return 0; - if(dname_is_root(nm)) { - /* goes to root config */ - return ssl_printf(ssl, "no delegation from " - "cache; goes to configured roots\n"); - } else { - /* useless, goes up */ - nm = dp->name; - nmlen = dp->namelen; - dname_remove_label(&nm, &nmlen); - dname_str(nm, b); - if(!ssl_printf(ssl, "going up, lookup %s\n", b)) - return 0; - continue; - } - } - stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass, - dp); - if(stub) { - if(stub->noprime) { - if(!ssl_printf(ssl, "The noprime stub servers " - "are used:\n")) - return 0; - } else { - if(!ssl_printf(ssl, "The stub is primed " - "with servers:\n")) - return 0; - } - print_dp_main(ssl, stub->dp, NULL); - print_dp_details(ssl, worker, stub->dp); - } else { - print_dp_main(ssl, dp, msg); - print_dp_details(ssl, worker, dp); - } - break; - } - - return 1; -} diff --git a/crates/libunbound-sys/unbound/daemon/cachedump.h b/crates/libunbound-sys/unbound/daemon/cachedump.h deleted file mode 100644 index 72c172d4..00000000 --- a/crates/libunbound-sys/unbound/daemon/cachedump.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * daemon/cachedump.h - dump the cache to text format. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to read and write the cache(s) - * to text format. - * - * The format of the file is as follows: - * [RRset cache] - * [Message cache] - * EOF -- fixed string "EOF" before end of the file. - * - * The RRset cache is: - * START_RRSET_CACHE - * [rrset]* - * END_RRSET_CACHE - * - * rrset is: - * ;rrset [nsec_apex] TTL rr_count rrsig_count trust security - * resource records, one per line, in zonefile format - * rrsig records, one per line, in zonefile format - * If the text conversion fails, BADRR is printed on the line. - * - * The Message cache is: - * START_MSG_CACHE - * [msg]* - * END_MSG_CACHE - * - * msg is: - * msg name class type flags qdcount ttl security an ns ar - * list of rrset references, one per line. If conversion fails, BADREF - * reference is: - * name class type flags - * - * Expired cache entries are not printed. - */ - -#ifndef DAEMON_DUMPCACHE_H -#define DAEMON_DUMPCACHE_H -struct worker; -#include "daemon/remote.h" - -/** - * Dump cache(s) to text - * @param ssl: to print to - * @param worker: worker that is available (buffers, etc) and has - * ptrs to the caches. - * @return false on ssl print error. - */ -int dump_cache(RES* ssl, struct worker* worker); - -/** - * Load cache(s) from text - * @param ssl: to read from - * @param worker: worker that is available (buffers, etc) and has - * ptrs to the caches. - * @return false on ssl error. - */ -int load_cache(RES* ssl, struct worker* worker); - -/** - * Print the delegation used to lookup for this name. - * @param ssl: to read from - * @param worker: worker that is available (buffers, etc) and has - * ptrs to the caches. - * @param nm: name to lookup - * @param nmlen: length of name. - * @param nmlabs: labels in name. - * @return false on ssl error. - */ -int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm, - size_t nmlen, int nmlabs); - -#endif /* DAEMON_DUMPCACHE_H */ diff --git a/crates/libunbound-sys/unbound/daemon/daemon.c b/crates/libunbound-sys/unbound/daemon/daemon.c deleted file mode 100644 index 193608d4..00000000 --- a/crates/libunbound-sys/unbound/daemon/daemon.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * daemon/daemon.c - collection of workers that handles requests. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * The daemon consists of global settings and a number of workers. - */ - -#include "config.h" -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif -#include - -#ifdef HAVE_NSS -/* nss3 */ -#include "nss.h" -#endif - -#include "daemon/daemon.h" -#include "daemon/worker.h" -#include "daemon/remote.h" -#include "daemon/acl_list.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/data/msgreply.h" -#include "util/shm_side/shm_main.h" -#include "util/storage/lookup3.h" -#include "util/storage/slabhash.h" -#include "util/tcp_conn_limit.h" -#include "util/edns.h" -#include "services/listen_dnsport.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "services/localzone.h" -#include "services/view.h" -#include "services/modstack.h" -#include "services/authzone.h" -#include "util/module.h" -#include "util/random.h" -#include "util/tube.h" -#include "util/net_help.h" -#include "sldns/keyraw.h" -#include "respip/respip.h" -#include - -#ifdef HAVE_SYSTEMD -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif - -/** How many quit requests happened. */ -static int sig_record_quit = 0; -/** How many reload requests happened. */ -static int sig_record_reload = 0; - -#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS -/** cleaner ssl memory freeup */ -static void* comp_meth = NULL; -#endif -/** remove buffers for parsing and init */ -int ub_c_lex_destroy(void); - -/** used when no other sighandling happens, so we don't die - * when multiple signals in quick succession are sent to us. - * @param sig: signal number. - * @return signal handler return type (void or int). - */ -static RETSIGTYPE record_sigh(int sig) -{ -#ifdef LIBEVENT_SIGNAL_PROBLEM - /* cannot log, verbose here because locks may be held */ - /* quit on signal, no cleanup and statistics, - because installed libevent version is not threadsafe */ - exit(0); -#endif - switch(sig) - { - case SIGTERM: -#ifdef SIGQUIT - case SIGQUIT: -#endif -#ifdef SIGBREAK - case SIGBREAK: -#endif - case SIGINT: - sig_record_quit++; - break; -#ifdef SIGHUP - case SIGHUP: - sig_record_reload++; - break; -#endif -#ifdef SIGPIPE - case SIGPIPE: - break; -#endif - default: - /* ignoring signal */ - break; - } -} - -/** - * Signal handling during the time when netevent is disabled. - * Stores signals to replay later. - */ -static void -signal_handling_record(void) -{ - if( signal(SIGTERM, record_sigh) == SIG_ERR || -#ifdef SIGQUIT - signal(SIGQUIT, record_sigh) == SIG_ERR || -#endif -#ifdef SIGBREAK - signal(SIGBREAK, record_sigh) == SIG_ERR || -#endif -#ifdef SIGHUP - signal(SIGHUP, record_sigh) == SIG_ERR || -#endif -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN) == SIG_ERR || -#endif - signal(SIGINT, record_sigh) == SIG_ERR - ) - log_err("install sighandler: %s", strerror(errno)); -} - -/** - * Replay old signals. - * @param wrk: worker that handles signals. - */ -static void -signal_handling_playback(struct worker* wrk) -{ -#ifdef SIGHUP - if(sig_record_reload) - worker_sighandler(SIGHUP, wrk); -#endif - if(sig_record_quit) - worker_sighandler(SIGTERM, wrk); - sig_record_quit = 0; - sig_record_reload = 0; -} - -struct daemon* -daemon_init(void) -{ - struct daemon* daemon = (struct daemon*)calloc(1, - sizeof(struct daemon)); -#ifdef USE_WINSOCK - int r; - WSADATA wsa_data; -#endif - if(!daemon) - return NULL; -#ifdef USE_WINSOCK - r = WSAStartup(MAKEWORD(2,2), &wsa_data); - if(r != 0) { - fatal_exit("could not init winsock. WSAStartup: %s", - wsa_strerror(r)); - } -#endif /* USE_WINSOCK */ - signal_handling_record(); -#ifdef HAVE_SSL -# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS - ERR_load_crypto_strings(); -# endif -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) - ERR_load_SSL_strings(); -#endif -# ifdef USE_GOST - (void)sldns_key_EVP_load_gost_id(); -# endif -# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) -# ifndef S_SPLINT_S - OpenSSL_add_all_algorithms(); -# endif -# else - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS - | OPENSSL_INIT_ADD_ALL_DIGESTS - | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); -# endif -# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS - /* grab the COMP method ptr because openssl leaks it */ - comp_meth = (void*)SSL_COMP_get_compression_methods(); -# endif -# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) - (void)SSL_library_init(); -# else - (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); -# endif -# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) - if(!ub_openssl_lock_init()) - fatal_exit("could not init openssl locks"); -# endif -#elif defined(HAVE_NSS) - if(NSS_NoDB_Init(NULL) != SECSuccess) - fatal_exit("could not init NSS"); -#endif /* HAVE_SSL or HAVE_NSS */ -#ifdef HAVE_TZSET - /* init timezone info while we are not chrooted yet */ - tzset(); -#endif - daemon->need_to_exit = 0; - modstack_init(&daemon->mods); - if(!(daemon->env = (struct module_env*)calloc(1, - sizeof(*daemon->env)))) { - free(daemon); - return NULL; - } - /* init edns_known_options */ - if(!edns_known_options_init(daemon->env)) { - free(daemon->env); - free(daemon); - return NULL; - } - alloc_init(&daemon->superalloc, NULL, 0); - daemon->acl = acl_list_create(); - if(!daemon->acl) { - edns_known_options_delete(daemon->env); - free(daemon->env); - free(daemon); - return NULL; - } - daemon->acl_interface = acl_list_create(); - if(!daemon->acl_interface) { - acl_list_delete(daemon->acl); - edns_known_options_delete(daemon->env); - free(daemon->env); - free(daemon); - return NULL; - } - daemon->tcl = tcl_list_create(); - if(!daemon->tcl) { - acl_list_delete(daemon->acl_interface); - acl_list_delete(daemon->acl); - edns_known_options_delete(daemon->env); - free(daemon->env); - free(daemon); - return NULL; - } - listen_setup_locks(); - if(gettimeofday(&daemon->time_boot, NULL) < 0) - log_err("gettimeofday: %s", strerror(errno)); - daemon->time_last_stat = daemon->time_boot; - if((daemon->env->auth_zones = auth_zones_create()) == 0) { - acl_list_delete(daemon->acl_interface); - acl_list_delete(daemon->acl); - tcl_list_delete(daemon->tcl); - edns_known_options_delete(daemon->env); - free(daemon->env); - free(daemon); - return NULL; - } - if(!(daemon->env->edns_strings = edns_strings_create())) { - auth_zones_delete(daemon->env->auth_zones); - acl_list_delete(daemon->acl_interface); - acl_list_delete(daemon->acl); - tcl_list_delete(daemon->tcl); - edns_known_options_delete(daemon->env); - free(daemon->env); - free(daemon); - return NULL; - } - return daemon; -} - -static int setup_acl_for_ports(struct acl_list* list, - struct listen_port* port_list) -{ - struct acl_addr* acl_node; - struct addrinfo* addr; - for(; port_list; port_list=port_list->next) { - if(!port_list->socket) { - /* This is mainly for testbound where port_list is - * empty. */ - continue; - } - addr = port_list->socket->addr; - if(!(acl_node = acl_interface_insert(list, - (struct sockaddr_storage*)addr->ai_addr, - (socklen_t)addr->ai_addrlen, - acl_refuse))) { - return 0; - } - port_list->socket->acl = acl_node; - } - return 1; -} - -int -daemon_open_shared_ports(struct daemon* daemon) -{ - log_assert(daemon); - if(daemon->cfg->port != daemon->listening_port) { - char** resif = NULL; - int num_resif = 0; - size_t i; - struct listen_port* p0; - daemon->reuseport = 0; - /* free and close old ports */ - if(daemon->ports != NULL) { - for(i=0; inum_ports; i++) - listening_ports_free(daemon->ports[i]); - free(daemon->ports); - daemon->ports = NULL; - } - /* clean acl_interface */ - acl_interface_init(daemon->acl_interface); - if(!resolve_interface_names(daemon->cfg->ifs, - daemon->cfg->num_ifs, NULL, &resif, &num_resif)) - return 0; - /* see if we want to reuseport */ -#ifdef SO_REUSEPORT - if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0) - daemon->reuseport = 1; -#endif - /* try to use reuseport */ - p0 = listening_ports_open(daemon->cfg, resif, num_resif, - &daemon->reuseport); - if(!p0) { - listening_ports_free(p0); - config_del_strarray(resif, num_resif); - return 0; - } - if(daemon->reuseport) { - /* reuseport was successful, allocate for it */ - daemon->num_ports = (size_t)daemon->cfg->num_threads; - } else { - /* do the normal, singleportslist thing, - * reuseport not enabled or did not work */ - daemon->num_ports = 1; - } - if(!(daemon->ports = (struct listen_port**)calloc( - daemon->num_ports, sizeof(*daemon->ports)))) { - listening_ports_free(p0); - config_del_strarray(resif, num_resif); - return 0; - } - daemon->ports[0] = p0; - if(!setup_acl_for_ports(daemon->acl_interface, - daemon->ports[0])) { - listening_ports_free(p0); - config_del_strarray(resif, num_resif); - return 0; - } - if(daemon->reuseport) { - /* continue to use reuseport */ - for(i=1; inum_ports; i++) { - if(!(daemon->ports[i]= - listening_ports_open(daemon->cfg, - resif, num_resif, - &daemon->reuseport)) - || !daemon->reuseport ) { - for(i=0; inum_ports; i++) - listening_ports_free(daemon->ports[i]); - free(daemon->ports); - daemon->ports = NULL; - config_del_strarray(resif, num_resif); - return 0; - } - if(!setup_acl_for_ports(daemon->acl_interface, - daemon->ports[i])) { - for(i=0; inum_ports; i++) - listening_ports_free(daemon->ports[i]); - free(daemon->ports); - daemon->ports = NULL; - config_del_strarray(resif, num_resif); - return 0; - } - } - } - config_del_strarray(resif, num_resif); - daemon->listening_port = daemon->cfg->port; - } - if(!daemon->cfg->remote_control_enable && daemon->rc_port) { - listening_ports_free(daemon->rc_ports); - daemon->rc_ports = NULL; - daemon->rc_port = 0; - } - if(daemon->cfg->remote_control_enable && - daemon->cfg->control_port != daemon->rc_port) { - listening_ports_free(daemon->rc_ports); - if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg))) - return 0; - daemon->rc_port = daemon->cfg->control_port; - } - return 1; -} - -/** - * Setup modules. setup module stack. - * @param daemon: the daemon - */ -static void daemon_setup_modules(struct daemon* daemon) -{ - daemon->env->cfg = daemon->cfg; - daemon->env->alloc = &daemon->superalloc; - daemon->env->worker = NULL; - daemon->env->need_to_validate = 0; /* set by module init below */ - if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, - daemon->env)) { - fatal_exit("failed to setup modules"); - } - log_edns_known_options(VERB_ALGO, daemon->env); -} - -/** - * Obtain allowed port numbers, concatenate the list, and shuffle them - * (ready to be handed out to threads). - * @param daemon: the daemon. Uses rand and cfg. - * @param shufport: the portlist output. - * @return number of ports available. - */ -static int daemon_get_shufport(struct daemon* daemon, int* shufport) -{ - int i, n, k, temp; - int avail = 0; - for(i=0; i<65536; i++) { - if(daemon->cfg->outgoing_avail_ports[i]) { - shufport[avail++] = daemon->cfg-> - outgoing_avail_ports[i]; - } - } - if(avail == 0) - fatal_exit("no ports are permitted for UDP, add " - "with outgoing-port-permit"); - /* Knuth shuffle */ - n = avail; - while(--n > 0) { - k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */ - temp = shufport[k]; - shufport[k] = shufport[n]; - shufport[n] = temp; - } - return avail; -} - -/** - * Clear and delete per-worker alloc caches, and free memory maintained in - * superalloc. - * The rrset and message caches must be empty at the time of call. - * @param daemon: the daemon that maintains the alloc caches to be cleared. - */ -static void -daemon_clear_allocs(struct daemon* daemon) -{ - int i; - - for(i=0; inum; i++) { - alloc_clear(daemon->worker_allocs[i]); - free(daemon->worker_allocs[i]); - } - free(daemon->worker_allocs); - daemon->worker_allocs = NULL; - - alloc_clear_special(&daemon->superalloc); -} - -/** - * Allocate empty worker structures. With backptr and thread-number, - * from 0..numthread initialised. Used as user arguments to new threads. - * Creates the daemon random generator if it does not exist yet. - * The random generator stays existing between reloads with a unique state. - * @param daemon: the daemon with (new) config settings. - */ -static void -daemon_create_workers(struct daemon* daemon) -{ - int i, numport; - int* shufport; - log_assert(daemon && daemon->cfg); - if(!daemon->rand) { - daemon->rand = ub_initstate(NULL); - if(!daemon->rand) - fatal_exit("could not init random generator"); - hash_set_raninit((uint32_t)ub_random(daemon->rand)); - } - shufport = (int*)calloc(65536, sizeof(int)); - if(!shufport) - fatal_exit("out of memory during daemon init"); - numport = daemon_get_shufport(daemon, shufport); - verbose(VERB_ALGO, "total of %d outgoing ports available", numport); - - daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); - if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) { - log_warn("cannot reduce num-threads to %d because so-reuseport " - "so continuing with %d threads.", (int)daemon->num, - (int)daemon->num_ports); - daemon->num = (int)daemon->num_ports; - } - daemon->workers = (struct worker**)calloc((size_t)daemon->num, - sizeof(struct worker*)); - if(!daemon->workers) - fatal_exit("out of memory during daemon init"); - if(daemon->cfg->dnstap) { -#ifdef USE_DNSTAP - daemon->dtenv = dt_create(daemon->cfg); - if (!daemon->dtenv) - fatal_exit("dt_create failed"); -#else - fatal_exit("dnstap enabled in config but not built with dnstap support"); -#endif - } - for(i=0; inum; i++) { - if(!(daemon->workers[i] = worker_create(daemon, i, - shufport+numport*i/daemon->num, - numport*(i+1)/daemon->num - numport*i/daemon->num))) - /* the above is not ports/numthr, due to rounding */ - fatal_exit("could not create worker"); - } - /* create per-worker alloc caches if not reusing existing ones. */ - if(!daemon->worker_allocs) { - daemon->worker_allocs = (struct alloc_cache**)calloc( - (size_t)daemon->num, sizeof(struct alloc_cache*)); - if(!daemon->worker_allocs) - fatal_exit("could not allocate worker allocs"); - for(i=0; inum; i++) { - struct alloc_cache* alloc = calloc(1, - sizeof(struct alloc_cache)); - if (!alloc) - fatal_exit("could not allocate worker alloc"); - alloc_init(alloc, &daemon->superalloc, i); - daemon->worker_allocs[i] = alloc; - } - } - free(shufport); -} - -#ifdef THREADS_DISABLED -/** - * Close all pipes except for the numbered thread. - * @param daemon: daemon to close pipes in. - * @param thr: thread number 0..num-1 of thread to skip. - */ -static void close_other_pipes(struct daemon* daemon, int thr) -{ - int i; - for(i=0; inum; i++) - if(i!=thr) { - if(i==0) { - /* only close read part, need to write stats */ - tube_close_read(daemon->workers[i]->cmd); - } else { - /* complete close channel to others */ - tube_delete(daemon->workers[i]->cmd); - daemon->workers[i]->cmd = NULL; - } - } -} -#endif /* THREADS_DISABLED */ - -/** - * Function to start one thread. - * @param arg: user argument. - * @return: void* user return value could be used for thread_join results. - */ -static void* -thread_start(void* arg) -{ - struct worker* worker = (struct worker*)arg; - int port_num = 0; - log_thread_set(&worker->thread_num); - ub_thread_blocksigs(); -#ifdef THREADS_DISABLED - /* close pipe ends used by main */ - tube_close_write(worker->cmd); - close_other_pipes(worker->daemon, worker->thread_num); -#endif -#ifdef SO_REUSEPORT - if(worker->daemon->cfg->so_reuseport) - port_num = worker->thread_num % worker->daemon->num_ports; - else - port_num = 0; -#endif - if(!worker_init(worker, worker->daemon->cfg, - worker->daemon->ports[port_num], 0)) - fatal_exit("Could not initialize thread"); - - worker_work(worker); - return NULL; -} - -/** - * Fork and init the other threads. Main thread returns for special handling. - * @param daemon: the daemon with other threads to fork. - */ -static void -daemon_start_others(struct daemon* daemon) -{ - int i; - log_assert(daemon); - verbose(VERB_ALGO, "start threads"); - /* skip i=0, is this thread */ - for(i=1; inum; i++) { - ub_thread_create(&daemon->workers[i]->thr_id, - thread_start, daemon->workers[i]); -#ifdef THREADS_DISABLED - /* close pipe end of child */ - tube_close_read(daemon->workers[i]->cmd); -#endif /* no threads */ - } -} - -/** - * Stop the other threads. - * @param daemon: the daemon with other threads. - */ -static void -daemon_stop_others(struct daemon* daemon) -{ - int i; - log_assert(daemon); - verbose(VERB_ALGO, "stop threads"); - /* skip i=0, is this thread */ - /* use i=0 buffer for sending cmds; because we are #0 */ - for(i=1; inum; i++) { - worker_send_cmd(daemon->workers[i], worker_cmd_quit); - } - /* wait for them to quit */ - for(i=1; inum; i++) { - /* join it to make sure its dead */ - verbose(VERB_ALGO, "join %d", i); - ub_thread_join(daemon->workers[i]->thr_id); - verbose(VERB_ALGO, "join success %d", i); - } -} - -void -daemon_fork(struct daemon* daemon) -{ - int have_view_respip_cfg = 0; -#ifdef HAVE_SYSTEMD - int ret; -#endif - - log_assert(daemon); - if(!(daemon->views = views_create())) - fatal_exit("Could not create views: out of memory"); - /* create individual views and their localzone/data trees */ - if(!views_apply_cfg(daemon->views, daemon->cfg)) - fatal_exit("Could not set up views"); - - if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views)) - fatal_exit("Could not setup access control list"); - if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg, - daemon->views)) - fatal_exit("Could not setup interface control list"); - if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg)) - fatal_exit("Could not setup TCP connection limits"); - if(daemon->cfg->dnscrypt) { -#ifdef USE_DNSCRYPT - daemon->dnscenv = dnsc_create(); - if (!daemon->dnscenv) - fatal_exit("dnsc_create failed"); - dnsc_apply_cfg(daemon->dnscenv, daemon->cfg); -#else - fatal_exit("dnscrypt enabled in config but unbound was not built with " - "dnscrypt support"); -#endif - } - /* create global local_zones */ - if(!(daemon->local_zones = local_zones_create())) - fatal_exit("Could not create local zones: out of memory"); - if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) - fatal_exit("Could not set up local zones"); - - /* process raw response-ip configuration data */ - if(!(daemon->respip_set = respip_set_create())) - fatal_exit("Could not create response IP set"); - if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg)) - fatal_exit("Could not set up response IP set"); - if(!respip_views_apply_cfg(daemon->views, daemon->cfg, - &have_view_respip_cfg)) - fatal_exit("Could not set up per-view response IP sets"); - daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) || - have_view_respip_cfg; - - /* setup modules */ - daemon_setup_modules(daemon); - - /* read auth zonefiles */ - if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1, - &daemon->use_rpz, daemon->env, &daemon->mods)) - fatal_exit("auth_zones could not be setup"); - - /* Set-up EDNS strings */ - if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg)) - fatal_exit("Could not set up EDNS strings"); - - /* response-ip-xxx options don't work as expected without the respip - * module. To avoid run-time operational surprise we reject such - * configuration. */ - if(daemon->use_response_ip && - modstack_find(&daemon->mods, "respip") < 0) - fatal_exit("response-ip options require respip module"); - /* RPZ response ip triggers don't work as expected without the respip - * module. To avoid run-time operational surprise we reject such - * configuration. */ - if(daemon->use_rpz && - modstack_find(&daemon->mods, "respip") < 0) - fatal_exit("RPZ requires the respip module"); - - /* first create all the worker structures, so we can pass - * them to the newly created threads. - */ - daemon_create_workers(daemon); - -#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) - /* in libev the first inited base gets signals */ - if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) - fatal_exit("Could not initialize main thread"); -#endif - - /* Now create the threads and init the workers. - * By the way, this is thread #0 (the main thread). - */ - daemon_start_others(daemon); - - /* Special handling for the main thread. This is the thread - * that handles signals and remote control. - */ -#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) - /* libevent has the last inited base get signals (or any base) */ - if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) - fatal_exit("Could not initialize main thread"); -#endif - signal_handling_playback(daemon->workers[0]); - - if (!shm_main_init(daemon)) - log_warn("SHM has failed"); - - /* Start resolver service on main thread. */ -#ifdef HAVE_SYSTEMD - ret = sd_notify(0, "READY=1"); - if(ret <= 0 && getenv("NOTIFY_SOCKET")) - fatal_exit("sd_notify failed %s: %s. Make sure that unbound has " - "access/permission to use the socket presented by systemd.", - getenv("NOTIFY_SOCKET"), - (ret==0?"no $NOTIFY_SOCKET": strerror(-ret))); -#endif - log_info("start of service (%s).", PACKAGE_STRING); - worker_work(daemon->workers[0]); -#ifdef HAVE_SYSTEMD - if (daemon->workers[0]->need_to_exit) - sd_notify(0, "STOPPING=1"); - else - sd_notify(0, "RELOADING=1"); -#endif - log_info("service stopped (%s).", PACKAGE_STRING); - - /* we exited! a signal happened! Stop other threads */ - daemon_stop_others(daemon); - - /* Shutdown SHM */ - shm_main_shutdown(daemon); - - daemon->reuse_cache = daemon->workers[0]->reuse_cache; - daemon->need_to_exit = daemon->workers[0]->need_to_exit; -} - -void -daemon_cleanup(struct daemon* daemon) -{ - int i; - log_assert(daemon); - /* before stopping main worker, handle signals ourselves, so we - don't die on multiple reload signals for example. */ - signal_handling_record(); - log_thread_set(NULL); - /* clean up caches because - * a) RRset IDs will be recycled after a reload, causing collisions - * b) validation config can change, thus rrset, msg, keycache clear - * - * If we are trying to keep the cache as long as possible, we should - * defer the cleanup until we know whether the new configuration allows - * the reuse. (If we're exiting, cleanup should be done here). */ - if(!daemon->reuse_cache || daemon->need_to_exit) { - slabhash_clear(&daemon->env->rrset_cache->table); - slabhash_clear(daemon->env->msg_cache); - } - daemon->old_num = daemon->num; /* save the current num */ - local_zones_delete(daemon->local_zones); - daemon->local_zones = NULL; - respip_set_delete(daemon->respip_set); - daemon->respip_set = NULL; - views_delete(daemon->views); - daemon->views = NULL; - if(daemon->env->auth_zones) - auth_zones_cleanup(daemon->env->auth_zones); - /* key cache is cleared by module desetup during next daemon_fork() */ - daemon_remote_clear(daemon->rc); - for(i=0; inum; i++) - worker_delete(daemon->workers[i]); - free(daemon->workers); - daemon->workers = NULL; - /* Unless we're trying to keep the cache, worker alloc_caches should be - * cleared and freed here. We do this after deleting workers to - * guarantee that the alloc caches are valid throughout the lifetime - * of workers. */ - if(!daemon->reuse_cache || daemon->need_to_exit) - daemon_clear_allocs(daemon); - daemon->num = 0; -#ifdef USE_DNSTAP - dt_delete(daemon->dtenv); - daemon->dtenv = NULL; -#endif -#ifdef USE_DNSCRYPT - dnsc_delete(daemon->dnscenv); - daemon->dnscenv = NULL; -#endif - daemon->cfg = NULL; -} - -void -daemon_delete(struct daemon* daemon) -{ - size_t i; - if(!daemon) - return; - modstack_desetup(&daemon->mods, daemon->env); - daemon_remote_delete(daemon->rc); - for(i = 0; i < daemon->num_ports; i++) - listening_ports_free(daemon->ports[i]); - free(daemon->ports); - listening_ports_free(daemon->rc_ports); - if(daemon->env) { - slabhash_delete(daemon->env->msg_cache); - rrset_cache_delete(daemon->env->rrset_cache); - infra_delete(daemon->env->infra_cache); - edns_known_options_delete(daemon->env); - edns_strings_delete(daemon->env->edns_strings); - auth_zones_delete(daemon->env->auth_zones); - } - ub_randfree(daemon->rand); - alloc_clear(&daemon->superalloc); - acl_list_delete(daemon->acl); - acl_list_delete(daemon->acl_interface); - tcl_list_delete(daemon->tcl); - listen_desetup_locks(); - free(daemon->chroot); - free(daemon->pidfile); - free(daemon->env); -#ifdef HAVE_SSL - listen_sslctx_delete_ticket_keys(); - SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx); - SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx); -#endif - free(daemon); - /* lex cleanup */ - ub_c_lex_destroy(); - /* libcrypto cleanup */ -#ifdef HAVE_SSL -# if defined(USE_GOST) - sldns_key_EVP_unload_gost(); -# endif -# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE -# ifndef S_SPLINT_S -# if OPENSSL_VERSION_NUMBER < 0x10100000 - sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); -# endif -# endif -# endif -# ifdef HAVE_OPENSSL_CONFIG - EVP_cleanup(); -# if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE) && defined(HAVE_ENGINE_CLEANUP) - ENGINE_cleanup(); -# endif - CONF_modules_free(); -# endif -# ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ -# endif -# ifdef HAVE_ERR_FREE_STRINGS - ERR_free_strings(); -# endif -# if OPENSSL_VERSION_NUMBER < 0x10100000 - RAND_cleanup(); -# endif -# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) - ub_openssl_lock_delete(); -# endif -#ifndef HAVE_ARC4RANDOM - _ARC4_LOCK_DESTROY(); -#endif -#elif defined(HAVE_NSS) - NSS_Shutdown(); -#endif /* HAVE_SSL or HAVE_NSS */ - checklock_stop(); -#ifdef USE_WINSOCK - if(WSACleanup() != 0) { - log_err("Could not WSACleanup: %s", - wsa_strerror(WSAGetLastError())); - } -#endif -} - -void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg) -{ - int new_num = cfg->num_threads?cfg->num_threads:1; - - daemon->cfg = cfg; - config_apply(cfg); - - /* If this is a reload and we deferred the decision on whether to - * reuse the alloc, RRset, and message caches, then check to see if - * it's safe to keep the caches: - * - changing the number of threads is obviously incompatible with - * keeping the per-thread alloc caches. It also means we have to - * clear RRset and message caches. (note that 'new_num' may be - * adjusted in daemon_create_workers, but for our purpose we can - * simply compare it with 'old_num'; if they are equal here, - * 'new_num' won't be adjusted to a different value than 'old_num'). - * - changing RRset cache size effectively clears any remaining cache - * entries. We could keep their keys in alloc caches, but it would - * be more consistent with the sense of the change to clear allocs - * and free memory. To do so we also have to clear message cache. - * - only changing message cache size does not necessarily affect - * RRset or alloc cache. But almost all new subsequent queries will - * require recursive resolution anyway, so it doesn't help much to - * just keep RRset and alloc caches. For simplicity we clear/free - * the other two, too. */ - if(daemon->worker_allocs && - (new_num != daemon->old_num || - !slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, - cfg->msg_cache_slabs) || - !slabhash_is_size(&daemon->env->rrset_cache->table, - cfg->rrset_cache_size, cfg->rrset_cache_slabs))) - { - log_warn("cannot reuse caches due to critical config change"); - slabhash_clear(&daemon->env->rrset_cache->table); - slabhash_clear(daemon->env->msg_cache); - daemon_clear_allocs(daemon); - } - - if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, - cfg->msg_cache_slabs)) { - slabhash_delete(daemon->env->msg_cache); - daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, - HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, - msgreply_sizefunc, query_info_compare, - query_entry_delete, reply_info_delete, NULL); - if(!daemon->env->msg_cache) { - fatal_exit("malloc failure updating config settings"); - } - } - if((daemon->env->rrset_cache = rrset_cache_adjust( - daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0) - fatal_exit("malloc failure updating config settings"); - if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache, - cfg))==0) - fatal_exit("malloc failure updating config settings"); -} diff --git a/crates/libunbound-sys/unbound/daemon/daemon.h b/crates/libunbound-sys/unbound/daemon/daemon.h deleted file mode 100644 index 57665446..00000000 --- a/crates/libunbound-sys/unbound/daemon/daemon.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * daemon/daemon.h - collection of workers that handles requests. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * The daemon consists of global settings and a number of workers. - */ - -#ifndef DAEMON_H -#define DAEMON_H - -#include "util/locks.h" -#include "util/alloc.h" -#include "services/modstack.h" -struct config_file; -struct worker; -struct listen_port; -struct slabhash; -struct module_env; -struct rrset_cache; -struct acl_list; -struct local_zones; -struct views; -struct ub_randstate; -struct daemon_remote; -struct respip_set; -struct shm_main_info; - -#include "dnstap/dnstap_config.h" -#ifdef USE_DNSTAP -struct dt_env; -#endif - -#include "dnscrypt/dnscrypt_config.h" -#ifdef USE_DNSCRYPT -struct dnsc_env; -#endif - -/** - * Structure holding worker list. - * Holds globally visible information. - */ -struct daemon { - /** The config settings */ - struct config_file* cfg; - /** the chroot dir in use, NULL if none */ - char* chroot; - /** pidfile that is used */ - char* pidfile; - /** port number that has ports opened. */ - int listening_port; - /** array of listening ports, opened. Listening ports per worker, - * or just one element[0] shared by the worker threads. */ - struct listen_port** ports; - /** size of ports array */ - size_t num_ports; - /** reuseport is enabled if true */ - int reuseport; - /** port number for remote that has ports opened. */ - int rc_port; - /** listening ports for remote control */ - struct listen_port* rc_ports; - /** remote control connections management (for first worker) */ - struct daemon_remote* rc; - /** ssl context for listening to dnstcp over ssl, and connecting ssl */ - void* listen_sslctx, *connect_sslctx; - /** num threads allocated */ - int num; - /** num threads allocated in the previous config or 0 at first */ - int old_num; - /** the worker entries */ - struct worker** workers; - /** per-worker allocation cache */ - struct alloc_cache **worker_allocs; - /** do we need to exit unbound (or is it only a reload?) */ - int need_to_exit; - /** master random table ; used for port div between threads on reload*/ - struct ub_randstate* rand; - /** master allocation cache */ - struct alloc_cache superalloc; - /** the module environment master value, copied and changed by threads*/ - struct module_env* env; - /** stack of module callbacks */ - struct module_stack mods; - /** access control, which client IPs are allowed to connect */ - struct acl_list* acl; - /** access control, which interfaces are allowed to connect */ - struct acl_list* acl_interface; - /** TCP connection limit, limit connections from client IPs */ - struct tcl_list* tcl; - /** local authority zones */ - struct local_zones* local_zones; - /** last time of statistics printout */ - struct timeval time_last_stat; - /** time when daemon started */ - struct timeval time_boot; - /** views structure containing view tree */ - struct views* views; -#ifdef USE_DNSTAP - /** the dnstap environment master value, copied and changed by threads*/ - struct dt_env* dtenv; -#endif - struct shm_main_info* shm_info; - /** response-ip set with associated actions and tags. */ - struct respip_set* respip_set; - /** some response-ip tags or actions are configured if true */ - int use_response_ip; - /** some RPZ policies are configured */ - int use_rpz; -#ifdef USE_DNSCRYPT - /** the dnscrypt environment */ - struct dnsc_env* dnscenv; -#endif - /** reuse existing cache on reload if other conditions allow it. */ - int reuse_cache; -}; - -/** - * Initialize daemon structure. - * @return: The daemon structure, or NULL on error. - */ -struct daemon* daemon_init(void); - -/** - * Open shared listening ports (if needed). - * The cfg member pointer must have been set for the daemon. - * @param daemon: the daemon. - * @return: false on error. - */ -int daemon_open_shared_ports(struct daemon* daemon); - -/** - * Fork workers and start service. - * When the routine exits, it is no longer forked. - * @param daemon: the daemon. - */ -void daemon_fork(struct daemon* daemon); - -/** - * Close off the worker thread information. - * Bring the daemon back into state ready for daemon_fork again. - * @param daemon: the daemon. - */ -void daemon_cleanup(struct daemon* daemon); - -/** - * Delete workers, close listening ports. - * @param daemon: the daemon. - */ -void daemon_delete(struct daemon* daemon); - -/** - * Apply config settings. - * @param daemon: the daemon. - * @param cfg: new config settings. - */ -void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg); - -#endif /* DAEMON_H */ diff --git a/crates/libunbound-sys/unbound/daemon/remote.c b/crates/libunbound-sys/unbound/daemon/remote.c deleted file mode 100644 index 4990fc8e..00000000 --- a/crates/libunbound-sys/unbound/daemon/remote.c +++ /dev/null @@ -1,3356 +0,0 @@ -/* - * daemon/remote.c - remote control for the unbound daemon. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the remote control functionality for the daemon. - * The remote control can be performed using either the commandline - * unbound-control tool, or a TLS capable web browser. - * The channel is secured using TLSv1, and certificates. - * Both the server and the client(control tool) have their own keys. - */ -#include "config.h" -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif -#ifdef HAVE_OPENSSL_DH_H -#include -#endif -#ifdef HAVE_OPENSSL_BN_H -#include -#endif - -#include -#include "daemon/remote.h" -#include "daemon/worker.h" -#include "daemon/daemon.h" -#include "daemon/stats.h" -#include "daemon/cachedump.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/module.h" -#include "services/listen_dnsport.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "services/mesh.h" -#include "services/localzone.h" -#include "services/authzone.h" -#include "services/rpz.h" -#include "util/storage/slabhash.h" -#include "util/fptr_wlist.h" -#include "util/data/dname.h" -#include "validator/validator.h" -#include "validator/val_kcache.h" -#include "validator/val_kentry.h" -#include "validator/val_anchor.h" -#include "iterator/iterator.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_hints.h" -#include "iterator/iter_delegpt.h" -#include "services/outbound_list.h" -#include "services/outside_network.h" -#include "sldns/str2wire.h" -#include "sldns/parseutil.h" -#include "sldns/wire2str.h" -#include "sldns/sbuffer.h" -#include "util/timeval_func.h" - -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif - -/* just for portability */ -#ifdef SQ -#undef SQ -#endif - -/** what to put on statistics lines between var and value, ": " or "=" */ -#define SQ "=" - -static int -remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg) -{ - char* s_cert; - char* s_key; - rc->ctx = SSL_CTX_new(SSLv23_server_method()); - if(!rc->ctx) { - log_crypto_err("could not SSL_CTX_new"); - return 0; - } - if(!listen_sslctx_setup(rc->ctx)) { - return 0; - } - - s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); - s_key = fname_after_chroot(cfg->server_key_file, cfg, 1); - if(!s_cert || !s_key) { - log_err("out of memory in remote control fname"); - goto setup_error; - } - verbose(VERB_ALGO, "setup SSL certificates"); - if (!SSL_CTX_use_certificate_chain_file(rc->ctx,s_cert)) { - log_err("Error for server-cert-file: %s", s_cert); - log_crypto_err("Error in SSL_CTX use_certificate_chain_file"); - goto setup_error; - } - if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) { - log_err("Error for server-key-file: %s", s_key); - log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); - goto setup_error; - } - if(!SSL_CTX_check_private_key(rc->ctx)) { - log_err("Error for server-key-file: %s", s_key); - log_crypto_err("Error in SSL_CTX check_private_key"); - goto setup_error; - } - listen_sslctx_setup_2(rc->ctx); - if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) { - log_crypto_err("Error setting up SSL_CTX verify locations"); - setup_error: - free(s_cert); - free(s_key); - return 0; - } - SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert)); - SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL); - free(s_cert); - free(s_key); - return 1; -} - -struct daemon_remote* -daemon_remote_create(struct config_file* cfg) -{ - struct daemon_remote* rc = (struct daemon_remote*)calloc(1, - sizeof(*rc)); - if(!rc) { - log_err("out of memory in daemon_remote_create"); - return NULL; - } - rc->max_active = 10; - - if(!cfg->remote_control_enable) { - rc->ctx = NULL; - return rc; - } - if(options_remote_is_address(cfg) && cfg->control_use_cert) { - if(!remote_setup_ctx(rc, cfg)) { - daemon_remote_delete(rc); - return NULL; - } - rc->use_cert = 1; - } else { - struct config_strlist* p; - rc->ctx = NULL; - rc->use_cert = 0; - if(!options_remote_is_address(cfg)) - for(p = cfg->control_ifs.first; p; p = p->next) { - if(p->str && p->str[0] != '/') - log_warn("control-interface %s is not using TLS, but plain transfer, because first control-interface in config file is a local socket (starts with a /).", p->str); - } - } - return rc; -} - -void daemon_remote_clear(struct daemon_remote* rc) -{ - struct rc_state* p, *np; - if(!rc) return; - /* but do not close the ports */ - listen_list_delete(rc->accept_list); - rc->accept_list = NULL; - /* do close these sockets */ - p = rc->busy_list; - while(p) { - np = p->next; - if(p->ssl) - SSL_free(p->ssl); - comm_point_delete(p->c); - free(p); - p = np; - } - rc->busy_list = NULL; - rc->active = 0; - rc->worker = NULL; -} - -void daemon_remote_delete(struct daemon_remote* rc) -{ - if(!rc) return; - daemon_remote_clear(rc); - if(rc->ctx) { - SSL_CTX_free(rc->ctx); - } - free(rc); -} - -/** - * Add and open a new control port - * @param ip: ip str - * @param nr: port nr - * @param list: list head - * @param noproto_is_err: if lack of protocol support is an error. - * @param cfg: config with username for chown of unix-sockets. - * @return false on failure. - */ -static int -add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, - struct config_file* cfg) -{ - struct addrinfo hints; - struct addrinfo* res; - struct listen_port* n; - int noproto = 0; - int fd, r; - char port[15]; - snprintf(port, sizeof(port), "%d", nr); - port[sizeof(port)-1]=0; - memset(&hints, 0, sizeof(hints)); - log_assert(ip); - - if(ip[0] == '/') { - /* This looks like a local socket */ - fd = create_local_accept_sock(ip, &noproto, cfg->use_systemd); - /* - * Change socket ownership and permissions so users other - * than root can access it provided they are in the same - * group as the user we run as. - */ - if(fd != -1) { -#ifdef HAVE_CHOWN - chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); - if (cfg->username && cfg->username[0] && - cfg_uid != (uid_t)-1) { - if(chown(ip, cfg_uid, cfg_gid) == -1) - verbose(VERB_QUERY, "cannot chown %u.%u %s: %s", - (unsigned)cfg_uid, (unsigned)cfg_gid, - ip, strerror(errno)); - } -#else - (void)cfg; -#endif - } - } else { - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) { -#ifdef USE_WINSOCK - if(!noproto_is_err && r == EAI_NONAME) { - /* tried to lookup the address as name */ - return 1; /* return success, but do nothing */ - } -#endif /* USE_WINSOCK */ - log_err("control interface %s:%s getaddrinfo: %s %s", - ip?ip:"default", port, gai_strerror(r), -#ifdef EAI_SYSTEM - r==EAI_SYSTEM?(char*)strerror(errno):"" -#else - "" -#endif - ); - return 0; - } - - /* open fd */ - fd = create_tcp_accept_sock(res, 1, &noproto, 0, - cfg->ip_transparent, 0, 0, cfg->ip_freebind, - cfg->use_systemd, cfg->ip_dscp); - freeaddrinfo(res); - } - - if(fd == -1 && noproto) { - if(!noproto_is_err) - return 1; /* return success, but do nothing */ - log_err("cannot open control interface %s %d : " - "protocol not supported", ip, nr); - return 0; - } - if(fd == -1) { - log_err("cannot open control interface %s %d", ip, nr); - return 0; - } - - /* alloc */ - n = (struct listen_port*)calloc(1, sizeof(*n)); - if(!n) { - sock_close(fd); - log_err("out of memory"); - return 0; - } - n->next = *list; - *list = n; - n->fd = fd; - return 1; -} - -struct listen_port* daemon_remote_open_ports(struct config_file* cfg) -{ - struct listen_port* l = NULL; - log_assert(cfg->remote_control_enable && cfg->control_port); - if(cfg->control_ifs.first) { - char** rcif = NULL; - int i, num_rcif = 0; - if(!resolve_interface_names(NULL, 0, cfg->control_ifs.first, - &rcif, &num_rcif)) { - return NULL; - } - for(i=0; icontrol_port, &l, 1, cfg)) { - listening_ports_free(l); - config_del_strarray(rcif, num_rcif); - return NULL; - } - } - config_del_strarray(rcif, num_rcif); - } else { - /* defaults */ - if(cfg->do_ip6 && - !add_open("::1", cfg->control_port, &l, 0, cfg)) { - listening_ports_free(l); - return NULL; - } - if(cfg->do_ip4 && - !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) { - listening_ports_free(l); - return NULL; - } - } - return l; -} - -/** open accept commpoint */ -static int -accept_open(struct daemon_remote* rc, int fd) -{ - struct listen_list* n = (struct listen_list*)malloc(sizeof(*n)); - if(!n) { - log_err("out of memory"); - return 0; - } - n->next = rc->accept_list; - rc->accept_list = n; - /* open commpt */ - n->com = comm_point_create_raw(rc->worker->base, fd, 0, - &remote_accept_callback, rc); - if(!n->com) - return 0; - /* keep this port open, its fd is kept in the rc portlist */ - n->com->do_not_close = 1; - return 1; -} - -int daemon_remote_open_accept(struct daemon_remote* rc, - struct listen_port* ports, struct worker* worker) -{ - struct listen_port* p; - rc->worker = worker; - for(p = ports; p; p = p->next) { - if(!accept_open(rc, p->fd)) { - log_err("could not create accept comm point"); - return 0; - } - } - return 1; -} - -void daemon_remote_stop_accept(struct daemon_remote* rc) -{ - struct listen_list* p; - for(p=rc->accept_list; p; p=p->next) { - comm_point_stop_listening(p->com); - } -} - -void daemon_remote_start_accept(struct daemon_remote* rc) -{ - struct listen_list* p; - for(p=rc->accept_list; p; p=p->next) { - comm_point_start_listening(p->com, -1, -1); - } -} - -int remote_accept_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* ATTR_UNUSED(rep)) -{ - struct daemon_remote* rc = (struct daemon_remote*)arg; - struct sockaddr_storage addr; - socklen_t addrlen; - int newfd; - struct rc_state* n; - if(err != NETEVENT_NOERROR) { - log_err("error %d on remote_accept_callback", err); - return 0; - } - /* perform the accept */ - newfd = comm_point_perform_accept(c, &addr, &addrlen); - if(newfd == -1) - return 0; - /* create new commpoint unless we are servicing already */ - if(rc->active >= rc->max_active) { - log_warn("drop incoming remote control: too many connections"); - close_exit: - sock_close(newfd); - return 0; - } - - /* setup commpoint to service the remote control command */ - n = (struct rc_state*)calloc(1, sizeof(*n)); - if(!n) { - log_err("out of memory"); - goto close_exit; - } - n->fd = newfd; - /* start in reading state */ - n->c = comm_point_create_raw(rc->worker->base, newfd, 0, - &remote_control_callback, n); - if(!n->c) { - log_err("out of memory"); - free(n); - goto close_exit; - } - log_addr(VERB_QUERY, "new control connection from", &addr, addrlen); - n->c->do_not_close = 0; - comm_point_stop_listening(n->c); - comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT); - memcpy(&n->c->repinfo.remote_addr, &addr, addrlen); - n->c->repinfo.remote_addrlen = addrlen; - if(rc->use_cert) { - n->shake_state = rc_hs_read; - n->ssl = SSL_new(rc->ctx); - if(!n->ssl) { - log_crypto_err("could not SSL_new"); - comm_point_delete(n->c); - free(n); - goto close_exit; - } - SSL_set_accept_state(n->ssl); - (void)SSL_set_mode(n->ssl, (long)SSL_MODE_AUTO_RETRY); - if(!SSL_set_fd(n->ssl, newfd)) { - log_crypto_err("could not SSL_set_fd"); - SSL_free(n->ssl); - comm_point_delete(n->c); - free(n); - goto close_exit; - } - } else { - n->ssl = NULL; - } - - n->rc = rc; - n->next = rc->busy_list; - rc->busy_list = n; - rc->active ++; - - /* perform the first nonblocking read already, for windows, - * so it can return wouldblock. could be faster too. */ - (void)remote_control_callback(n->c, n, NETEVENT_NOERROR, NULL); - return 0; -} - -/** delete from list */ -static void -state_list_remove_elem(struct rc_state** list, struct comm_point* c) -{ - while(*list) { - if( (*list)->c == c) { - *list = (*list)->next; - return; - } - list = &(*list)->next; - } -} - -/** decrease active count and remove commpoint from busy list */ -static void -clean_point(struct daemon_remote* rc, struct rc_state* s) -{ - state_list_remove_elem(&rc->busy_list, s->c); - rc->active --; - if(s->ssl) { - SSL_shutdown(s->ssl); - SSL_free(s->ssl); - } - comm_point_delete(s->c); - free(s); -} - -int -ssl_print_text(RES* res, const char* text) -{ - int r; - if(!res) - return 0; - if(res->ssl) { - ERR_clear_error(); - if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) { - verbose(VERB_QUERY, "warning, in SSL_write, peer " - "closed connection"); - return 0; - } - log_crypto_err("could not SSL_write"); - return 0; - } - } else { - size_t at = 0; - while(at < strlen(text)) { - ssize_t r = send(res->fd, text+at, strlen(text)-at, 0); - if(r == -1) { - if(errno == EAGAIN || errno == EINTR) - continue; - log_err("could not send: %s", - sock_strerror(errno)); - return 0; - } - at += r; - } - } - return 1; -} - -/** print text over the ssl connection */ -static int -ssl_print_vmsg(RES* ssl, const char* format, va_list args) -{ - char msg[1024]; - vsnprintf(msg, sizeof(msg), format, args); - return ssl_print_text(ssl, msg); -} - -/** printf style printing to the ssl connection */ -int ssl_printf(RES* ssl, const char* format, ...) -{ - va_list args; - int ret; - va_start(args, format); - ret = ssl_print_vmsg(ssl, format, args); - va_end(args); - return ret; -} - -int -ssl_read_line(RES* res, char* buf, size_t max) -{ - int r; - size_t len = 0; - if(!res) - return 0; - while(len < max) { - if(res->ssl) { - ERR_clear_error(); - if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) { - buf[len] = 0; - return 1; - } - log_crypto_err("could not SSL_read"); - return 0; - } - } else { - while(1) { - ssize_t rr = recv(res->fd, buf+len, 1, 0); - if(rr <= 0) { - if(rr == 0) { - buf[len] = 0; - return 1; - } - if(errno == EINTR || errno == EAGAIN) - continue; - log_err("could not recv: %s", - sock_strerror(errno)); - return 0; - } - break; - } - } - if(buf[len] == '\n') { - /* return string without \n */ - buf[len] = 0; - return 1; - } - len++; - } - buf[max-1] = 0; - log_err("control line too long (%d): %s", (int)max, buf); - return 0; -} - -/** skip whitespace, return new pointer into string */ -static char* -skipwhite(char* str) -{ - /* EOS \0 is not a space */ - while( isspace((unsigned char)*str) ) - str++; - return str; -} - -/** send the OK to the control client */ -static void send_ok(RES* ssl) -{ - (void)ssl_printf(ssl, "ok\n"); -} - -/** do the stop command */ -static void -do_stop(RES* ssl, struct worker* worker) -{ - worker->need_to_exit = 1; - comm_base_exit(worker->base); - send_ok(ssl); -} - -/** do the reload command */ -static void -do_reload(RES* ssl, struct worker* worker, int reuse_cache) -{ - worker->reuse_cache = reuse_cache; - worker->need_to_exit = 0; - comm_base_exit(worker->base); - send_ok(ssl); -} - -/** do the verbosity command */ -static void -do_verbosity(RES* ssl, char* str) -{ - int val = atoi(str); - if(val == 0 && strcmp(str, "0") != 0) { - ssl_printf(ssl, "error in verbosity number syntax: %s\n", str); - return; - } - verbosity = val; - send_ok(ssl); -} - -/** print stats from statinfo */ -static int -print_stats(RES* ssl, const char* nm, struct ub_stats_info* s) -{ - struct timeval sumwait, avg; - if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries)) return 0; - if(!ssl_printf(ssl, "%s.num.queries_ip_ratelimited"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_ip_ratelimited)) return 0; - if(!ssl_printf(ssl, "%s.num.queries_cookie_valid"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_cookie_valid)) return 0; - if(!ssl_printf(ssl, "%s.num.queries_cookie_client"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_cookie_client)) return 0; - if(!ssl_printf(ssl, "%s.num.queries_cookie_invalid"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_cookie_invalid)) return 0; - if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm, - (unsigned long)(s->svr.num_queries - - s->svr.num_queries_missed_cache))) return 0; - if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_missed_cache)) return 0; - if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_prefetch)) return 0; - if(!ssl_printf(ssl, "%s.num.queries_timed_out"SQ"%lu\n", nm, - (unsigned long)s->svr.num_queries_timed_out)) return 0; - if(!ssl_printf(ssl, "%s.query.queue_time_us.max"SQ"%lu\n", nm, - (unsigned long)s->svr.max_query_time_us)) return 0; - if(!ssl_printf(ssl, "%s.num.expired"SQ"%lu\n", nm, - (unsigned long)s->svr.ans_expired)) return 0; - if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm, - (unsigned long)s->mesh_replies_sent)) return 0; -#ifdef USE_DNSCRYPT - if(!ssl_printf(ssl, "%s.num.dnscrypt.crypted"SQ"%lu\n", nm, - (unsigned long)s->svr.num_query_dnscrypt_crypted)) return 0; - if(!ssl_printf(ssl, "%s.num.dnscrypt.cert"SQ"%lu\n", nm, - (unsigned long)s->svr.num_query_dnscrypt_cert)) return 0; - if(!ssl_printf(ssl, "%s.num.dnscrypt.cleartext"SQ"%lu\n", nm, - (unsigned long)s->svr.num_query_dnscrypt_cleartext)) return 0; - if(!ssl_printf(ssl, "%s.num.dnscrypt.malformed"SQ"%lu\n", nm, - (unsigned long)s->svr.num_query_dnscrypt_crypted_malformed)) return 0; -#endif - if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm, - (s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)? - (double)s->svr.sum_query_list_size/ - (double)(s->svr.num_queries_missed_cache+ - s->svr.num_queries_prefetch) : 0.0)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%lu\n", nm, - (unsigned long)s->svr.max_query_list_size)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.overwritten"SQ"%lu\n", nm, - (unsigned long)s->mesh_jostled)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.exceeded"SQ"%lu\n", nm, - (unsigned long)s->mesh_dropped)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.current.all"SQ"%lu\n", nm, - (unsigned long)s->mesh_num_states)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%lu\n", nm, - (unsigned long)s->mesh_num_reply_states)) return 0; -#ifndef S_SPLINT_S - sumwait.tv_sec = s->mesh_replies_sum_wait_sec; - sumwait.tv_usec = s->mesh_replies_sum_wait_usec; -#endif - timeval_divide(&avg, &sumwait, s->mesh_replies_sent); - if(!ssl_printf(ssl, "%s.recursion.time.avg"SQ ARG_LL "d.%6.6d\n", nm, - (long long)avg.tv_sec, (int)avg.tv_usec)) return 0; - if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm, - s->mesh_time_median)) return 0; - if(!ssl_printf(ssl, "%s.tcpusage"SQ"%lu\n", nm, - (unsigned long)s->svr.tcp_accept_usage)) return 0; - return 1; -} - -/** print stats for one thread */ -static int -print_thread_stats(RES* ssl, int i, struct ub_stats_info* s) -{ - char nm[32]; - snprintf(nm, sizeof(nm), "thread%d", i); - nm[sizeof(nm)-1]=0; - return print_stats(ssl, nm, s); -} - -/** print long number */ -static int -print_longnum(RES* ssl, const char* desc, size_t x) -{ - if(x > 1024*1024*1024) { - /* more than a Gb */ - size_t front = x / (size_t)1000000; - size_t back = x % (size_t)1000000; - return ssl_printf(ssl, "%s%u%6.6u\n", desc, - (unsigned)front, (unsigned)back); - } else { - return ssl_printf(ssl, "%s%lu\n", desc, (unsigned long)x); - } -} - -/** print mem stats */ -static int -print_mem(RES* ssl, struct worker* worker, struct daemon* daemon, - struct ub_stats_info* s) -{ - size_t msg, rrset, val, iter, respip; -#ifdef CLIENT_SUBNET - size_t subnet = 0; -#endif /* CLIENT_SUBNET */ -#ifdef USE_IPSECMOD - size_t ipsecmod = 0; -#endif /* USE_IPSECMOD */ -#ifdef USE_DNSCRYPT - size_t dnscrypt_shared_secret = 0; - size_t dnscrypt_nonce = 0; -#endif /* USE_DNSCRYPT */ -#ifdef WITH_DYNLIBMODULE - size_t dynlib = 0; -#endif /* WITH_DYNLIBMODULE */ - msg = slabhash_get_mem(daemon->env->msg_cache); - rrset = slabhash_get_mem(&daemon->env->rrset_cache->table); - val = mod_get_mem(&worker->env, "validator"); - iter = mod_get_mem(&worker->env, "iterator"); - respip = mod_get_mem(&worker->env, "respip"); -#ifdef CLIENT_SUBNET - subnet = mod_get_mem(&worker->env, "subnetcache"); -#endif /* CLIENT_SUBNET */ -#ifdef USE_IPSECMOD - ipsecmod = mod_get_mem(&worker->env, "ipsecmod"); -#endif /* USE_IPSECMOD */ -#ifdef USE_DNSCRYPT - if(daemon->dnscenv) { - dnscrypt_shared_secret = slabhash_get_mem( - daemon->dnscenv->shared_secrets_cache); - dnscrypt_nonce = slabhash_get_mem(daemon->dnscenv->nonces_cache); - } -#endif /* USE_DNSCRYPT */ -#ifdef WITH_DYNLIBMODULE - dynlib = mod_get_mem(&worker->env, "dynlib"); -#endif /* WITH_DYNLIBMODULE */ - - if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset)) - return 0; - if(!print_longnum(ssl, "mem.cache.message"SQ, msg)) - return 0; - if(!print_longnum(ssl, "mem.mod.iterator"SQ, iter)) - return 0; - if(!print_longnum(ssl, "mem.mod.validator"SQ, val)) - return 0; - if(!print_longnum(ssl, "mem.mod.respip"SQ, respip)) - return 0; -#ifdef CLIENT_SUBNET - if(!print_longnum(ssl, "mem.mod.subnet"SQ, subnet)) - return 0; -#endif /* CLIENT_SUBNET */ -#ifdef USE_IPSECMOD - if(!print_longnum(ssl, "mem.mod.ipsecmod"SQ, ipsecmod)) - return 0; -#endif /* USE_IPSECMOD */ -#ifdef USE_DNSCRYPT - if(!print_longnum(ssl, "mem.cache.dnscrypt_shared_secret"SQ, - dnscrypt_shared_secret)) - return 0; - if(!print_longnum(ssl, "mem.cache.dnscrypt_nonce"SQ, - dnscrypt_nonce)) - return 0; -#endif /* USE_DNSCRYPT */ -#ifdef WITH_DYNLIBMODULE - if(!print_longnum(ssl, "mem.mod.dynlibmod"SQ, dynlib)) - return 0; -#endif /* WITH_DYNLIBMODULE */ - if(!print_longnum(ssl, "mem.streamwait"SQ, - (size_t)s->svr.mem_stream_wait)) - return 0; - if(!print_longnum(ssl, "mem.http.query_buffer"SQ, - (size_t)s->svr.mem_http2_query_buffer)) - return 0; - if(!print_longnum(ssl, "mem.http.response_buffer"SQ, - (size_t)s->svr.mem_http2_response_buffer)) - return 0; - return 1; -} - -/** print uptime stats */ -static int -print_uptime(RES* ssl, struct worker* worker, int reset) -{ - struct timeval now = *worker->env.now_tv; - struct timeval up, dt; - timeval_subtract(&up, &now, &worker->daemon->time_boot); - timeval_subtract(&dt, &now, &worker->daemon->time_last_stat); - if(reset) - worker->daemon->time_last_stat = now; - if(!ssl_printf(ssl, "time.now"SQ ARG_LL "d.%6.6d\n", - (long long)now.tv_sec, (unsigned)now.tv_usec)) return 0; - if(!ssl_printf(ssl, "time.up"SQ ARG_LL "d.%6.6d\n", - (long long)up.tv_sec, (unsigned)up.tv_usec)) return 0; - if(!ssl_printf(ssl, "time.elapsed"SQ ARG_LL "d.%6.6d\n", - (long long)dt.tv_sec, (unsigned)dt.tv_usec)) return 0; - return 1; -} - -/** print extended histogram */ -static int -print_hist(RES* ssl, struct ub_stats_info* s) -{ - struct timehist* hist; - size_t i; - hist = timehist_setup(); - if(!hist) { - log_err("out of memory"); - return 0; - } - timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST); - for(i=0; inum; i++) { - if(!ssl_printf(ssl, - "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n", - (int)hist->buckets[i].lower.tv_sec, - (int)hist->buckets[i].lower.tv_usec, - (int)hist->buckets[i].upper.tv_sec, - (int)hist->buckets[i].upper.tv_usec, - (unsigned long)hist->buckets[i].count)) { - timehist_delete(hist); - return 0; - } - } - timehist_delete(hist); - return 1; -} - -/** print extended stats */ -static int -print_ext(RES* ssl, struct ub_stats_info* s, int inhibit_zero) -{ - int i; - char nm[32]; - const sldns_rr_descriptor* desc; - const sldns_lookup_table* lt; - /* TYPE */ - for(i=0; isvr.qtype[i] == 0) - continue; - desc = sldns_rr_descript((uint16_t)i); - if(desc && desc->_name) { - snprintf(nm, sizeof(nm), "%s", desc->_name); - } else if (i == LDNS_RR_TYPE_IXFR) { - snprintf(nm, sizeof(nm), "IXFR"); - } else if (i == LDNS_RR_TYPE_AXFR) { - snprintf(nm, sizeof(nm), "AXFR"); - } else if (i == LDNS_RR_TYPE_MAILA) { - snprintf(nm, sizeof(nm), "MAILA"); - } else if (i == LDNS_RR_TYPE_MAILB) { - snprintf(nm, sizeof(nm), "MAILB"); - } else if (i == LDNS_RR_TYPE_ANY) { - snprintf(nm, sizeof(nm), "ANY"); - } else { - snprintf(nm, sizeof(nm), "TYPE%d", i); - } - if(!ssl_printf(ssl, "num.query.type.%s"SQ"%lu\n", - nm, (unsigned long)s->svr.qtype[i])) return 0; - } - if(!inhibit_zero || s->svr.qtype_big) { - if(!ssl_printf(ssl, "num.query.type.other"SQ"%lu\n", - (unsigned long)s->svr.qtype_big)) return 0; - } - /* CLASS */ - for(i=0; isvr.qclass[i] == 0) - continue; - lt = sldns_lookup_by_id(sldns_rr_classes, i); - if(lt && lt->name) { - snprintf(nm, sizeof(nm), "%s", lt->name); - } else { - snprintf(nm, sizeof(nm), "CLASS%d", i); - } - if(!ssl_printf(ssl, "num.query.class.%s"SQ"%lu\n", - nm, (unsigned long)s->svr.qclass[i])) return 0; - } - if(!inhibit_zero || s->svr.qclass_big) { - if(!ssl_printf(ssl, "num.query.class.other"SQ"%lu\n", - (unsigned long)s->svr.qclass_big)) return 0; - } - /* OPCODE */ - for(i=0; isvr.qopcode[i] == 0) - continue; - lt = sldns_lookup_by_id(sldns_opcodes, i); - if(lt && lt->name) { - snprintf(nm, sizeof(nm), "%s", lt->name); - } else { - snprintf(nm, sizeof(nm), "OPCODE%d", i); - } - if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%lu\n", - nm, (unsigned long)s->svr.qopcode[i])) return 0; - } - /* transport */ - if(!ssl_printf(ssl, "num.query.tcp"SQ"%lu\n", - (unsigned long)s->svr.qtcp)) return 0; - if(!ssl_printf(ssl, "num.query.tcpout"SQ"%lu\n", - (unsigned long)s->svr.qtcp_outgoing)) return 0; - if(!ssl_printf(ssl, "num.query.udpout"SQ"%lu\n", - (unsigned long)s->svr.qudp_outgoing)) return 0; - if(!ssl_printf(ssl, "num.query.tls"SQ"%lu\n", - (unsigned long)s->svr.qtls)) return 0; - if(!ssl_printf(ssl, "num.query.tls.resume"SQ"%lu\n", - (unsigned long)s->svr.qtls_resume)) return 0; - if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n", - (unsigned long)s->svr.qipv6)) return 0; - if(!ssl_printf(ssl, "num.query.https"SQ"%lu\n", - (unsigned long)s->svr.qhttps)) return 0; - /* flags */ - if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%lu\n", - (unsigned long)s->svr.qbit_QR)) return 0; - if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%lu\n", - (unsigned long)s->svr.qbit_AA)) return 0; - if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%lu\n", - (unsigned long)s->svr.qbit_TC)) return 0; - if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%lu\n", - (unsigned long)s->svr.qbit_RD)) return 0; - if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%lu\n", - (unsigned long)s->svr.qbit_RA)) return 0; - if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%lu\n", - (unsigned long)s->svr.qbit_Z)) return 0; - if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%lu\n", - (unsigned long)s->svr.qbit_AD)) return 0; - if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%lu\n", - (unsigned long)s->svr.qbit_CD)) return 0; - if(!ssl_printf(ssl, "num.query.edns.present"SQ"%lu\n", - (unsigned long)s->svr.qEDNS)) return 0; - if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%lu\n", - (unsigned long)s->svr.qEDNS_DO)) return 0; - - /* RCODE */ - for(i=0; i LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0) - continue; - lt = sldns_lookup_by_id(sldns_rcodes, i); - if(lt && lt->name) { - snprintf(nm, sizeof(nm), "%s", lt->name); - } else { - snprintf(nm, sizeof(nm), "RCODE%d", i); - } - if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%lu\n", - nm, (unsigned long)s->svr.ans_rcode[i])) return 0; - } - if(!inhibit_zero || s->svr.ans_rcode_nodata) { - if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%lu\n", - (unsigned long)s->svr.ans_rcode_nodata)) return 0; - } - /* iteration */ - if(!ssl_printf(ssl, "num.query.ratelimited"SQ"%lu\n", - (unsigned long)s->svr.queries_ratelimited)) return 0; - /* validation */ - if(!ssl_printf(ssl, "num.answer.secure"SQ"%lu\n", - (unsigned long)s->svr.ans_secure)) return 0; - if(!ssl_printf(ssl, "num.answer.bogus"SQ"%lu\n", - (unsigned long)s->svr.ans_bogus)) return 0; - if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n", - (unsigned long)s->svr.rrset_bogus)) return 0; - if(!ssl_printf(ssl, "num.query.aggressive.NOERROR"SQ"%lu\n", - (unsigned long)s->svr.num_neg_cache_noerror)) return 0; - if(!ssl_printf(ssl, "num.query.aggressive.NXDOMAIN"SQ"%lu\n", - (unsigned long)s->svr.num_neg_cache_nxdomain)) return 0; - /* threat detection */ - if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n", - (unsigned long)s->svr.unwanted_queries)) return 0; - if(!ssl_printf(ssl, "unwanted.replies"SQ"%lu\n", - (unsigned long)s->svr.unwanted_replies)) return 0; - /* cache counts */ - if(!ssl_printf(ssl, "msg.cache.count"SQ"%u\n", - (unsigned)s->svr.msg_cache_count)) return 0; - if(!ssl_printf(ssl, "rrset.cache.count"SQ"%u\n", - (unsigned)s->svr.rrset_cache_count)) return 0; - if(!ssl_printf(ssl, "infra.cache.count"SQ"%u\n", - (unsigned)s->svr.infra_cache_count)) return 0; - if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n", - (unsigned)s->svr.key_cache_count)) return 0; - /* max collisions */ - if(!ssl_printf(ssl, "msg.cache.max_collisions"SQ"%u\n", - (unsigned)s->svr.msg_cache_max_collisions)) return 0; - if(!ssl_printf(ssl, "rrset.cache.max_collisions"SQ"%u\n", - (unsigned)s->svr.rrset_cache_max_collisions)) return 0; - /* applied RPZ actions */ - for(i=0; isvr.rpz_action[i] == 0) - continue; - if(!ssl_printf(ssl, "num.rpz.action.%s"SQ"%lu\n", - rpz_action_to_string(i), - (unsigned long)s->svr.rpz_action[i])) return 0; - } -#ifdef USE_DNSCRYPT - if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n", - (unsigned)s->svr.shared_secret_cache_count)) return 0; - if(!ssl_printf(ssl, "dnscrypt_nonce.cache.count"SQ"%u\n", - (unsigned)s->svr.nonce_cache_count)) return 0; - if(!ssl_printf(ssl, "num.query.dnscrypt.shared_secret.cachemiss"SQ"%lu\n", - (unsigned long)s->svr.num_query_dnscrypt_secret_missed_cache)) return 0; - if(!ssl_printf(ssl, "num.query.dnscrypt.replay"SQ"%lu\n", - (unsigned long)s->svr.num_query_dnscrypt_replay)) return 0; -#endif /* USE_DNSCRYPT */ - if(!ssl_printf(ssl, "num.query.authzone.up"SQ"%lu\n", - (unsigned long)s->svr.num_query_authzone_up)) return 0; - if(!ssl_printf(ssl, "num.query.authzone.down"SQ"%lu\n", - (unsigned long)s->svr.num_query_authzone_down)) return 0; -#ifdef CLIENT_SUBNET - if(!ssl_printf(ssl, "num.query.subnet"SQ"%lu\n", - (unsigned long)s->svr.num_query_subnet)) return 0; - if(!ssl_printf(ssl, "num.query.subnet_cache"SQ"%lu\n", - (unsigned long)s->svr.num_query_subnet_cache)) return 0; -#endif /* CLIENT_SUBNET */ -#ifdef USE_CACHEDB - if(!ssl_printf(ssl, "num.query.cachedb"SQ"%lu\n", - (unsigned long)s->svr.num_query_cachedb)) return 0; -#endif /* USE_CACHEDB */ - return 1; -} - -/** do the stats command */ -static void -do_stats(RES* ssl, struct worker* worker, int reset) -{ - struct daemon* daemon = worker->daemon; - struct ub_stats_info total; - struct ub_stats_info s; - int i; - memset(&total, 0, sizeof(total)); - log_assert(daemon->num > 0); - /* gather all thread statistics in one place */ - for(i=0; inum; i++) { - server_stats_obtain(worker, daemon->workers[i], &s, reset); - if(!print_thread_stats(ssl, i, &s)) - return; - if(i == 0) - total = s; - else server_stats_add(&total, &s); - } - /* print the thread statistics */ - total.mesh_time_median /= (double)daemon->num; - if(!print_stats(ssl, "total", &total)) - return; - if(!print_uptime(ssl, worker, reset)) - return; - if(daemon->cfg->stat_extended) { - if(!print_mem(ssl, worker, daemon, &total)) - return; - if(!print_hist(ssl, &total)) - return; - if(!print_ext(ssl, &total, daemon->cfg->stat_inhibit_zero)) - return; - } -} - -/** parse commandline argument domain name */ -static int -parse_arg_name(RES* ssl, char* str, uint8_t** res, size_t* len, int* labs) -{ - uint8_t nm[LDNS_MAX_DOMAINLEN+1]; - size_t nmlen = sizeof(nm); - int status; - *res = NULL; - *len = 0; - *labs = 0; - if(str[0] == '\0') { - ssl_printf(ssl, "error: this option requires a domain name\n"); - return 0; - } - status = sldns_str2wire_dname_buf(str, nm, &nmlen); - if(status != 0) { - ssl_printf(ssl, "error cannot parse name %s at %d: %s\n", str, - LDNS_WIREPARSE_OFFSET(status), - sldns_get_errorstr_parse(status)); - return 0; - } - *res = memdup(nm, nmlen); - if(!*res) { - ssl_printf(ssl, "error out of memory\n"); - return 0; - } - *labs = dname_count_size_labels(*res, len); - return 1; -} - -/** find second argument, modifies string */ -static int -find_arg2(RES* ssl, char* arg, char** arg2) -{ - char* as = strchr(arg, ' '); - char* at = strchr(arg, '\t'); - if(as && at) { - if(at < as) - as = at; - as[0]=0; - *arg2 = skipwhite(as+1); - } else if(as) { - as[0]=0; - *arg2 = skipwhite(as+1); - } else if(at) { - at[0]=0; - *arg2 = skipwhite(at+1); - } else { - ssl_printf(ssl, "error could not find next argument " - "after %s\n", arg); - return 0; - } - return 1; -} - -/** Add a new zone */ -static int -perform_zone_add(RES* ssl, struct local_zones* zones, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - char* arg2; - enum localzone_type t; - struct local_zone* z; - if(!find_arg2(ssl, arg, &arg2)) - return 0; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return 0; - if(!local_zone_str2type(arg2, &t)) { - ssl_printf(ssl, "error not a zone type. %s\n", arg2); - free(nm); - return 0; - } - lock_rw_wrlock(&zones->lock); - if((z=local_zones_find(zones, nm, nmlen, - nmlabs, LDNS_RR_CLASS_IN))) { - /* already present in tree */ - lock_rw_wrlock(&z->lock); - z->type = t; /* update type anyway */ - lock_rw_unlock(&z->lock); - free(nm); - lock_rw_unlock(&zones->lock); - return 1; - } - if(!local_zones_add_zone(zones, nm, nmlen, - nmlabs, LDNS_RR_CLASS_IN, t)) { - lock_rw_unlock(&zones->lock); - ssl_printf(ssl, "error out of memory\n"); - return 0; - } - lock_rw_unlock(&zones->lock); - return 1; -} - -/** Do the local_zone command */ -static void -do_zone_add(RES* ssl, struct local_zones* zones, char* arg) -{ - if(!perform_zone_add(ssl, zones, arg)) - return; - send_ok(ssl); -} - -/** Do the local_zones command */ -static void -do_zones_add(RES* ssl, struct local_zones* zones) -{ - char buf[2048]; - int num = 0; - while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ - if(!perform_zone_add(ssl, zones, buf)) { - if(!ssl_printf(ssl, "error for input line: %s\n", buf)) - return; - } - else - num++; - } - (void)ssl_printf(ssl, "added %d zones\n", num); -} - -/** Remove a zone */ -static int -perform_zone_remove(RES* ssl, struct local_zones* zones, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - struct local_zone* z; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return 0; - lock_rw_wrlock(&zones->lock); - if((z=local_zones_find(zones, nm, nmlen, - nmlabs, LDNS_RR_CLASS_IN))) { - /* present in tree */ - local_zones_del_zone(zones, z); - } - lock_rw_unlock(&zones->lock); - free(nm); - return 1; -} - -/** Do the local_zone_remove command */ -static void -do_zone_remove(RES* ssl, struct local_zones* zones, char* arg) -{ - if(!perform_zone_remove(ssl, zones, arg)) - return; - send_ok(ssl); -} - -/** Do the local_zones_remove command */ -static void -do_zones_remove(RES* ssl, struct local_zones* zones) -{ - char buf[2048]; - int num = 0; - while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ - if(!perform_zone_remove(ssl, zones, buf)) { - if(!ssl_printf(ssl, "error for input line: %s\n", buf)) - return; - } - else - num++; - } - (void)ssl_printf(ssl, "removed %d zones\n", num); -} - -/** check syntax of newly added RR */ -static int -check_RR_syntax(RES* ssl, char* str, int line) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t len = sizeof(rr), dname_len = 0; - int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600, - NULL, 0, NULL, 0); - if(s != 0) { - char linestr[32]; - if(line == 0) - linestr[0]=0; - else snprintf(linestr, sizeof(linestr), "line %d ", line); - if(!ssl_printf(ssl, "error parsing local-data at %sposition %d '%s': %s\n", - linestr, LDNS_WIREPARSE_OFFSET(s), str, - sldns_get_errorstr_parse(s))) - return 0; - return 0; - } - return 1; -} - -/** Add new RR data */ -static int -perform_data_add(RES* ssl, struct local_zones* zones, char* arg, int line) -{ - if(!check_RR_syntax(ssl, arg, line)) { - return 0; - } - if(!local_zones_add_RR(zones, arg)) { - ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg); - return 0; - } - return 1; -} - -/** Do the local_data command */ -static void -do_data_add(RES* ssl, struct local_zones* zones, char* arg) -{ - if(!perform_data_add(ssl, zones, arg, 0)) - return; - send_ok(ssl); -} - -/** Do the local_datas command */ -static void -do_datas_add(RES* ssl, struct local_zones* zones) -{ - char buf[2048]; - int num = 0, line = 0; - while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ - line++; - if(perform_data_add(ssl, zones, buf, line)) - num++; - } - (void)ssl_printf(ssl, "added %d datas\n", num); -} - -/** Remove RR data */ -static int -perform_data_remove(RES* ssl, struct local_zones* zones, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return 0; - local_zones_del_data(zones, nm, - nmlen, nmlabs, LDNS_RR_CLASS_IN); - free(nm); - return 1; -} - -/** Do the local_data_remove command */ -static void -do_data_remove(RES* ssl, struct local_zones* zones, char* arg) -{ - if(!perform_data_remove(ssl, zones, arg)) - return; - send_ok(ssl); -} - -/** Do the local_datas_remove command */ -static void -do_datas_remove(RES* ssl, struct local_zones* zones) -{ - char buf[2048]; - int num = 0; - while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ - if(!perform_data_remove(ssl, zones, buf)) { - if(!ssl_printf(ssl, "error for input line: %s\n", buf)) - return; - } - else - num++; - } - (void)ssl_printf(ssl, "removed %d datas\n", num); -} - -/** Add a new zone to view */ -static void -do_view_zone_add(RES* ssl, struct worker* worker, char* arg) -{ - char* arg2; - struct view* v; - if(!find_arg2(ssl, arg, &arg2)) - return; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones) { - if(!(v->local_zones = local_zones_create())){ - lock_rw_unlock(&v->lock); - ssl_printf(ssl,"error out of memory\n"); - return; - } - if(!v->isfirst) { - /* Global local-zone is not used for this view, - * therefore add defaults to this view-specic - * local-zone. */ - struct config_file lz_cfg; - memset(&lz_cfg, 0, sizeof(lz_cfg)); - local_zone_enter_defaults(v->local_zones, &lz_cfg); - } - } - do_zone_add(ssl, v->local_zones, arg2); - lock_rw_unlock(&v->lock); -} - -/** Remove a zone from view */ -static void -do_view_zone_remove(RES* ssl, struct worker* worker, char* arg) -{ - char* arg2; - struct view* v; - if(!find_arg2(ssl, arg, &arg2)) - return; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones) { - lock_rw_unlock(&v->lock); - send_ok(ssl); - return; - } - do_zone_remove(ssl, v->local_zones, arg2); - lock_rw_unlock(&v->lock); -} - -/** Add new RR data to view */ -static void -do_view_data_add(RES* ssl, struct worker* worker, char* arg) -{ - char* arg2; - struct view* v; - if(!find_arg2(ssl, arg, &arg2)) - return; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones) { - if(!(v->local_zones = local_zones_create())){ - lock_rw_unlock(&v->lock); - ssl_printf(ssl,"error out of memory\n"); - return; - } - } - do_data_add(ssl, v->local_zones, arg2); - lock_rw_unlock(&v->lock); -} - -/** Add new RR data from stdin to view */ -static void -do_view_datas_add(RES* ssl, struct worker* worker, char* arg) -{ - struct view* v; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones) { - if(!(v->local_zones = local_zones_create())){ - lock_rw_unlock(&v->lock); - ssl_printf(ssl,"error out of memory\n"); - return; - } - } - do_datas_add(ssl, v->local_zones); - lock_rw_unlock(&v->lock); -} - -/** Remove RR data from view */ -static void -do_view_data_remove(RES* ssl, struct worker* worker, char* arg) -{ - char* arg2; - struct view* v; - if(!find_arg2(ssl, arg, &arg2)) - return; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones) { - lock_rw_unlock(&v->lock); - send_ok(ssl); - return; - } - do_data_remove(ssl, v->local_zones, arg2); - lock_rw_unlock(&v->lock); -} - -/** Remove RR data from stdin from view */ -static void -do_view_datas_remove(RES* ssl, struct worker* worker, char* arg) -{ - struct view* v; - v = views_find_view(worker->daemon->views, - arg, 1 /* get write lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(!v->local_zones){ - lock_rw_unlock(&v->lock); - ssl_printf(ssl, "removed 0 datas\n"); - return; - } - - do_datas_remove(ssl, v->local_zones); - lock_rw_unlock(&v->lock); -} - -/** cache lookup of nameservers */ -static void -do_lookup(RES* ssl, struct worker* worker, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - (void)print_deleg_lookup(ssl, worker, nm, nmlen, nmlabs); - free(nm); -} - -/** flush something from rrset and msg caches */ -static void -do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen, - uint16_t t, uint16_t c) -{ - hashvalue_type h; - struct query_info k; - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, 0); - if(t == LDNS_RR_TYPE_SOA) - rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, - PACKED_RRSET_SOA_NEG); - k.qname = nm; - k.qname_len = nmlen; - k.qtype = t; - k.qclass = c; - k.local_alias = NULL; - h = query_info_hash(&k, 0); - slabhash_remove(worker->env.msg_cache, h, &k); - if(t == LDNS_RR_TYPE_AAAA) { - /* for AAAA also flush dns64 bit_cd packet */ - h = query_info_hash(&k, BIT_CD); - slabhash_remove(worker->env.msg_cache, h, &k); - } -} - -/** flush a type */ -static void -do_flush_type(RES* ssl, struct worker* worker, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - char* arg2; - uint16_t t; - if(!find_arg2(ssl, arg, &arg2)) - return; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - t = sldns_get_rr_type_by_name(arg2); - if(t == 0 && strcmp(arg2, "TYPE0") != 0) { - return; - } - do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN); - - free(nm); - send_ok(ssl); -} - -/** flush statistics */ -static void -do_flush_stats(RES* ssl, struct worker* worker) -{ - worker_stats_clear(worker); - send_ok(ssl); -} - -/** - * Local info for deletion functions - */ -struct del_info { - /** worker */ - struct worker* worker; - /** name to delete */ - uint8_t* name; - /** length */ - size_t len; - /** labels */ - int labs; - /** time to invalidate to */ - time_t expired; - /** number of rrsets removed */ - size_t num_rrsets; - /** number of msgs removed */ - size_t num_msgs; - /** number of key entries removed */ - size_t num_keys; - /** length of addr */ - socklen_t addrlen; - /** socket address for host deletion */ - struct sockaddr_storage addr; -}; - -/** callback to delete hosts in infra cache */ -static void -infra_del_host(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct infra_key* k = (struct infra_key*)e->key; - if(sockaddr_cmp(&inf->addr, inf->addrlen, &k->addr, k->addrlen) == 0) { - struct infra_data* d = (struct infra_data*)e->data; - d->probedelay = 0; - d->timeout_A = 0; - d->timeout_AAAA = 0; - d->timeout_other = 0; - rtt_init(&d->rtt); - if(d->ttl > inf->expired) { - d->ttl = inf->expired; - inf->num_keys++; - } - } -} - -/** flush infra cache */ -static void -do_flush_infra(RES* ssl, struct worker* worker, char* arg) -{ - struct sockaddr_storage addr; - socklen_t len; - struct del_info inf; - if(strcmp(arg, "all") == 0) { - slabhash_clear(worker->env.infra_cache->hosts); - send_ok(ssl); - return; - } - if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) { - (void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg); - return; - } - /* delete all entries from cache */ - /* what we do is to set them all expired */ - inf.worker = worker; - inf.name = 0; - inf.len = 0; - inf.labs = 0; - inf.expired = *worker->env.now; - inf.expired -= 3; /* handle 3 seconds skew between threads */ - inf.num_rrsets = 0; - inf.num_msgs = 0; - inf.num_keys = 0; - inf.addrlen = len; - memmove(&inf.addr, &addr, len); - slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host, - &inf); - send_ok(ssl); -} - -/** flush requestlist */ -static void -do_flush_requestlist(RES* ssl, struct worker* worker) -{ - mesh_delete_all(worker->env.mesh); - send_ok(ssl); -} - -/** callback to delete rrsets in a zone */ -static void -zone_del_rrset(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key; - if(dname_subdomain_c(k->rk.dname, inf->name)) { - struct packed_rrset_data* d = - (struct packed_rrset_data*)e->data; - if(d->ttl > inf->expired) { - d->ttl = inf->expired; - inf->num_rrsets++; - } - } -} - -/** callback to delete messages in a zone */ -static void -zone_del_msg(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct msgreply_entry* k = (struct msgreply_entry*)e->key; - if(dname_subdomain_c(k->key.qname, inf->name)) { - struct reply_info* d = (struct reply_info*)e->data; - if(d->ttl > inf->expired) { - d->ttl = inf->expired; - d->prefetch_ttl = inf->expired; - d->serve_expired_ttl = inf->expired; - inf->num_msgs++; - } - } -} - -/** callback to delete keys in zone */ -static void -zone_del_kcache(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct key_entry_key* k = (struct key_entry_key*)e->key; - if(dname_subdomain_c(k->name, inf->name)) { - struct key_entry_data* d = (struct key_entry_data*)e->data; - if(d->ttl > inf->expired) { - d->ttl = inf->expired; - inf->num_keys++; - } - } -} - -/** remove all rrsets and keys from zone from cache */ -static void -do_flush_zone(RES* ssl, struct worker* worker, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - struct del_info inf; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - /* delete all RRs and key entries from zone */ - /* what we do is to set them all expired */ - inf.worker = worker; - inf.name = nm; - inf.len = nmlen; - inf.labs = nmlabs; - inf.expired = *worker->env.now; - inf.expired -= 3; /* handle 3 seconds skew between threads */ - inf.num_rrsets = 0; - inf.num_msgs = 0; - inf.num_keys = 0; - slabhash_traverse(&worker->env.rrset_cache->table, 1, - &zone_del_rrset, &inf); - - slabhash_traverse(worker->env.msg_cache, 1, &zone_del_msg, &inf); - - /* and validator cache */ - if(worker->env.key_cache) { - slabhash_traverse(worker->env.key_cache->slab, 1, - &zone_del_kcache, &inf); - } - - free(nm); - - (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " - "and %lu key entries\n", (unsigned long)inf.num_rrsets, - (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); -} - -/** callback to delete bogus rrsets */ -static void -bogus_del_rrset(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct packed_rrset_data* d = (struct packed_rrset_data*)e->data; - if(d->security == sec_status_bogus) { - d->ttl = inf->expired; - inf->num_rrsets++; - } -} - -/** callback to delete bogus messages */ -static void -bogus_del_msg(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct reply_info* d = (struct reply_info*)e->data; - if(d->security == sec_status_bogus) { - d->ttl = inf->expired; - inf->num_msgs++; - } -} - -/** callback to delete bogus keys */ -static void -bogus_del_kcache(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct key_entry_data* d = (struct key_entry_data*)e->data; - if(d->isbad) { - d->ttl = inf->expired; - inf->num_keys++; - } -} - -/** remove all bogus rrsets, msgs and keys from cache */ -static void -do_flush_bogus(RES* ssl, struct worker* worker) -{ - struct del_info inf; - /* what we do is to set them all expired */ - inf.worker = worker; - inf.expired = *worker->env.now; - inf.expired -= 3; /* handle 3 seconds skew between threads */ - inf.num_rrsets = 0; - inf.num_msgs = 0; - inf.num_keys = 0; - slabhash_traverse(&worker->env.rrset_cache->table, 1, - &bogus_del_rrset, &inf); - - slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf); - - /* and validator cache */ - if(worker->env.key_cache) { - slabhash_traverse(worker->env.key_cache->slab, 1, - &bogus_del_kcache, &inf); - } - - (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " - "and %lu key entries\n", (unsigned long)inf.num_rrsets, - (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); -} - -/** callback to delete negative and servfail rrsets */ -static void -negative_del_rrset(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key; - struct packed_rrset_data* d = (struct packed_rrset_data*)e->data; - /* delete the parentside negative cache rrsets, - * these are nameserver rrsets that failed lookup, rdata empty */ - if((k->rk.flags & PACKED_RRSET_PARENT_SIDE) && d->count == 1 && - d->rrsig_count == 0 && d->rr_len[0] == 0) { - d->ttl = inf->expired; - inf->num_rrsets++; - } -} - -/** callback to delete negative and servfail messages */ -static void -negative_del_msg(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct reply_info* d = (struct reply_info*)e->data; - /* rcode not NOERROR: NXDOMAIN, SERVFAIL, ..: an nxdomain or error - * or NOERROR rcode with ANCOUNT==0: a NODATA answer */ - if(FLAGS_GET_RCODE(d->flags) != 0 || d->an_numrrsets == 0) { - d->ttl = inf->expired; - inf->num_msgs++; - } -} - -/** callback to delete negative key entries */ -static void -negative_del_kcache(struct lruhash_entry* e, void* arg) -{ - /* entry is locked */ - struct del_info* inf = (struct del_info*)arg; - struct key_entry_data* d = (struct key_entry_data*)e->data; - /* could be bad because of lookup failure on the DS, DNSKEY, which - * was nxdomain or servfail, and thus a result of negative lookups */ - if(d->isbad) { - d->ttl = inf->expired; - inf->num_keys++; - } -} - -/** remove all negative(NODATA,NXDOMAIN), and servfail messages from cache */ -static void -do_flush_negative(RES* ssl, struct worker* worker) -{ - struct del_info inf; - /* what we do is to set them all expired */ - inf.worker = worker; - inf.expired = *worker->env.now; - inf.expired -= 3; /* handle 3 seconds skew between threads */ - inf.num_rrsets = 0; - inf.num_msgs = 0; - inf.num_keys = 0; - slabhash_traverse(&worker->env.rrset_cache->table, 1, - &negative_del_rrset, &inf); - - slabhash_traverse(worker->env.msg_cache, 1, &negative_del_msg, &inf); - - /* and validator cache */ - if(worker->env.key_cache) { - slabhash_traverse(worker->env.key_cache->slab, 1, - &negative_del_kcache, &inf); - } - - (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " - "and %lu key entries\n", (unsigned long)inf.num_rrsets, - (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); -} - -/** remove name rrset from cache */ -static void -do_flush_name(RES* ssl, struct worker* w, char* arg) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SVCB, LDNS_RR_CLASS_IN); - do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_HTTPS, LDNS_RR_CLASS_IN); - - free(nm); - send_ok(ssl); -} - -/** printout a delegation point info */ -static int -ssl_print_name_dp(RES* ssl, const char* str, uint8_t* nm, uint16_t dclass, - struct delegpt* dp) -{ - char buf[257]; - struct delegpt_ns* ns; - struct delegpt_addr* a; - int f = 0; - if(str) { /* print header for forward, stub */ - char* c = sldns_wire2str_class(dclass); - dname_str(nm, buf); - if(!ssl_printf(ssl, "%s %s %s ", buf, (c?c:"CLASS??"), str)) { - free(c); - return 0; - } - free(c); - } - for(ns = dp->nslist; ns; ns = ns->next) { - dname_str(ns->name, buf); - if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) - return 0; - f = 1; - } - for(a = dp->target_list; a; a = a->next_target) { - addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); - if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) - return 0; - f = 1; - } - return ssl_printf(ssl, "\n"); -} - - -/** print root forwards */ -static int -print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root) -{ - struct delegpt* dp; - dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN); - if(!dp) - return ssl_printf(ssl, "off (using root hints)\n"); - /* if dp is returned it must be the root */ - log_assert(query_dname_compare(dp->name, root)==0); - return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp); -} - -/** parse args into delegpt */ -static struct delegpt* -parse_delegpt(RES* ssl, char* args, uint8_t* nm) -{ - /* parse args and add in */ - char* p = args; - char* todo; - struct delegpt* dp = delegpt_create_mlc(nm); - struct sockaddr_storage addr; - socklen_t addrlen; - char* auth_name; - if(!dp) { - (void)ssl_printf(ssl, "error out of memory\n"); - return NULL; - } - while(p) { - todo = p; - p = strchr(p, ' '); /* find next spot, if any */ - if(p) { - *p++ = 0; /* end this spot */ - p = skipwhite(p); /* position at next spot */ - } - /* parse address */ - if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) { - uint8_t* dname= NULL; - int port; - dname = authextstrtodname(todo, &port, &auth_name); - if(!dname) { - (void)ssl_printf(ssl, "error cannot parse" - " '%s'\n", todo); - delegpt_free_mlc(dp); - return NULL; - } -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", todo); -#endif - if(!delegpt_add_ns_mlc(dp, dname, 0, auth_name, port)) { - (void)ssl_printf(ssl, "error out of memory\n"); - free(dname); - delegpt_free_mlc(dp); - return NULL; - } - } else { -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", todo); -#endif - /* add address */ - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, - auth_name, -1)) { - (void)ssl_printf(ssl, "error out of memory\n"); - delegpt_free_mlc(dp); - return NULL; - } - } - } - dp->has_parent_side_NS = 1; - return dp; -} - -/** do the status command */ -static void -do_forward(RES* ssl, struct worker* worker, char* args) -{ - struct iter_forwards* fwd = worker->env.fwds; - uint8_t* root = (uint8_t*)"\000"; - if(!fwd) { - (void)ssl_printf(ssl, "error: structure not allocated\n"); - return; - } - if(args == NULL || args[0] == 0) { - (void)print_root_fwds(ssl, fwd, root); - return; - } - /* set root forwards for this thread. since we are in remote control - * the actual mesh is not running, so we can freely edit it. */ - /* delete all the existing queries first */ - mesh_delete_all(worker->env.mesh); - if(strcmp(args, "off") == 0) { - forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root); - } else { - struct delegpt* dp; - if(!(dp = parse_delegpt(ssl, args, root))) - return; - if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) { - (void)ssl_printf(ssl, "error out of memory\n"); - return; - } - } - send_ok(ssl); -} - -static int -parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp, - int* insecure, int* prime) -{ - char* zonename; - char* rest; - size_t nmlen; - int nmlabs; - /* parse all -x args */ - while(args[0] == '+') { - if(!find_arg2(ssl, args, &rest)) - return 0; - while(*(++args) != 0) { - if(*args == 'i' && insecure) - *insecure = 1; - else if(*args == 'p' && prime) - *prime = 1; - else { - (void)ssl_printf(ssl, "error: unknown option %s\n", args); - return 0; - } - } - args = rest; - } - /* parse name */ - if(dp) { - if(!find_arg2(ssl, args, &rest)) - return 0; - zonename = args; - args = rest; - } else zonename = args; - if(!parse_arg_name(ssl, zonename, nm, &nmlen, &nmlabs)) - return 0; - - /* parse dp */ - if(dp) { - if(!(*dp = parse_delegpt(ssl, args, *nm))) { - free(*nm); - return 0; - } - } - return 1; -} - -/** do the forward_add command */ -static void -do_forward_add(RES* ssl, struct worker* worker, char* args) -{ - struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0; - uint8_t* nm = NULL; - struct delegpt* dp = NULL; - if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL)) - return; - if(insecure && worker->env.anchors) { - if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, - nm)) { - (void)ssl_printf(ssl, "error out of memory\n"); - delegpt_free_mlc(dp); - free(nm); - return; - } - } - if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) { - (void)ssl_printf(ssl, "error out of memory\n"); - free(nm); - return; - } - free(nm); - send_ok(ssl); -} - -/** do the forward_remove command */ -static void -do_forward_remove(RES* ssl, struct worker* worker, char* args) -{ - struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0; - uint8_t* nm = NULL; - if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) - return; - if(insecure && worker->env.anchors) - anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, - nm); - forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm); - free(nm); - send_ok(ssl); -} - -/** do the stub_add command */ -static void -do_stub_add(RES* ssl, struct worker* worker, char* args) -{ - struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0, prime = 0; - uint8_t* nm = NULL; - struct delegpt* dp = NULL; - if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime)) - return; - if(insecure && worker->env.anchors) { - if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, - nm)) { - (void)ssl_printf(ssl, "error out of memory\n"); - delegpt_free_mlc(dp); - free(nm); - return; - } - } - if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) { - if(insecure && worker->env.anchors) - anchors_delete_insecure(worker->env.anchors, - LDNS_RR_CLASS_IN, nm); - (void)ssl_printf(ssl, "error out of memory\n"); - delegpt_free_mlc(dp); - free(nm); - return; - } - if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) { - (void)ssl_printf(ssl, "error out of memory\n"); - forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm); - if(insecure && worker->env.anchors) - anchors_delete_insecure(worker->env.anchors, - LDNS_RR_CLASS_IN, nm); - free(nm); - return; - } - free(nm); - send_ok(ssl); -} - -/** do the stub_remove command */ -static void -do_stub_remove(RES* ssl, struct worker* worker, char* args) -{ - struct iter_forwards* fwd = worker->env.fwds; - int insecure = 0; - uint8_t* nm = NULL; - if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) - return; - if(insecure && worker->env.anchors) - anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, - nm); - forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm); - hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm); - free(nm); - send_ok(ssl); -} - -/** do the insecure_add command */ -static void -do_insecure_add(RES* ssl, struct worker* worker, char* arg) -{ - size_t nmlen; - int nmlabs; - uint8_t* nm = NULL; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - if(worker->env.anchors) { - if(!anchors_add_insecure(worker->env.anchors, - LDNS_RR_CLASS_IN, nm)) { - (void)ssl_printf(ssl, "error out of memory\n"); - free(nm); - return; - } - } - free(nm); - send_ok(ssl); -} - -/** do the insecure_remove command */ -static void -do_insecure_remove(RES* ssl, struct worker* worker, char* arg) -{ - size_t nmlen; - int nmlabs; - uint8_t* nm = NULL; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - if(worker->env.anchors) - anchors_delete_insecure(worker->env.anchors, - LDNS_RR_CLASS_IN, nm); - free(nm); - send_ok(ssl); -} - -static void -do_insecure_list(RES* ssl, struct worker* worker) -{ - char buf[257]; - struct trust_anchor* a; - if(worker->env.anchors) { - RBTREE_FOR(a, struct trust_anchor*, worker->env.anchors->tree) { - if(a->numDS == 0 && a->numDNSKEY == 0) { - dname_str(a->name, buf); - ssl_printf(ssl, "%s\n", buf); - } - } - } -} - -/** do the status command */ -static void -do_status(RES* ssl, struct worker* worker) -{ - int i; - time_t uptime; - if(!ssl_printf(ssl, "version: %s\n", PACKAGE_VERSION)) - return; - if(!ssl_printf(ssl, "verbosity: %d\n", verbosity)) - return; - if(!ssl_printf(ssl, "threads: %d\n", worker->daemon->num)) - return; - if(!ssl_printf(ssl, "modules: %d [", worker->daemon->mods.num)) - return; - for(i=0; idaemon->mods.num; i++) { - if(!ssl_printf(ssl, " %s", worker->daemon->mods.mod[i]->name)) - return; - } - if(!ssl_printf(ssl, " ]\n")) - return; - uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec; - if(!ssl_printf(ssl, "uptime: " ARG_LL "d seconds\n", (long long)uptime)) - return; - if(!ssl_printf(ssl, "options:%s%s%s%s\n" , - (worker->daemon->reuseport?" reuseport":""), - (worker->daemon->rc->accept_list?" control":""), - (worker->daemon->rc->accept_list && worker->daemon->rc->use_cert?"(ssl)":""), - (worker->daemon->rc->accept_list && worker->daemon->cfg->control_ifs.first && worker->daemon->cfg->control_ifs.first->str && worker->daemon->cfg->control_ifs.first->str[0] == '/'?"(namedpipe)":"") - )) - return; - if(!ssl_printf(ssl, "unbound (pid %d) is running...\n", - (int)getpid())) - return; -} - -/** get age for the mesh state */ -static void -get_mesh_age(struct mesh_state* m, char* buf, size_t len, - struct module_env* env) -{ - if(m->reply_list) { - struct timeval d; - struct mesh_reply* r = m->reply_list; - /* last reply is the oldest */ - while(r && r->next) - r = r->next; - timeval_subtract(&d, env->now_tv, &r->start_time); - snprintf(buf, len, ARG_LL "d.%6.6d", - (long long)d.tv_sec, (int)d.tv_usec); - } else { - snprintf(buf, len, "-"); - } -} - -/** get status of a mesh state */ -static void -get_mesh_status(struct mesh_area* mesh, struct mesh_state* m, - char* buf, size_t len) -{ - enum module_ext_state s = m->s.ext_state[m->s.curmod]; - const char *modname = mesh->mods.mod[m->s.curmod]->name; - size_t l; - if(strcmp(modname, "iterator") == 0 && s == module_wait_reply && - m->s.minfo[m->s.curmod]) { - /* break into iterator to find out who its waiting for */ - struct iter_qstate* qstate = (struct iter_qstate*) - m->s.minfo[m->s.curmod]; - struct outbound_list* ol = &qstate->outlist; - struct outbound_entry* e; - snprintf(buf, len, "%s wait for", modname); - l = strlen(buf); - buf += l; len -= l; - if(ol->first == NULL) - snprintf(buf, len, " (empty_list)"); - for(e = ol->first; e; e = e->next) { - snprintf(buf, len, " "); - l = strlen(buf); - buf += l; len -= l; - addr_to_str(&e->qsent->addr, e->qsent->addrlen, - buf, len); - l = strlen(buf); - buf += l; len -= l; - } - } else if(s == module_wait_subquery) { - /* look in subs from mesh state to see what */ - char nm[257]; - struct mesh_state_ref* sub; - snprintf(buf, len, "%s wants", modname); - l = strlen(buf); - buf += l; len -= l; - if(m->sub_set.count == 0) - snprintf(buf, len, " (empty_list)"); - RBTREE_FOR(sub, struct mesh_state_ref*, &m->sub_set) { - char* t = sldns_wire2str_type(sub->s->s.qinfo.qtype); - char* c = sldns_wire2str_class(sub->s->s.qinfo.qclass); - dname_str(sub->s->s.qinfo.qname, nm); - snprintf(buf, len, " %s %s %s", (t?t:"TYPE??"), - (c?c:"CLASS??"), nm); - l = strlen(buf); - buf += l; len -= l; - free(t); - free(c); - } - } else { - snprintf(buf, len, "%s is %s", modname, strextstate(s)); - } -} - -/** do the dump_requestlist command */ -static void -do_dump_requestlist(RES* ssl, struct worker* worker) -{ - struct mesh_area* mesh; - struct mesh_state* m; - int num = 0; - char buf[257]; - char timebuf[32]; - char statbuf[10240]; - if(!ssl_printf(ssl, "thread #%d\n", worker->thread_num)) - return; - if(!ssl_printf(ssl, "# type cl name seconds module status\n")) - return; - /* show worker mesh contents */ - mesh = worker->env.mesh; - if(!mesh) return; - RBTREE_FOR(m, struct mesh_state*, &mesh->all) { - char* t = sldns_wire2str_type(m->s.qinfo.qtype); - char* c = sldns_wire2str_class(m->s.qinfo.qclass); - dname_str(m->s.qinfo.qname, buf); - get_mesh_age(m, timebuf, sizeof(timebuf), &worker->env); - get_mesh_status(mesh, m, statbuf, sizeof(statbuf)); - if(!ssl_printf(ssl, "%3d %4s %2s %s %s %s\n", - num, (t?t:"TYPE??"), (c?c:"CLASS??"), buf, timebuf, - statbuf)) { - free(t); - free(c); - return; - } - num++; - free(t); - free(c); - } -} - -/** structure for argument data for dump infra host */ -struct infra_arg { - /** the infra cache */ - struct infra_cache* infra; - /** the SSL connection */ - RES* ssl; - /** the time now */ - time_t now; - /** ssl failure? stop writing and skip the rest. If the tcp - * connection is broken, and writes fail, we then stop writing. */ - int ssl_failed; -}; - -/** callback for every host element in the infra cache */ -static void -dump_infra_host(struct lruhash_entry* e, void* arg) -{ - struct infra_arg* a = (struct infra_arg*)arg; - struct infra_key* k = (struct infra_key*)e->key; - struct infra_data* d = (struct infra_data*)e->data; - char ip_str[1024]; - char name[257]; - int port; - if(a->ssl_failed) - return; - addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str)); - dname_str(k->zonename, name); - port = (int)ntohs(((struct sockaddr_in*)&k->addr)->sin_port); - if(port != UNBOUND_DNS_PORT) { - snprintf(ip_str+strlen(ip_str), sizeof(ip_str)-strlen(ip_str), - "@%d", port); - } - /* skip expired stuff (only backed off) */ - if(d->ttl < a->now) { - if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) { - if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str, - name, d->rtt.rto)) { - a->ssl_failed = 1; - return; - } - } - return; - } - if(!ssl_printf(a->ssl, "%s %s ttl %lu ping %d var %d rtt %d rto %d " - "tA %d tAAAA %d tother %d " - "ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d " - "other %d\n", ip_str, name, (unsigned long)(d->ttl - a->now), - d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, - d->timeout_A, d->timeout_AAAA, d->timeout_other, - (int)d->edns_lame_known, (int)d->edns_version, - (int)(a->nowprobedelay?(d->probedelay - a->now):0), - (int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A, - (int)d->lame_other)) { - a->ssl_failed = 1; - return; - } -} - -/** do the dump_infra command */ -static void -do_dump_infra(RES* ssl, struct worker* worker) -{ - struct infra_arg arg; - arg.infra = worker->env.infra_cache; - arg.ssl = ssl; - arg.now = *worker->env.now; - arg.ssl_failed = 0; - slabhash_traverse(arg.infra->hosts, 0, &dump_infra_host, (void*)&arg); -} - -/** do the log_reopen command */ -static void -do_log_reopen(RES* ssl, struct worker* worker) -{ - struct config_file* cfg = worker->env.cfg; - send_ok(ssl); - log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); -} - -/** do the auth_zone_reload command */ -static void -do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg) -{ - size_t nmlen; - int nmlabs; - uint8_t* nm = NULL; - struct auth_zones* az = worker->env.auth_zones; - struct auth_zone* z = NULL; - struct auth_xfer* xfr = NULL; - char* reason = NULL; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - if(az) { - lock_rw_rdlock(&az->lock); - z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN); - if(z) { - lock_rw_wrlock(&z->lock); - } - xfr = auth_xfer_find(az, nm, nmlen, LDNS_RR_CLASS_IN); - if(xfr) { - lock_basic_lock(&xfr->lock); - } - lock_rw_unlock(&az->lock); - } - free(nm); - if(!z) { - if(xfr) { - lock_basic_unlock(&xfr->lock); - } - (void)ssl_printf(ssl, "error no auth-zone %s\n", arg); - return; - } - if(!auth_zone_read_zonefile(z, worker->env.cfg)) { - lock_rw_unlock(&z->lock); - if(xfr) { - lock_basic_unlock(&xfr->lock); - } - (void)ssl_printf(ssl, "error failed to read %s\n", arg); - return; - } - - z->zone_expired = 0; - if(xfr) { - xfr->zone_expired = 0; - if(!xfr_find_soa(z, xfr)) { - if(z->data.count == 0) { - lock_rw_unlock(&z->lock); - lock_basic_unlock(&xfr->lock); - (void)ssl_printf(ssl, "zone %s has no contents\n", arg); - return; - } - lock_rw_unlock(&z->lock); - lock_basic_unlock(&xfr->lock); - (void)ssl_printf(ssl, "error: no SOA in zone after read %s\n", arg); - return; - } - if(xfr->have_zone) - xfr->lease_time = *worker->env.now; - lock_basic_unlock(&xfr->lock); - } - - auth_zone_verify_zonemd(z, &worker->env, &worker->env.mesh->mods, - &reason, 0, 0); - if(reason && z->zone_expired) { - lock_rw_unlock(&z->lock); - (void)ssl_printf(ssl, "error zonemd for %s failed: %s\n", - arg, reason); - free(reason); - return; - } else if(reason && strcmp(reason, "ZONEMD verification successful") - ==0) { - (void)ssl_printf(ssl, "%s: %s\n", arg, reason); - } - lock_rw_unlock(&z->lock); - free(reason); - send_ok(ssl); -} - -/** do the auth_zone_transfer command */ -static void -do_auth_zone_transfer(RES* ssl, struct worker* worker, char* arg) -{ - size_t nmlen; - int nmlabs; - uint8_t* nm = NULL; - struct auth_zones* az = worker->env.auth_zones; - if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - if(!az || !auth_zones_startprobesequence(az, &worker->env, nm, nmlen, - LDNS_RR_CLASS_IN)) { - (void)ssl_printf(ssl, "error zone xfr task not found %s\n", arg); - free(nm); - return; - } - free(nm); - send_ok(ssl); -} - -/** do the set_option command */ -static void -do_set_option(RES* ssl, struct worker* worker, char* arg) -{ - char* arg2; - if(!find_arg2(ssl, arg, &arg2)) - return; - if(!config_set_option(worker->env.cfg, arg, arg2)) { - (void)ssl_printf(ssl, "error setting option\n"); - return; - } - /* effectuate some arguments */ - if(strcmp(arg, "val-override-date:") == 0) { - int m = modstack_find(&worker->env.mesh->mods, "validator"); - struct val_env* val_env = NULL; - if(m != -1) val_env = (struct val_env*)worker->env.modinfo[m]; - if(val_env) - val_env->date_override = worker->env.cfg->val_date_override; - } - send_ok(ssl); -} - -/* routine to printout option values over SSL */ -void remote_get_opt_ssl(char* line, void* arg) -{ - RES* ssl = (RES*)arg; - (void)ssl_printf(ssl, "%s\n", line); -} - -/** do the get_option command */ -static void -do_get_option(RES* ssl, struct worker* worker, char* arg) -{ - int r; - r = config_get_option(worker->env.cfg, arg, remote_get_opt_ssl, ssl); - if(!r) { - (void)ssl_printf(ssl, "error unknown option\n"); - return; - } -} - -/** do the list_forwards command */ -static void -do_list_forwards(RES* ssl, struct worker* worker) -{ - /* since its a per-worker structure no locks needed */ - struct iter_forwards* fwds = worker->env.fwds; - struct iter_forward_zone* z; - struct trust_anchor* a; - int insecure; - RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) { - if(!z->dp) continue; /* skip empty marker for stub */ - - /* see if it is insecure */ - insecure = 0; - if(worker->env.anchors && - (a=anchor_find(worker->env.anchors, z->name, - z->namelabs, z->namelen, z->dclass))) { - if(!a->keylist && !a->numDS && !a->numDNSKEY) - insecure = 1; - lock_basic_unlock(&a->lock); - } - - if(!ssl_print_name_dp(ssl, (insecure?"forward +i":"forward"), - z->name, z->dclass, z->dp)) - return; - } -} - -/** do the list_stubs command */ -static void -do_list_stubs(RES* ssl, struct worker* worker) -{ - struct iter_hints_stub* z; - struct trust_anchor* a; - int insecure; - char str[32]; - RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) { - - /* see if it is insecure */ - insecure = 0; - if(worker->env.anchors && - (a=anchor_find(worker->env.anchors, z->node.name, - z->node.labs, z->node.len, z->node.dclass))) { - if(!a->keylist && !a->numDS && !a->numDNSKEY) - insecure = 1; - lock_basic_unlock(&a->lock); - } - - snprintf(str, sizeof(str), "stub %sprime%s", - (z->noprime?"no":""), (insecure?" +i":"")); - if(!ssl_print_name_dp(ssl, str, z->node.name, - z->node.dclass, z->dp)) - return; - } -} - -/** do the list_auth_zones command */ -static void -do_list_auth_zones(RES* ssl, struct auth_zones* az) -{ - struct auth_zone* z; - char buf[257], buf2[256]; - lock_rw_rdlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_rdlock(&z->lock); - dname_str(z->name, buf); - if(z->zone_expired) - snprintf(buf2, sizeof(buf2), "expired"); - else { - uint32_t serial = 0; - if(auth_zone_get_serial(z, &serial)) - snprintf(buf2, sizeof(buf2), "serial %u", - (unsigned)serial); - else snprintf(buf2, sizeof(buf2), "no serial"); - } - if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) { - /* failure to print */ - lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); - return; - } - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&az->lock); -} - -/** do the list_local_zones command */ -static void -do_list_local_zones(RES* ssl, struct local_zones* zones) -{ - struct local_zone* z; - char buf[257]; - lock_rw_rdlock(&zones->lock); - RBTREE_FOR(z, struct local_zone*, &zones->ztree) { - lock_rw_rdlock(&z->lock); - dname_str(z->name, buf); - if(!ssl_printf(ssl, "%s %s\n", buf, - local_zone_type2str(z->type))) { - /* failure to print */ - lock_rw_unlock(&z->lock); - lock_rw_unlock(&zones->lock); - return; - } - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&zones->lock); -} - -/** do the list_local_data command */ -static void -do_list_local_data(RES* ssl, struct worker* worker, struct local_zones* zones) -{ - struct local_zone* z; - struct local_data* d; - struct local_rrset* p; - char* s = (char*)sldns_buffer_begin(worker->env.scratch_buffer); - size_t slen = sldns_buffer_capacity(worker->env.scratch_buffer); - lock_rw_rdlock(&zones->lock); - RBTREE_FOR(z, struct local_zone*, &zones->ztree) { - lock_rw_rdlock(&z->lock); - RBTREE_FOR(d, struct local_data*, &z->data) { - for(p = d->rrsets; p; p = p->next) { - struct packed_rrset_data* d = - (struct packed_rrset_data*)p->rrset->entry.data; - size_t i; - for(i=0; icount + d->rrsig_count; i++) { - if(!packed_rr_to_string(p->rrset, i, - 0, s, slen)) { - if(!ssl_printf(ssl, "BADRR\n")) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&zones->lock); - return; - } - } - if(!ssl_printf(ssl, "%s\n", s)) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&zones->lock); - return; - } - } - } - } - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&zones->lock); -} - -/** do the view_list_local_zones command */ -static void -do_view_list_local_zones(RES* ssl, struct worker* worker, char* arg) -{ - struct view* v = views_find_view(worker->daemon->views, - arg, 0 /* get read lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(v->local_zones) { - do_list_local_zones(ssl, v->local_zones); - } - lock_rw_unlock(&v->lock); -} - -/** do the view_list_local_data command */ -static void -do_view_list_local_data(RES* ssl, struct worker* worker, char* arg) -{ - struct view* v = views_find_view(worker->daemon->views, - arg, 0 /* get read lock*/); - if(!v) { - ssl_printf(ssl,"no view with name: %s\n", arg); - return; - } - if(v->local_zones) { - do_list_local_data(ssl, worker, v->local_zones); - } - lock_rw_unlock(&v->lock); -} - -/** struct for user arg ratelimit list */ -struct ratelimit_list_arg { - /** the infra cache */ - struct infra_cache* infra; - /** the SSL to print to */ - RES* ssl; - /** all or only ratelimited */ - int all; - /** current time */ - time_t now; - /** if backoff is enabled */ - int backoff; -}; - -#define ip_ratelimit_list_arg ratelimit_list_arg - -/** list items in the ratelimit table */ -static void -rate_list(struct lruhash_entry* e, void* arg) -{ - struct ratelimit_list_arg* a = (struct ratelimit_list_arg*)arg; - struct rate_key* k = (struct rate_key*)e->key; - struct rate_data* d = (struct rate_data*)e->data; - char buf[257]; - int lim = infra_find_ratelimit(a->infra, k->name, k->namelen); - int max = infra_rate_max(d, a->now, a->backoff); - if(a->all == 0) { - if(max < lim) - return; - } - dname_str(k->name, buf); - ssl_printf(a->ssl, "%s %d limit %d\n", buf, max, lim); -} - -/** list items in the ip_ratelimit table */ -static void -ip_rate_list(struct lruhash_entry* e, void* arg) -{ - char ip[128]; - struct ip_ratelimit_list_arg* a = (struct ip_ratelimit_list_arg*)arg; - struct ip_rate_key* k = (struct ip_rate_key*)e->key; - struct ip_rate_data* d = (struct ip_rate_data*)e->data; - int lim = infra_ip_ratelimit; - int max = infra_rate_max(d, a->now, a->backoff); - if(a->all == 0) { - if(max < lim) - return; - } - addr_to_str(&k->addr, k->addrlen, ip, sizeof(ip)); - ssl_printf(a->ssl, "%s %d limit %d\n", ip, max, lim); -} - -/** do the ratelimit_list command */ -static void -do_ratelimit_list(RES* ssl, struct worker* worker, char* arg) -{ - struct ratelimit_list_arg a; - a.all = 0; - a.infra = worker->env.infra_cache; - a.now = *worker->env.now; - a.ssl = ssl; - a.backoff = worker->env.cfg->ratelimit_backoff; - arg = skipwhite(arg); - if(strcmp(arg, "+a") == 0) - a.all = 1; - if(a.infra->domain_rates==NULL || - (a.all == 0 && infra_dp_ratelimit == 0)) - return; - slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a); -} - -/** do the ip_ratelimit_list command */ -static void -do_ip_ratelimit_list(RES* ssl, struct worker* worker, char* arg) -{ - struct ip_ratelimit_list_arg a; - a.all = 0; - a.infra = worker->env.infra_cache; - a.now = *worker->env.now; - a.ssl = ssl; - a.backoff = worker->env.cfg->ip_ratelimit_backoff; - arg = skipwhite(arg); - if(strcmp(arg, "+a") == 0) - a.all = 1; - if(a.infra->client_ip_rates==NULL || - (a.all == 0 && infra_ip_ratelimit == 0)) - return; - slabhash_traverse(a.infra->client_ip_rates, 0, ip_rate_list, &a); -} - -/** do the rpz_enable/disable command */ -static void -do_rpz_enable_disable(RES* ssl, struct worker* worker, char* arg, int enable) { - size_t nmlen; - int nmlabs; - uint8_t *nm = NULL; - struct auth_zones *az = worker->env.auth_zones; - struct auth_zone *z = NULL; - if (!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; - if (az) { - lock_rw_rdlock(&az->lock); - z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN); - if (z) { - lock_rw_wrlock(&z->lock); - } - lock_rw_unlock(&az->lock); - } - free(nm); - if (!z) { - (void) ssl_printf(ssl, "error no auth-zone %s\n", arg); - return; - } - if (!z->rpz) { - (void) ssl_printf(ssl, "error auth-zone %s not RPZ\n", arg); - lock_rw_unlock(&z->lock); - return; - } - if (enable) { - rpz_enable(z->rpz); - } else { - rpz_disable(z->rpz); - } - lock_rw_unlock(&z->lock); - send_ok(ssl); -} - -/** do the rpz_enable command */ -static void -do_rpz_enable(RES* ssl, struct worker* worker, char* arg) -{ - do_rpz_enable_disable(ssl, worker, arg, 1); -} - -/** do the rpz_disable command */ -static void -do_rpz_disable(RES* ssl, struct worker* worker, char* arg) -{ - do_rpz_enable_disable(ssl, worker, arg, 0); -} - -/** tell other processes to execute the command */ -static void -distribute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd) -{ - int i; - if(!cmd || !ssl) - return; - /* skip i=0 which is me */ - for(i=1; iworker->daemon->num; i++) { - worker_send_cmd(rc->worker->daemon->workers[i], - worker_cmd_remote); - if(!tube_write_msg(rc->worker->daemon->workers[i]->cmd, - (uint8_t*)cmd, strlen(cmd)+1, 0)) { - ssl_printf(ssl, "error could not distribute cmd\n"); - return; - } - } -} - -/** check for name with end-of-string, space or tab after it */ -static int -cmdcmp(char* p, const char* cmd, size_t len) -{ - return strncmp(p,cmd,len)==0 && (p[len]==0||p[len]==' '||p[len]=='\t'); -} - -/** execute a remote control command */ -static void -execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd, - struct worker* worker) -{ - char* p = skipwhite(cmd); - /* compare command */ - if(cmdcmp(p, "stop", 4)) { - do_stop(ssl, worker); - return; - } else if(cmdcmp(p, "reload_keep_cache", 17)) { - do_reload(ssl, worker, 1); - return; - } else if(cmdcmp(p, "reload", 6)) { - do_reload(ssl, worker, 0); - return; - } else if(cmdcmp(p, "stats_noreset", 13)) { - do_stats(ssl, worker, 0); - return; - } else if(cmdcmp(p, "stats", 5)) { - do_stats(ssl, worker, 1); - return; - } else if(cmdcmp(p, "status", 6)) { - do_status(ssl, worker); - return; - } else if(cmdcmp(p, "dump_cache", 10)) { - (void)dump_cache(ssl, worker); - return; - } else if(cmdcmp(p, "load_cache", 10)) { - if(load_cache(ssl, worker)) send_ok(ssl); - return; - } else if(cmdcmp(p, "list_forwards", 13)) { - do_list_forwards(ssl, worker); - return; - } else if(cmdcmp(p, "list_stubs", 10)) { - do_list_stubs(ssl, worker); - return; - } else if(cmdcmp(p, "list_insecure", 13)) { - do_insecure_list(ssl, worker); - return; - } else if(cmdcmp(p, "list_local_zones", 16)) { - do_list_local_zones(ssl, worker->daemon->local_zones); - return; - } else if(cmdcmp(p, "list_local_data", 15)) { - do_list_local_data(ssl, worker, worker->daemon->local_zones); - return; - } else if(cmdcmp(p, "view_list_local_zones", 21)) { - do_view_list_local_zones(ssl, worker, skipwhite(p+21)); - return; - } else if(cmdcmp(p, "view_list_local_data", 20)) { - do_view_list_local_data(ssl, worker, skipwhite(p+20)); - return; - } else if(cmdcmp(p, "ratelimit_list", 14)) { - do_ratelimit_list(ssl, worker, p+14); - return; - } else if(cmdcmp(p, "ip_ratelimit_list", 17)) { - do_ip_ratelimit_list(ssl, worker, p+17); - return; - } else if(cmdcmp(p, "list_auth_zones", 15)) { - do_list_auth_zones(ssl, worker->env.auth_zones); - return; - } else if(cmdcmp(p, "auth_zone_reload", 16)) { - do_auth_zone_reload(ssl, worker, skipwhite(p+16)); - return; - } else if(cmdcmp(p, "auth_zone_transfer", 18)) { - do_auth_zone_transfer(ssl, worker, skipwhite(p+18)); - return; - } else if(cmdcmp(p, "stub_add", 8)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_stub_add(ssl, worker, skipwhite(p+8)); - return; - } else if(cmdcmp(p, "stub_remove", 11)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_stub_remove(ssl, worker, skipwhite(p+11)); - return; - } else if(cmdcmp(p, "forward_add", 11)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_forward_add(ssl, worker, skipwhite(p+11)); - return; - } else if(cmdcmp(p, "forward_remove", 14)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_forward_remove(ssl, worker, skipwhite(p+14)); - return; - } else if(cmdcmp(p, "insecure_add", 12)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_insecure_add(ssl, worker, skipwhite(p+12)); - return; - } else if(cmdcmp(p, "insecure_remove", 15)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_insecure_remove(ssl, worker, skipwhite(p+15)); - return; - } else if(cmdcmp(p, "forward", 7)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_forward(ssl, worker, skipwhite(p+7)); - return; - } else if(cmdcmp(p, "flush_stats", 11)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_flush_stats(ssl, worker); - return; - } else if(cmdcmp(p, "flush_requestlist", 17)) { - /* must always distribute this cmd */ - if(rc) distribute_cmd(rc, ssl, cmd); - do_flush_requestlist(ssl, worker); - return; - } else if(cmdcmp(p, "lookup", 6)) { - do_lookup(ssl, worker, skipwhite(p+6)); - return; - } - -#ifdef THREADS_DISABLED - /* other processes must execute the command as well */ - /* commands that should not be distributed, returned above. */ - if(rc) { /* only if this thread is the master (rc) thread */ - /* done before the code below, which may split the string */ - distribute_cmd(rc, ssl, cmd); - } -#endif - if(cmdcmp(p, "verbosity", 9)) { - do_verbosity(ssl, skipwhite(p+9)); - } else if(cmdcmp(p, "local_zone_remove", 17)) { - do_zone_remove(ssl, worker->daemon->local_zones, skipwhite(p+17)); - } else if(cmdcmp(p, "local_zones_remove", 18)) { - do_zones_remove(ssl, worker->daemon->local_zones); - } else if(cmdcmp(p, "local_zone", 10)) { - do_zone_add(ssl, worker->daemon->local_zones, skipwhite(p+10)); - } else if(cmdcmp(p, "local_zones", 11)) { - do_zones_add(ssl, worker->daemon->local_zones); - } else if(cmdcmp(p, "local_data_remove", 17)) { - do_data_remove(ssl, worker->daemon->local_zones, skipwhite(p+17)); - } else if(cmdcmp(p, "local_datas_remove", 18)) { - do_datas_remove(ssl, worker->daemon->local_zones); - } else if(cmdcmp(p, "local_data", 10)) { - do_data_add(ssl, worker->daemon->local_zones, skipwhite(p+10)); - } else if(cmdcmp(p, "local_datas", 11)) { - do_datas_add(ssl, worker->daemon->local_zones); - } else if(cmdcmp(p, "view_local_zone_remove", 22)) { - do_view_zone_remove(ssl, worker, skipwhite(p+22)); - } else if(cmdcmp(p, "view_local_zone", 15)) { - do_view_zone_add(ssl, worker, skipwhite(p+15)); - } else if(cmdcmp(p, "view_local_data_remove", 22)) { - do_view_data_remove(ssl, worker, skipwhite(p+22)); - } else if(cmdcmp(p, "view_local_datas_remove", 23)){ - do_view_datas_remove(ssl, worker, skipwhite(p+23)); - } else if(cmdcmp(p, "view_local_data", 15)) { - do_view_data_add(ssl, worker, skipwhite(p+15)); - } else if(cmdcmp(p, "view_local_datas", 16)) { - do_view_datas_add(ssl, worker, skipwhite(p+16)); - } else if(cmdcmp(p, "flush_zone", 10)) { - do_flush_zone(ssl, worker, skipwhite(p+10)); - } else if(cmdcmp(p, "flush_type", 10)) { - do_flush_type(ssl, worker, skipwhite(p+10)); - } else if(cmdcmp(p, "flush_infra", 11)) { - do_flush_infra(ssl, worker, skipwhite(p+11)); - } else if(cmdcmp(p, "flush", 5)) { - do_flush_name(ssl, worker, skipwhite(p+5)); - } else if(cmdcmp(p, "dump_requestlist", 16)) { - do_dump_requestlist(ssl, worker); - } else if(cmdcmp(p, "dump_infra", 10)) { - do_dump_infra(ssl, worker); - } else if(cmdcmp(p, "log_reopen", 10)) { - do_log_reopen(ssl, worker); - } else if(cmdcmp(p, "set_option", 10)) { - do_set_option(ssl, worker, skipwhite(p+10)); - } else if(cmdcmp(p, "get_option", 10)) { - do_get_option(ssl, worker, skipwhite(p+10)); - } else if(cmdcmp(p, "flush_bogus", 11)) { - do_flush_bogus(ssl, worker); - } else if(cmdcmp(p, "flush_negative", 14)) { - do_flush_negative(ssl, worker); - } else if(cmdcmp(p, "rpz_enable", 10)) { - do_rpz_enable(ssl, worker, skipwhite(p+10)); - } else if(cmdcmp(p, "rpz_disable", 11)) { - do_rpz_disable(ssl, worker, skipwhite(p+11)); - } else { - (void)ssl_printf(ssl, "error unknown command '%s'\n", p); - } -} - -void -daemon_remote_exec(struct worker* worker) -{ - /* read the cmd string */ - uint8_t* msg = NULL; - uint32_t len = 0; - if(!tube_read_msg(worker->cmd, &msg, &len, 0)) { - log_err("daemon_remote_exec: tube_read_msg failed"); - return; - } - verbose(VERB_ALGO, "remote exec distributed: %s", (char*)msg); - execute_cmd(NULL, NULL, (char*)msg, worker); - free(msg); -} - -/** handle remote control request */ -static void -handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res) -{ - int r; - char pre[10]; - char magic[7]; - char buf[1024]; -#ifdef USE_WINSOCK - /* makes it possible to set the socket blocking again. */ - /* basically removes it from winsock_event ... */ - WSAEventSelect(s->c->fd, NULL, 0); -#endif - fd_set_block(s->c->fd); - - /* try to read magic UBCT[version]_space_ string */ - if(res->ssl) { - ERR_clear_error(); - if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) - return; - log_crypto_err("could not SSL_read"); - return; - } - } else { - while(1) { - ssize_t rr = recv(res->fd, magic, sizeof(magic)-1, 0); - if(rr <= 0) { - if(rr == 0) return; - if(errno == EINTR || errno == EAGAIN) - continue; - log_err("could not recv: %s", sock_strerror(errno)); - return; - } - r = (int)rr; - break; - } - } - magic[6] = 0; - if( r != 6 || strncmp(magic, "UBCT", 4) != 0) { - verbose(VERB_QUERY, "control connection has bad magic string"); - /* probably wrong tool connected, ignore it completely */ - return; - } - - /* read the command line */ - if(!ssl_read_line(res, buf, sizeof(buf))) { - return; - } - snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION); - if(strcmp(magic, pre) != 0) { - verbose(VERB_QUERY, "control connection had bad " - "version %s, cmd: %s", magic, buf); - ssl_printf(res, "error version mismatch\n"); - return; - } - verbose(VERB_DETAIL, "control cmd: %s", buf); - - /* figure out what to do */ - execute_cmd(rc, res, buf, rc->worker); -} - -/** handle SSL_do_handshake changes to the file descriptor to wait for later */ -static int -remote_handshake_later(struct daemon_remote* rc, struct rc_state* s, - struct comm_point* c, int r, int r2) -{ - if(r2 == SSL_ERROR_WANT_READ) { - if(s->shake_state == rc_hs_read) { - /* try again later */ - return 0; - } - s->shake_state = rc_hs_read; - comm_point_listen_for_rw(c, 1, 0); - return 0; - } else if(r2 == SSL_ERROR_WANT_WRITE) { - if(s->shake_state == rc_hs_write) { - /* try again later */ - return 0; - } - s->shake_state = rc_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 0; - } else { - if(r == 0) - log_err("remote control connection closed prematurely"); - log_addr(VERB_OPS, "failed connection from", - &s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen); - log_crypto_err("remote control failed ssl"); - clean_point(rc, s); - } - return 0; -} - -int remote_control_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* ATTR_UNUSED(rep)) -{ - RES res; - struct rc_state* s = (struct rc_state*)arg; - struct daemon_remote* rc = s->rc; - int r; - if(err != NETEVENT_NOERROR) { - if(err==NETEVENT_TIMEOUT) - log_err("remote control timed out"); - clean_point(rc, s); - return 0; - } - if(s->ssl) { - /* (continue to) setup the SSL connection */ - ERR_clear_error(); - r = SSL_do_handshake(s->ssl); - if(r != 1) { - int r2 = SSL_get_error(s->ssl, r); - return remote_handshake_later(rc, s, c, r, r2); - } - s->shake_state = rc_none; - } - - /* once handshake has completed, check authentication */ - if (!rc->use_cert) { - verbose(VERB_ALGO, "unauthenticated remote control connection"); - } else if(SSL_get_verify_result(s->ssl) == X509_V_OK) { -#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE - X509* x = SSL_get1_peer_certificate(s->ssl); -#else - X509* x = SSL_get_peer_certificate(s->ssl); -#endif - if(!x) { - verbose(VERB_DETAIL, "remote control connection " - "provided no client certificate"); - clean_point(rc, s); - return 0; - } - verbose(VERB_ALGO, "remote control connection authenticated"); - X509_free(x); - } else { - verbose(VERB_DETAIL, "remote control connection failed to " - "authenticate with client certificate"); - clean_point(rc, s); - return 0; - } - - /* if OK start to actually handle the request */ - res.ssl = s->ssl; - res.fd = c->fd; - handle_req(rc, s, &res); - - verbose(VERB_ALGO, "remote control operation completed"); - clean_point(rc, s); - return 0; -} diff --git a/crates/libunbound-sys/unbound/daemon/remote.h b/crates/libunbound-sys/unbound/daemon/remote.h deleted file mode 100644 index 4902803f..00000000 --- a/crates/libunbound-sys/unbound/daemon/remote.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * daemon/remote.h - remote control for the unbound daemon. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the remote control functionality for the daemon. - * The remote control can be performed using either the commandline - * unbound-control tool, or a SSLv3/TLS capable web browser. - * The channel is secured using SSLv3 or TLSv1, and certificates. - * Both the server and the client(control tool) have their own keys. - */ - -#ifndef DAEMON_REMOTE_H -#define DAEMON_REMOTE_H -#ifdef HAVE_OPENSSL_SSL_H -#include -#endif -struct config_file; -struct listen_list; -struct listen_port; -struct worker; -struct comm_reply; -struct comm_point; -struct daemon_remote; - -/** number of milliseconds timeout on incoming remote control handshake */ -#define REMOTE_CONTROL_TCP_TIMEOUT 120000 - -/** - * a busy control command connection, SSL state - */ -struct rc_state { - /** the next item in list */ - struct rc_state* next; - /** the commpoint */ - struct comm_point* c; - /** in the handshake part */ - enum { rc_none, rc_hs_read, rc_hs_write } shake_state; -#ifdef HAVE_SSL - /** the ssl state */ - SSL* ssl; -#endif - /** file descriptor */ - int fd; - /** the rc this is part of */ - struct daemon_remote* rc; -}; - -/** - * The remote control tool state. - * The state is only created for the first thread, other threads - * are called from this thread. Only the first threads listens to - * the control port. The other threads do not, but are called on the - * command channel(pipe) from the first thread. - */ -struct daemon_remote { - /** the worker for this remote control */ - struct worker* worker; - /** commpoints for accepting remote control connections */ - struct listen_list* accept_list; - /* if certificates are used */ - int use_cert; - /** number of active commpoints that are handling remote control */ - int active; - /** max active commpoints */ - int max_active; - /** current commpoints busy; should be a short list, malloced */ - struct rc_state* busy_list; -#ifdef HAVE_SSL - /** the SSL context for creating new SSL streams */ - SSL_CTX* ctx; -#endif -}; - -/** - * Connection to print to, either SSL or plain over fd - */ -struct remote_stream { -#ifdef HAVE_SSL - /** SSL structure, nonNULL if using SSL */ - SSL* ssl; -#endif - /** file descriptor for plain transfer */ - int fd; -}; -typedef struct remote_stream RES; - -/** - * Create new remote control state for the daemon. - * @param cfg: config file with key file settings. - * @return new state, or NULL on failure. - */ -struct daemon_remote* daemon_remote_create(struct config_file* cfg); - -/** - * remote control state to delete. - * @param rc: state to delete. - */ -void daemon_remote_delete(struct daemon_remote* rc); - -/** - * remote control state to clear up. Busy and accept points are closed. - * Does not delete the rc itself, or the ssl context (with its keys). - * @param rc: state to clear. - */ -void daemon_remote_clear(struct daemon_remote* rc); - -/** - * Open and create listening ports for remote control. - * @param cfg: config options. - * @return list of ports or NULL on failure. - * can be freed with listening_ports_free(). - */ -struct listen_port* daemon_remote_open_ports(struct config_file* cfg); - -/** - * Setup comm points for accepting remote control connections. - * @param rc: state - * @param ports: already opened ports. - * @param worker: worker with communication base. and links to command channels. - * @return false on error. - */ -int daemon_remote_open_accept(struct daemon_remote* rc, - struct listen_port* ports, struct worker* worker); - -/** - * Stop accept handlers for TCP (until enabled again) - * @param rc: state - */ -void daemon_remote_stop_accept(struct daemon_remote* rc); - -/** - * Stop accept handlers for TCP (until enabled again) - * @param rc: state - */ -void daemon_remote_start_accept(struct daemon_remote* rc); - -/** - * Handle nonthreaded remote cmd execution. - * @param worker: this worker (the remote worker). - */ -void daemon_remote_exec(struct worker* worker); - -#ifdef HAVE_SSL -/** - * Print fixed line of text over ssl connection in blocking mode - * @param ssl: print to - * @param text: the text. - * @return false on connection failure. - */ -int ssl_print_text(RES* ssl, const char* text); - -/** - * printf style printing to the ssl connection - * @param ssl: the RES connection to print to. Blocking. - * @param format: printf style format string. - * @return success or false on a network failure. - */ -int ssl_printf(RES* ssl, const char* format, ...) - ATTR_FORMAT(printf, 2, 3); - -/** - * Read until \n is encountered - * If stream signals EOF, the string up to then is returned (without \n). - * @param ssl: the RES connection to read from. blocking. - * @param buf: buffer to read to. - * @param max: size of buffer. - * @return false on connection failure. - */ -int ssl_read_line(RES* ssl, char* buf, size_t max); -#endif /* HAVE_SSL */ - -#endif /* DAEMON_REMOTE_H */ diff --git a/crates/libunbound-sys/unbound/daemon/stats.c b/crates/libunbound-sys/unbound/daemon/stats.c deleted file mode 100644 index 4855bf1c..00000000 --- a/crates/libunbound-sys/unbound/daemon/stats.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * daemon/stats.c - collect runtime performance indicators. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file describes the data structure used to collect runtime performance - * numbers. These 'statistics' may be of interest to the operator. - */ -#include "config.h" -#ifdef HAVE_TIME_H -#include -#endif -#include -#include -#include "daemon/stats.h" -#include "daemon/worker.h" -#include "daemon/daemon.h" -#include "services/mesh.h" -#include "services/outside_network.h" -#include "services/listen_dnsport.h" -#include "util/config_file.h" -#include "util/tube.h" -#include "util/timehist.h" -#include "util/net_help.h" -#include "validator/validator.h" -#include "iterator/iterator.h" -#include "sldns/sbuffer.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "services/authzone.h" -#include "validator/val_kcache.h" -#include "validator/val_neg.h" -#ifdef CLIENT_SUBNET -#include "edns-subnet/subnetmod.h" -#endif -#ifdef HAVE_SSL -#include -#endif - -/** How long to wait for threads to transmit statistics, in msec. */ -#define STATS_THREAD_WAIT 60000 - -/** add timers and the values do not overflow or become negative */ -static void -stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec) -{ -#ifndef S_SPLINT_S - (*d_sec) += add_sec; - (*d_usec) += add_usec; - if((*d_usec) >= 1000000) { - (*d_usec) -= 1000000; - (*d_sec)++; - } -#endif -} - -void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg) -{ - memset(stats, 0, sizeof(*stats)); - stats->extended = cfg->stat_extended; -} - -void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker) -{ - stats->num_queries_missed_cache++; - stats->sum_query_list_size += worker->env.mesh->all.count; - if((long long)worker->env.mesh->all.count > stats->max_query_list_size) - stats->max_query_list_size = (long long)worker->env.mesh->all.count; -} - -void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker) -{ - stats->num_queries_prefetch++; - /* changes the query list size so account that, like a querymiss */ - stats->sum_query_list_size += worker->env.mesh->all.count; - if((long long)worker->env.mesh->all.count > stats->max_query_list_size) - stats->max_query_list_size = (long long)worker->env.mesh->all.count; -} - -void server_stats_log(struct ub_server_stats* stats, struct worker* worker, - int threadnum) -{ - log_info("server stats for thread %d: %u queries, " - "%u answers from cache, %u recursions, %u prefetch, %u rejected by " - "ip ratelimiting", - threadnum, (unsigned)stats->num_queries, - (unsigned)(stats->num_queries - - stats->num_queries_missed_cache), - (unsigned)stats->num_queries_missed_cache, - (unsigned)stats->num_queries_prefetch, - (unsigned)stats->num_queries_ip_ratelimited); - log_info("server stats for thread %d: requestlist max %u avg %g " - "exceeded %u jostled %u", threadnum, - (unsigned)stats->max_query_list_size, - (stats->num_queries_missed_cache+stats->num_queries_prefetch)? - (double)stats->sum_query_list_size/ - (double)(stats->num_queries_missed_cache+ - stats->num_queries_prefetch) : 0.0, - (unsigned)worker->env.mesh->stats_dropped, - (unsigned)worker->env.mesh->stats_jostled); -} - - -#ifdef CLIENT_SUBNET -/** Set the EDNS Subnet stats. */ -static void -set_subnet_stats(struct worker* worker, struct ub_server_stats* svr, - int reset) -{ - int m = modstack_find(&worker->env.mesh->mods, "subnetcache"); - struct subnet_env* sne; - if(m == -1) - return; - sne = (struct subnet_env*)worker->env.modinfo[m]; - if(reset && !worker->env.cfg->stat_cumulative) { - lock_rw_wrlock(&sne->biglock); - } else { - lock_rw_rdlock(&sne->biglock); - } - svr->num_query_subnet = (long long)(sne->num_msg_nocache + sne->num_msg_cache); - svr->num_query_subnet_cache = (long long)sne->num_msg_cache; - if(reset && !worker->env.cfg->stat_cumulative) { - sne->num_msg_cache = 0; - sne->num_msg_nocache = 0; - } - lock_rw_unlock(&sne->biglock); -} -#endif /* CLIENT_SUBNET */ - -/** Set the neg cache stats. */ -static void -set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr, - int reset) -{ - int m = modstack_find(&worker->env.mesh->mods, "validator"); - struct val_env* ve; - struct val_neg_cache* neg; - if(m == -1) - return; - ve = (struct val_env*)worker->env.modinfo[m]; - if(!ve->neg_cache) - return; - neg = ve->neg_cache; - lock_basic_lock(&neg->lock); - svr->num_neg_cache_noerror = (long long)neg->num_neg_cache_noerror; - svr->num_neg_cache_nxdomain = (long long)neg->num_neg_cache_nxdomain; - if(reset && !worker->env.cfg->stat_cumulative) { - neg->num_neg_cache_noerror = 0; - neg->num_neg_cache_nxdomain = 0; - } - lock_basic_unlock(&neg->lock); -} - -/** get rrsets bogus number from validator */ -static size_t -get_rrset_bogus(struct worker* worker, int reset) -{ - int m = modstack_find(&worker->env.mesh->mods, "validator"); - struct val_env* ve; - size_t r; - if(m == -1) - return 0; - ve = (struct val_env*)worker->env.modinfo[m]; - lock_basic_lock(&ve->bogus_lock); - r = ve->num_rrset_bogus; - if(reset && !worker->env.cfg->stat_cumulative) - ve->num_rrset_bogus = 0; - lock_basic_unlock(&ve->bogus_lock); - return r; -} - -/** get number of ratelimited queries from iterator */ -static size_t -get_queries_ratelimit(struct worker* worker, int reset) -{ - int m = modstack_find(&worker->env.mesh->mods, "iterator"); - struct iter_env* ie; - size_t r; - if(m == -1) - return 0; - ie = (struct iter_env*)worker->env.modinfo[m]; - lock_basic_lock(&ie->queries_ratelimit_lock); - r = ie->num_queries_ratelimited; - if(reset && !worker->env.cfg->stat_cumulative) - ie->num_queries_ratelimited = 0; - lock_basic_unlock(&ie->queries_ratelimit_lock); - return r; -} - -#ifdef USE_DNSCRYPT -/** get the number of shared secret cache miss */ -static size_t -get_dnscrypt_cache_miss(struct worker* worker, int reset) -{ - size_t r; - struct dnsc_env* de = worker->daemon->dnscenv; - if(!de) return 0; - - lock_basic_lock(&de->shared_secrets_cache_lock); - r = de->num_query_dnscrypt_secret_missed_cache; - if(reset && !worker->env.cfg->stat_cumulative) - de->num_query_dnscrypt_secret_missed_cache = 0; - lock_basic_unlock(&de->shared_secrets_cache_lock); - return r; -} - -/** get the number of replayed queries */ -static size_t -get_dnscrypt_replay(struct worker* worker, int reset) -{ - size_t r; - struct dnsc_env* de = worker->daemon->dnscenv; - - lock_basic_lock(&de->nonces_cache_lock); - r = de->num_query_dnscrypt_replay; - if(reset && !worker->env.cfg->stat_cumulative) - de->num_query_dnscrypt_replay = 0; - lock_basic_unlock(&de->nonces_cache_lock); - return r; -} -#endif /* USE_DNSCRYPT */ - -void -server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset) -{ - int i; - struct listen_list* lp; - - s->svr = worker->stats; - s->mesh_num_states = (long long)worker->env.mesh->all.count; - s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states; - s->mesh_jostled = (long long)worker->env.mesh->stats_jostled; - s->mesh_dropped = (long long)worker->env.mesh->stats_dropped; - s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent; - s->mesh_replies_sum_wait_sec = (long long)worker->env.mesh->replies_sum_wait.tv_sec; - s->mesh_replies_sum_wait_usec = (long long)worker->env.mesh->replies_sum_wait.tv_usec; - s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram, - 0.50); - - /* add in the values from the mesh */ - s->svr.ans_secure += (long long)worker->env.mesh->ans_secure; - s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus; - s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata; - s->svr.ans_expired += (long long)worker->env.mesh->ans_expired; - for(i=0; isvr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i]; - for(i=0; isvr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i]; - timehist_export(worker->env.mesh->histogram, s->svr.hist, - NUM_BUCKETS_HIST); - /* values from outside network */ - s->svr.unwanted_replies = (long long)worker->back->unwanted_replies; - s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing; - s->svr.qudp_outgoing = (long long)worker->back->num_udp_outgoing; - - /* get and reset validator rrset bogus number */ - s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset); - - /* get and reset iterator query ratelimit number */ - s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset); - - /* get cache sizes */ - get_slabhash_stats(worker->env.msg_cache, - &s->svr.msg_cache_count, &s->svr.msg_cache_max_collisions); - get_slabhash_stats(&worker->env.rrset_cache->table, - &s->svr.rrset_cache_count, &s->svr.rrset_cache_max_collisions); - s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts); - if(worker->env.key_cache) - s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab); - else s->svr.key_cache_count = 0; - -#ifdef USE_DNSCRYPT - if(worker->daemon->dnscenv) { - s->svr.num_query_dnscrypt_secret_missed_cache = - (long long)get_dnscrypt_cache_miss(worker, reset); - s->svr.shared_secret_cache_count = (long long)count_slabhash_entries( - worker->daemon->dnscenv->shared_secrets_cache); - s->svr.nonce_cache_count = (long long)count_slabhash_entries( - worker->daemon->dnscenv->nonces_cache); - s->svr.num_query_dnscrypt_replay = - (long long)get_dnscrypt_replay(worker, reset); - } else { - s->svr.num_query_dnscrypt_secret_missed_cache = 0; - s->svr.shared_secret_cache_count = 0; - s->svr.nonce_cache_count = 0; - s->svr.num_query_dnscrypt_replay = 0; - } -#else - s->svr.num_query_dnscrypt_secret_missed_cache = 0; - s->svr.shared_secret_cache_count = 0; - s->svr.nonce_cache_count = 0; - s->svr.num_query_dnscrypt_replay = 0; -#endif /* USE_DNSCRYPT */ - if(worker->env.auth_zones) { - if(reset && !worker->env.cfg->stat_cumulative) { - lock_rw_wrlock(&worker->env.auth_zones->lock); - } else { - lock_rw_rdlock(&worker->env.auth_zones->lock); - } - s->svr.num_query_authzone_up = (long long)worker->env. - auth_zones->num_query_up; - s->svr.num_query_authzone_down = (long long)worker->env. - auth_zones->num_query_down; - if(reset && !worker->env.cfg->stat_cumulative) { - worker->env.auth_zones->num_query_up = 0; - worker->env.auth_zones->num_query_down = 0; - } - lock_rw_unlock(&worker->env.auth_zones->lock); - } - s->svr.mem_stream_wait = - (long long)tcp_req_info_get_stream_buffer_size(); - s->svr.mem_http2_query_buffer = - (long long)http2_get_query_buffer_size(); - s->svr.mem_http2_response_buffer = - (long long)http2_get_response_buffer_size(); - - /* Set neg cache usage numbers */ - set_neg_cache_stats(worker, &s->svr, reset); -#ifdef CLIENT_SUBNET - /* EDNS Subnet usage numbers */ - set_subnet_stats(worker, &s->svr, reset); -#else - s->svr.num_query_subnet = 0; - s->svr.num_query_subnet_cache = 0; -#endif -#ifdef USE_CACHEDB - s->svr.num_query_cachedb = (long long)worker->env.mesh->ans_cachedb; -#else - s->svr.num_query_cachedb = 0; -#endif - - /* get tcp accept usage */ - s->svr.tcp_accept_usage = 0; - for(lp = worker->front->cps; lp; lp = lp->next) { - if(lp->com->type == comm_tcp_accept) - s->svr.tcp_accept_usage += (long long)lp->com->cur_tcp_count; - } - - if(reset && !worker->env.cfg->stat_cumulative) { - worker_stats_clear(worker); - } -} - -void server_stats_obtain(struct worker* worker, struct worker* who, - struct ub_stats_info* s, int reset) -{ - uint8_t *reply = NULL; - uint32_t len = 0; - if(worker == who) { - /* just fill it in */ - server_stats_compile(worker, s, reset); - return; - } - /* communicate over tube */ - verbose(VERB_ALGO, "write stats cmd"); - if(reset) - worker_send_cmd(who, worker_cmd_stats); - else worker_send_cmd(who, worker_cmd_stats_noreset); - verbose(VERB_ALGO, "wait for stats reply"); - if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) { - verbose(VERB_OPS, "no response from thread %d" -#ifdef HAVE_GETTID - " LWP %u" -#endif -#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG) -# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG - " pthread 0x%lx" -# endif -#endif - , - who->thread_num -#ifdef HAVE_GETTID - , (unsigned)who->thread_tid -#endif -#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG) -# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG - , (unsigned long)*((unsigned long*)&who->thr_id) -# endif -#endif - ); - } - if(!tube_read_msg(worker->cmd, &reply, &len, 0)) - fatal_exit("failed to read stats over cmd channel"); - if(len != (uint32_t)sizeof(*s)) - fatal_exit("stats on cmd channel wrong length %d %d", - (int)len, (int)sizeof(*s)); - memcpy(s, reply, (size_t)len); - free(reply); -} - -void server_stats_reply(struct worker* worker, int reset) -{ - struct ub_stats_info s; - server_stats_compile(worker, &s, reset); - verbose(VERB_ALGO, "write stats replymsg"); - if(!tube_write_msg(worker->daemon->workers[0]->cmd, - (uint8_t*)&s, sizeof(s), 0)) - fatal_exit("could not write stat values over cmd channel"); -} - -void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a) -{ - total->svr.num_queries += a->svr.num_queries; - total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited; - total->svr.num_queries_cookie_valid += a->svr.num_queries_cookie_valid; - total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client; - total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid; - total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache; - total->svr.num_queries_prefetch += a->svr.num_queries_prefetch; - total->svr.num_queries_timed_out += a->svr.num_queries_timed_out; - if (total->svr.max_query_time_us < a->svr.max_query_time_us) - total->svr.max_query_time_us = a->svr.max_query_time_us; - total->svr.sum_query_list_size += a->svr.sum_query_list_size; - total->svr.ans_expired += a->svr.ans_expired; -#ifdef USE_DNSCRYPT - total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted; - total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert; - total->svr.num_query_dnscrypt_cleartext += \ - a->svr.num_query_dnscrypt_cleartext; - total->svr.num_query_dnscrypt_crypted_malformed += \ - a->svr.num_query_dnscrypt_crypted_malformed; -#endif /* USE_DNSCRYPT */ - /* the max size reached is upped to higher of both */ - if(a->svr.max_query_list_size > total->svr.max_query_list_size) - total->svr.max_query_list_size = a->svr.max_query_list_size; - - if(a->svr.extended) { - int i; - total->svr.qtype_big += a->svr.qtype_big; - total->svr.qclass_big += a->svr.qclass_big; - total->svr.qtcp += a->svr.qtcp; - total->svr.qtcp_outgoing += a->svr.qtcp_outgoing; - total->svr.qudp_outgoing += a->svr.qudp_outgoing; - total->svr.qtls += a->svr.qtls; - total->svr.qtls_resume += a->svr.qtls_resume; - total->svr.qhttps += a->svr.qhttps; - total->svr.qipv6 += a->svr.qipv6; - total->svr.qbit_QR += a->svr.qbit_QR; - total->svr.qbit_AA += a->svr.qbit_AA; - total->svr.qbit_TC += a->svr.qbit_TC; - total->svr.qbit_RD += a->svr.qbit_RD; - total->svr.qbit_RA += a->svr.qbit_RA; - total->svr.qbit_Z += a->svr.qbit_Z; - total->svr.qbit_AD += a->svr.qbit_AD; - total->svr.qbit_CD += a->svr.qbit_CD; - total->svr.qEDNS += a->svr.qEDNS; - total->svr.qEDNS_DO += a->svr.qEDNS_DO; - total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata; - total->svr.ans_secure += a->svr.ans_secure; - total->svr.ans_bogus += a->svr.ans_bogus; - total->svr.unwanted_replies += a->svr.unwanted_replies; - total->svr.unwanted_queries += a->svr.unwanted_queries; - total->svr.tcp_accept_usage += a->svr.tcp_accept_usage; -#ifdef USE_CACHEDB - total->svr.num_query_cachedb += a->svr.num_query_cachedb; -#endif - for(i=0; isvr.qtype[i] += a->svr.qtype[i]; - for(i=0; isvr.qclass[i] += a->svr.qclass[i]; - for(i=0; isvr.qopcode[i] += a->svr.qopcode[i]; - for(i=0; isvr.ans_rcode[i] += a->svr.ans_rcode[i]; - for(i=0; isvr.hist[i] += a->svr.hist[i]; - for(i=0; isvr.rpz_action[i] += a->svr.rpz_action[i]; - } - - total->mesh_num_states += a->mesh_num_states; - total->mesh_num_reply_states += a->mesh_num_reply_states; - total->mesh_jostled += a->mesh_jostled; - total->mesh_dropped += a->mesh_dropped; - total->mesh_replies_sent += a->mesh_replies_sent; - stats_timeval_add(&total->mesh_replies_sum_wait_sec, &total->mesh_replies_sum_wait_usec, a->mesh_replies_sum_wait_sec, a->mesh_replies_sum_wait_usec); - /* the medians are averaged together, this is not as accurate as - * taking the median over all of the data, but is good and fast - * added up here, division later*/ - total->mesh_time_median += a->mesh_time_median; -} - -void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c, - uint16_t qtype, uint16_t qclass, struct edns_data* edns, - struct comm_reply* repinfo) -{ - uint16_t flags = sldns_buffer_read_u16_at(c->buffer, 2); - if(qtype < UB_STATS_QTYPE_NUM) - stats->qtype[qtype]++; - else stats->qtype_big++; - if(qclass < UB_STATS_QCLASS_NUM) - stats->qclass[qclass]++; - else stats->qclass_big++; - stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++; - if(c->type != comm_udp) { - stats->qtcp++; - if(c->ssl != NULL) { - stats->qtls++; -#ifdef HAVE_SSL - if(SSL_session_reused(c->ssl)) - stats->qtls_resume++; -#endif - if(c->type == comm_http) - stats->qhttps++; - } - } - if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen)) - stats->qipv6++; - if( (flags&BIT_QR) ) - stats->qbit_QR++; - if( (flags&BIT_AA) ) - stats->qbit_AA++; - if( (flags&BIT_TC) ) - stats->qbit_TC++; - if( (flags&BIT_RD) ) - stats->qbit_RD++; - if( (flags&BIT_RA) ) - stats->qbit_RA++; - if( (flags&BIT_Z) ) - stats->qbit_Z++; - if( (flags&BIT_AD) ) - stats->qbit_AD++; - if( (flags&BIT_CD) ) - stats->qbit_CD++; - if(edns->edns_present) { - stats->qEDNS++; - if( (edns->bits & EDNS_DO) ) - stats->qEDNS_DO++; - } -} - -void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf) -{ - if(stats->extended && sldns_buffer_limit(buf) != 0) { - int r = (int)LDNS_RCODE_WIRE( sldns_buffer_begin(buf) ); - stats->ans_rcode[r] ++; - if(r == 0 && LDNS_ANCOUNT( sldns_buffer_begin(buf) ) == 0) - stats->ans_rcode_nodata ++; - } -} - -void server_stats_downstream_cookie(struct ub_server_stats* stats, - struct edns_data* edns) -{ - if(!(edns->edns_present && edns->cookie_present)) return; - if(edns->cookie_valid) { - stats->num_queries_cookie_valid++; - } else if(edns->cookie_client) { - stats->num_queries_cookie_client++; - } else { - stats->num_queries_cookie_invalid++; - } -} diff --git a/crates/libunbound-sys/unbound/daemon/stats.h b/crates/libunbound-sys/unbound/daemon/stats.h deleted file mode 100644 index 47bb20d7..00000000 --- a/crates/libunbound-sys/unbound/daemon/stats.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * daemon/stats.h - collect runtime performance indicators. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file describes the data structure used to collect runtime performance - * numbers. These 'statistics' may be of interest to the operator. - */ - -#ifndef DAEMON_STATS_H -#define DAEMON_STATS_H -#include "util/timehist.h" -struct worker; -struct config_file; -struct comm_point; -struct comm_reply; -struct edns_data; -struct sldns_buffer; - -/* stats struct */ -#include "libunbound/unbound.h" - -/** - * Initialize server stats to 0. - * @param stats: what to init (this is alloced by the caller). - * @param cfg: with extended statistics option. - */ -void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg); - -/** add query if it missed the cache */ -void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker); - -/** add query if was cached and also resulted in a prefetch */ -void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker); - -/** display the stats to the log */ -void server_stats_log(struct ub_server_stats* stats, struct worker* worker, - int threadnum); - -/** - * Obtain the stats info for a given thread. Uses pipe to communicate. - * @param worker: the worker that is executing (the first worker). - * @param who: on who to get the statistics info. - * @param s: the stats block to fill in. - * @param reset: if stats can be reset. - */ -void server_stats_obtain(struct worker* worker, struct worker* who, - struct ub_stats_info* s, int reset); - -/** - * Compile stats into structure for this thread worker. - * Also clears the statistics counters (if that is set by config file). - * @param worker: the worker to compile stats for, also the executing worker. - * @param s: stats block. - * @param reset: if true, depending on config stats are reset. - * if false, statistics are not reset. - */ -void server_stats_compile(struct worker* worker, struct ub_stats_info* s, - int reset); - -/** - * Send stats over comm tube in reply to query cmd - * @param worker: this worker. - * @param reset: if true, depending on config stats are reset. - * if false, statistics are not reset. - */ -void server_stats_reply(struct worker* worker, int reset); - -/** - * Addup stat blocks. - * @param total: sum of the two entries. - * @param a: to add to it. - */ -void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a); - -/** - * Add stats for this query - * @param stats: the stats - * @param c: commpoint with type and buffer. - * @param qtype: query type - * @param qclass: query class - * @param edns: edns record - * @param repinfo: reply info with remote address - */ -void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c, - uint16_t qtype, uint16_t qclass, struct edns_data* edns, - struct comm_reply* repinfo); - -/** - * Add rcode for this query. - * @param stats: the stats - * @param buf: buffer with rcode. If buffer is length0: not counted. - */ -void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf); - -/** - * Add DNS Cookie stats for this query - * @param stats: the stats - * @param edns: edns record - */ -void server_stats_downstream_cookie(struct ub_server_stats* stats, - struct edns_data* edns); -#endif /* DAEMON_STATS_H */ diff --git a/crates/libunbound-sys/unbound/daemon/unbound.c b/crates/libunbound-sys/unbound/daemon/unbound.c deleted file mode 100644 index 457a0803..00000000 --- a/crates/libunbound-sys/unbound/daemon/unbound.c +++ /dev/null @@ -1,846 +0,0 @@ -/* - * daemon/unbound.c - main program for unbound DNS resolver daemon. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * - * Main program to start the DNS resolver daemon. - */ - -#include "config.h" -#ifdef HAVE_GETOPT_H -#include -#endif -#include -#include "util/log.h" -#include "daemon/daemon.h" -#include "daemon/remote.h" -#include "util/config_file.h" -#include "util/storage/slabhash.h" -#include "services/listen_dnsport.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "util/fptr_wlist.h" -#include "util/data/msgreply.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/ub_event.h" -#include -#include -#include -#ifdef HAVE_PWD_H -#include -#endif -#ifdef HAVE_GRP_H -#include -#endif -#include - -#ifndef S_SPLINT_S -/* splint chokes on this system header file */ -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif -#endif /* S_SPLINT_S */ -#ifdef HAVE_LOGIN_CAP_H -#include -#endif - -#ifdef UB_ON_WINDOWS -# include "winrc/win_svc.h" -#endif - -#ifdef HAVE_NSS -/* nss3 */ -# include "nss.h" -#endif - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) -#undef HAVE_FORK -#endif - -/** print build options. */ -static void -print_build_options(void) -{ - const char** m; - const char *evnm="event", *evsys="", *evmethod=""; - time_t t; - struct timeval now; - struct ub_event_base* base; - printf("Version %s\n\n", PACKAGE_VERSION); - printf("Configure line: %s\n", CONFCMDLINE); - base = ub_default_event_base(0,&t,&now); - ub_get_event_sys(base, &evnm, &evsys, &evmethod); - printf("Linked libs: %s %s (it uses %s), %s\n", - evnm, evsys, evmethod, -#ifdef HAVE_SSL -# ifdef SSLEAY_VERSION - SSLeay_version(SSLEAY_VERSION) -# else - OpenSSL_version(OPENSSL_VERSION) -# endif -#elif defined(HAVE_NSS) - NSS_GetVersion() -#elif defined(HAVE_NETTLE) - "nettle" -#endif - ); - printf("Linked modules:"); - for(m = module_list_avail(); *m; m++) - printf(" %s", *m); - printf("\n"); -#ifdef USE_DNSCRYPT - printf("DNSCrypt feature available\n"); -#endif -#ifdef USE_TCP_FASTOPEN - printf("TCP Fastopen feature available\n"); -#endif - ub_event_base_free(base); - printf("\nBSD licensed, see LICENSE in source package for details.\n"); - printf("Report bugs to %s\n", PACKAGE_BUGREPORT); -} - -/** print usage. */ -static void -usage(void) -{ - printf("usage: unbound [options]\n"); - printf(" start unbound daemon DNS resolver.\n"); - printf("-h this help.\n"); - printf("-c file config file to read instead of %s\n", CONFIGFILE); - printf(" file format is described in unbound.conf(5).\n"); - printf("-d do not fork into the background.\n"); - printf("-p do not create a pidfile.\n"); - printf("-v verbose (more times to increase verbosity).\n"); - printf("-V show version number and build options.\n"); -#ifdef UB_ON_WINDOWS - printf("-w opt windows option: \n"); - printf(" install, remove - manage the services entry\n"); - printf(" service - used to start from services control panel\n"); -#endif - printf("\nVersion %s\n", PACKAGE_VERSION); - printf("BSD licensed, see LICENSE in source package for details.\n"); - printf("Report bugs to %s\n", PACKAGE_BUGREPORT); -} - -#ifndef unbound_testbound -int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} -#endif - -/** check file descriptor count */ -static void -checkrlimits(struct config_file* cfg) -{ -#ifndef S_SPLINT_S -#ifdef HAVE_GETRLIMIT - /* list has number of ports to listen to, ifs number addresses */ - int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 + - (int)cfg->incoming_num_tcp:0)); - size_t listen_ifs = (size_t)(cfg->num_ifs==0? - ((cfg->do_ip4 && !cfg->if_automatic?1:0) + - (cfg->do_ip6?1:0)):cfg->num_ifs); - size_t listen_num = list*listen_ifs; - size_t outudpnum = (size_t)cfg->outgoing_num_ports; - size_t outtcpnum = cfg->outgoing_num_tcp; - size_t misc = 4; /* logfile, pidfile, stdout... */ - size_t perthread_noudp = listen_num + outtcpnum + - 2/*cmdpipe*/ + 2/*libevent*/ + misc; - size_t perthread = perthread_noudp + outudpnum; - -#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) - int numthread = 1; /* it forks */ -#else - int numthread = (cfg->num_threads?cfg->num_threads:1); -#endif - size_t total = numthread * perthread + misc; - size_t avail; - struct rlimit rlim; - size_t memsize_expect = cfg->msg_cache_size + cfg->rrset_cache_size - + (cfg->do_tcp?cfg->stream_wait_size:0) - + (cfg->ip_ratelimit?cfg->ip_ratelimit_size:0) - + (cfg->ratelimit?cfg->ratelimit_size:0) - + (cfg->dnscrypt?cfg->dnscrypt_shared_secret_cache_size + cfg->dnscrypt_nonce_cache_size:0) - + cfg->infra_cache_numhosts * (sizeof(struct infra_key)+sizeof(struct infra_data)); - if(strstr(cfg->module_conf, "validator") && (cfg->trust_anchor_file_list || cfg->trust_anchor_list || cfg->auto_trust_anchor_file_list || cfg->trusted_keys_file_list)) { - memsize_expect += cfg->key_cache_size + cfg->neg_cache_size; - } -#ifdef HAVE_NGHTTP2_NGHTTP2_H - if(cfg_has_https(cfg)) { - memsize_expect += cfg->http_query_buffer_size + cfg->http_response_buffer_size; - } -#endif - -#ifdef RLIMIT_AS - if(getrlimit(RLIMIT_AS, &rlim) == 0) { - if(rlim.rlim_cur != (rlim_t)RLIM_INFINITY && - rlim.rlim_cur < (rlim_t)memsize_expect) { - log_warn("the ulimit(max memory size) is smaller than the expected memory usage (added size of caches). %u < %u bytes", (unsigned)rlim.rlim_cur, (unsigned)memsize_expect); - } - } -#endif - if(getrlimit(RLIMIT_DATA, &rlim) == 0) { - if(rlim.rlim_cur != (rlim_t)RLIM_INFINITY && - rlim.rlim_cur < (rlim_t)memsize_expect) { - log_warn("the ulimit(data seg size) is smaller than the expected memory usage (added size of caches). %u < %u bytes", (unsigned)rlim.rlim_cur, (unsigned)memsize_expect); - } - } - - if(total > 1024 && - strncmp(ub_event_get_version(), "mini-event", 10) == 0) { - log_warn("too many file descriptors requested. The builtin" - "mini-event cannot handle more than 1024. Config " - "for less fds or compile with libevent"); - if(numthread*perthread_noudp+15 > 1024) - fatal_exit("too much tcp. not enough fds."); - cfg->outgoing_num_ports = (int)((1024 - - numthread*perthread_noudp - - 10 /* safety margin */) /numthread); - log_warn("continuing with less udp ports: %u", - cfg->outgoing_num_ports); - total = 1024; - } - if(perthread > 64 && - strncmp(ub_event_get_version(), "winsock-event", 13) == 0) { - log_err("too many file descriptors requested. The winsock" - " event handler cannot handle more than 64 per " - " thread. Config for less fds"); - if(perthread_noudp+2 > 64) - fatal_exit("too much tcp. not enough fds."); - cfg->outgoing_num_ports = (int)((64 - - perthread_noudp - - 2/* safety margin */)); - log_warn("continuing with less udp ports: %u", - cfg->outgoing_num_ports); - total = numthread*(perthread_noudp+ - (size_t)cfg->outgoing_num_ports)+misc; - } - if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) { - log_warn("getrlimit: %s", strerror(errno)); - return; - } - if(rlim.rlim_cur == (rlim_t)RLIM_INFINITY) - return; - if((size_t)rlim.rlim_cur < total) { - avail = (size_t)rlim.rlim_cur; - rlim.rlim_cur = (rlim_t)(total + 10); - rlim.rlim_max = (rlim_t)(total + 10); -#ifdef HAVE_SETRLIMIT - if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) { - log_warn("setrlimit: %s", strerror(errno)); -#endif - log_warn("cannot increase max open fds from %u to %u", - (unsigned)avail, (unsigned)total+10); - /* check that calculation below does not underflow, - * with 15 as margin */ - if(numthread*perthread_noudp+15 > avail) - fatal_exit("too much tcp. not enough fds."); - cfg->outgoing_num_ports = (int)((avail - - numthread*perthread_noudp - - 10 /* safety margin */) /numthread); - log_warn("continuing with less udp ports: %u", - cfg->outgoing_num_ports); - log_warn("increase ulimit or decrease threads, " - "ports in config to remove this warning"); - return; -#ifdef HAVE_SETRLIMIT - } -#endif - verbose(VERB_ALGO, "increased limit(open files) from %u to %u", - (unsigned)avail, (unsigned)total+10); - } -#else - (void)cfg; -#endif /* HAVE_GETRLIMIT */ -#endif /* S_SPLINT_S */ -} - -/** set verbosity, check rlimits, cache settings */ -static void -apply_settings(struct daemon* daemon, struct config_file* cfg, - int cmdline_verbose, int debug_mode) -{ - /* apply if they have changed */ - verbosity = cmdline_verbose + cfg->verbosity; - if (debug_mode > 1) { - cfg->use_syslog = 0; - free(cfg->logfile); - cfg->logfile = NULL; - } - daemon_apply_cfg(daemon, cfg); - checkrlimits(cfg); - - if (cfg->use_systemd && cfg->do_daemonize) { - log_warn("use-systemd and do-daemonize should not be enabled at the same time"); - } - - log_ident_set_or_default(cfg->log_identity); -} - -#ifdef HAVE_KILL -/** Read existing pid from pidfile. - * @param file: file name of pid file. - * @return: the pid from the file or -1 if none. - */ -static pid_t -readpid (const char* file) -{ - int fd; - pid_t pid; - char pidbuf[32]; - char* t; - ssize_t l; - - if ((fd = open(file, O_RDONLY)) == -1) { - if(errno != ENOENT) - log_err("Could not read pidfile %s: %s", - file, strerror(errno)); - return -1; - } - - if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) { - if(errno != ENOENT) - log_err("Could not read pidfile %s: %s", - file, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - - /* Empty pidfile means no pidfile... */ - if (l == 0) { - return -1; - } - - pidbuf[sizeof(pidbuf)-1] = 0; - pid = (pid_t)strtol(pidbuf, &t, 10); - - if (*t && *t != '\n') { - return -1; - } - return pid; -} - -/** write pid to file. - * @param pidfile: file name of pid file. - * @param pid: pid to write to file. - * @return false on failure - */ -static int -writepid (const char* pidfile, pid_t pid) -{ - int fd; - char pidbuf[32]; - size_t count = 0; - snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long)pid); - - if((fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC -#ifdef O_NOFOLLOW - | O_NOFOLLOW -#endif - , 0644)) == -1) { - log_err("cannot open pidfile %s: %s", - pidfile, strerror(errno)); - return 0; - } - while(count < strlen(pidbuf)) { - ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count); - if(r == -1) { - if(errno == EAGAIN || errno == EINTR) - continue; - log_err("cannot write to pidfile %s: %s", - pidfile, strerror(errno)); - close(fd); - return 0; - } else if(r == 0) { - log_err("cannot write any bytes to pidfile %s: " - "write returns 0 bytes written", pidfile); - close(fd); - return 0; - } - count += r; - } - close(fd); - return 1; -} - -/** - * check old pid file. - * @param pidfile: the file name of the pid file. - * @param inchroot: if pidfile is inchroot and we can thus expect to - * be able to delete it. - */ -static void -checkoldpid(char* pidfile, int inchroot) -{ - pid_t old; - if((old = readpid(pidfile)) != -1) { - /* see if it is still alive */ - if(kill(old, 0) == 0 || errno == EPERM) - log_warn("unbound is already running as pid %u.", - (unsigned)old); - else if(inchroot) - log_warn("did not exit gracefully last time (%u)", - (unsigned)old); - } -} -#endif /* HAVE_KILL */ - -/** detach from command line */ -static void -detach(void) -{ -#if defined(HAVE_DAEMON) && !defined(DEPRECATED_DAEMON) - /* use POSIX daemon(3) function */ - if(daemon(1, 0) != 0) - fatal_exit("daemon failed: %s", strerror(errno)); -#else /* no HAVE_DAEMON */ -#ifdef HAVE_FORK - int fd; - /* Take off... */ - switch (fork()) { - case 0: - break; - case -1: - fatal_exit("fork failed: %s", strerror(errno)); - default: - /* exit interactive session */ - exit(0); - } - /* detach */ -#ifdef HAVE_SETSID - if(setsid() == -1) - fatal_exit("setsid() failed: %s", strerror(errno)); -#endif - if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { - (void)dup2(fd, STDIN_FILENO); - (void)dup2(fd, STDOUT_FILENO); - (void)dup2(fd, STDERR_FILENO); - if (fd > 2) - (void)close(fd); - } -#endif /* HAVE_FORK */ -#endif /* HAVE_DAEMON */ -} - -/** daemonize, drop user privileges and chroot if needed */ -static void -perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, - const char** cfgfile, int need_pidfile) -{ -#ifdef HAVE_KILL - int pidinchroot; -#endif -#ifdef HAVE_GETPWNAM - struct passwd *pwd = NULL; - - if(cfg->username && cfg->username[0]) { - if((pwd = getpwnam(cfg->username)) == NULL) - fatal_exit("user '%s' does not exist.", cfg->username); - /* endpwent below, in case we need pwd for setusercontext */ - } -#endif -#ifdef UB_ON_WINDOWS - w_config_adjust_directory(cfg); -#endif - - /* read ssl keys while superuser and outside chroot */ -#ifdef HAVE_SSL - if(!(daemon->rc = daemon_remote_create(cfg))) - fatal_exit("could not set up remote-control"); - if(cfg->ssl_service_key && cfg->ssl_service_key[0]) { - if(!(daemon->listen_sslctx = listen_sslctx_create( - cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) - fatal_exit("could not set up listen SSL_CTX"); - if(cfg->tls_ciphers && cfg->tls_ciphers[0]) { - if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) { - fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers); - } - } -#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES - if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) { - if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) { - fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites); - } - } -#endif - if(cfg->tls_session_ticket_keys.first && - cfg->tls_session_ticket_keys.first->str[0] != 0) { - if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) { - fatal_exit("could not set session ticket SSL_CTX"); - } - } - } - if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, - cfg->tls_cert_bundle, cfg->tls_win_cert))) - fatal_exit("could not set up connect SSL_CTX"); -#endif - - /* init syslog (as root) if needed, before daemonize, otherwise - * a fork error could not be printed since daemonize closed stderr.*/ - if(cfg->use_syslog) { - log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); - } - /* if using a logfile, we cannot open it because the logfile would - * be created with the wrong permissions, we cannot chown it because - * we cannot chown system logfiles, so we do not open at all. - * So, using a logfile, the user does not see errors unless -d is - * given to unbound on the commandline. */ - -#ifdef HAVE_KILL - /* true if pidfile is inside chrootdir, or nochroot */ - pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) || - (cfg->chrootdir && cfg->chrootdir[0] && - strncmp(cfg->pidfile, cfg->chrootdir, - strlen(cfg->chrootdir))==0)); - - /* check old pid file before forking */ - if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) { - /* calculate position of pidfile */ - if(cfg->pidfile[0] == '/') - daemon->pidfile = strdup(cfg->pidfile); - else daemon->pidfile = fname_after_chroot(cfg->pidfile, - cfg, 1); - if(!daemon->pidfile) - fatal_exit("pidfile alloc: out of memory"); - checkoldpid(daemon->pidfile, pidinchroot); - } -#endif - - /* daemonize because pid is needed by the writepid func */ - if(!debug_mode && cfg->do_daemonize) { - detach(); - } - - /* write new pidfile (while still root, so can be outside chroot) */ -#ifdef HAVE_KILL - if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) { - if(writepid(daemon->pidfile, getpid())) { - if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 && - pidinchroot) { -# ifdef HAVE_CHOWN - if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) { - verbose(VERB_QUERY, "cannot chown %u.%u %s: %s", - (unsigned)cfg_uid, (unsigned)cfg_gid, - daemon->pidfile, strerror(errno)); - } -# endif /* HAVE_CHOWN */ - } - } - } -#else - (void)daemon; - (void)need_pidfile; -#endif /* HAVE_KILL */ - - /* Set user context */ -#ifdef HAVE_GETPWNAM - if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { -#ifdef HAVE_SETUSERCONTEXT - /* setusercontext does initgroups, setuid, setgid, and - * also resource limits from login config, but we - * still call setresuid, setresgid to be sure to set all uid*/ - if(setusercontext(NULL, pwd, cfg_uid, (unsigned) - LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) - log_warn("unable to setusercontext %s: %s", - cfg->username, strerror(errno)); -#else - (void)pwd; -#endif /* HAVE_SETUSERCONTEXT */ - } -#endif /* HAVE_GETPWNAM */ - - /* box into the chroot */ -#ifdef HAVE_CHROOT - if(cfg->chrootdir && cfg->chrootdir[0]) { - if(chdir(cfg->chrootdir)) { - fatal_exit("unable to chdir to chroot %s: %s", - cfg->chrootdir, strerror(errno)); - } - verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir); - if(chroot(cfg->chrootdir)) - fatal_exit("unable to chroot to %s: %s", - cfg->chrootdir, strerror(errno)); - if(chdir("/")) - fatal_exit("unable to chdir to / in chroot %s: %s", - cfg->chrootdir, strerror(errno)); - verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir); - if(strncmp(*cfgfile, cfg->chrootdir, - strlen(cfg->chrootdir)) == 0) - (*cfgfile) += strlen(cfg->chrootdir); - - /* adjust stored pidfile for chroot */ - if(daemon->pidfile && daemon->pidfile[0] && - strncmp(daemon->pidfile, cfg->chrootdir, - strlen(cfg->chrootdir))==0) { - char* old = daemon->pidfile; - daemon->pidfile = strdup(old+strlen(cfg->chrootdir)); - free(old); - if(!daemon->pidfile) - log_err("out of memory in pidfile adjust"); - } - daemon->chroot = strdup(cfg->chrootdir); - if(!daemon->chroot) - log_err("out of memory in daemon chroot dir storage"); - } -#else - (void)cfgfile; -#endif - /* change to working directory inside chroot */ - if(cfg->directory && cfg->directory[0]) { - char* dir = cfg->directory; - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(dir, cfg->chrootdir, - strlen(cfg->chrootdir)) == 0) - dir += strlen(cfg->chrootdir); - if(dir[0]) { - if(chdir(dir)) { - fatal_exit("Could not chdir to %s: %s", - dir, strerror(errno)); - } - verbose(VERB_QUERY, "chdir to %s", dir); - } - } - - /* drop permissions after chroot, getpwnam, pidfile, syslog done*/ -#ifdef HAVE_GETPWNAM - if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { -# ifdef HAVE_INITGROUPS - if(initgroups(cfg->username, cfg_gid) != 0) - log_warn("unable to initgroups %s: %s", - cfg->username, strerror(errno)); -# endif /* HAVE_INITGROUPS */ -# ifdef HAVE_ENDPWENT - endpwent(); -# endif - -#ifdef HAVE_SETRESGID - if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0) -#elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) - if(setregid(cfg_gid,cfg_gid) != 0) -#else /* use setgid */ - if(setgid(cfg_gid) != 0) -#endif /* HAVE_SETRESGID */ - fatal_exit("unable to set group id of %s: %s", - cfg->username, strerror(errno)); -#ifdef HAVE_SETRESUID - if(setresuid(cfg_uid,cfg_uid,cfg_uid) != 0) -#elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) - if(setreuid(cfg_uid,cfg_uid) != 0) -#else /* use setuid */ - if(setuid(cfg_uid) != 0) -#endif /* HAVE_SETRESUID */ - fatal_exit("unable to set user id of %s: %s", - cfg->username, strerror(errno)); - verbose(VERB_QUERY, "drop user privileges, run as %s", - cfg->username); - } -#endif /* HAVE_GETPWNAM */ - /* file logging inited after chroot,chdir,setuid is done so that - * it would succeed on SIGHUP as well */ - if(!cfg->use_syslog) - log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); -} - -/** - * Run the daemon. - * @param cfgfile: the config file name. - * @param cmdline_verbose: verbosity resulting from commandline -v. - * These increase verbosity as specified in the config file. - * @param debug_mode: if set, do not daemonize. - * @param need_pidfile: if false, no pidfile is checked or created. - */ -static void -run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pidfile) -{ - struct config_file* cfg = NULL; - struct daemon* daemon = NULL; - int done_setup = 0; - - if(!(daemon = daemon_init())) - fatal_exit("alloc failure"); - while(!daemon->need_to_exit) { - if(done_setup) - verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING); - else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING); - - /* config stuff */ - if(!(cfg = config_create())) - fatal_exit("Could not alloc config defaults"); - if(!config_read(cfg, cfgfile, daemon->chroot)) { - if(errno != ENOENT) - fatal_exit("Could not read config file: %s." - " Maybe try unbound -dd, it stays on " - "the commandline to see more errors, " - "or unbound-checkconf", cfgfile); - log_warn("Continuing with default config settings"); - } - apply_settings(daemon, cfg, cmdline_verbose, debug_mode); - if(!done_setup) - config_lookup_uid(cfg); - - /* prepare */ - if(!daemon_open_shared_ports(daemon)) - fatal_exit("could not open ports"); - if(!done_setup) { - perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile); - done_setup = 1; - } else { - /* reopen log after HUP to facilitate log rotation */ - if(!cfg->use_syslog) - log_init(cfg->logfile, 0, cfg->chrootdir); - } - /* work */ - daemon_fork(daemon); - - /* clean up for restart */ - verbose(VERB_ALGO, "cleanup."); - daemon_cleanup(daemon); - config_delete(cfg); - } - verbose(VERB_ALGO, "Exit cleanup."); - /* this unlink may not work if the pidfile is located outside - * of the chroot/workdir or we no longer have permissions */ - if(daemon->pidfile) { - int fd; - /* truncate pidfile */ - fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644); - if(fd != -1) - close(fd); - /* delete pidfile */ - unlink(daemon->pidfile); - } - daemon_delete(daemon); -} - -/** getopt global, in case header files fail to declare it. */ -extern int optind; -/** getopt global, in case header files fail to declare it. */ -extern char* optarg; - -/** - * main program. Set options given commandline arguments. - * @param argc: number of commandline arguments. - * @param argv: array of commandline arguments. - * @return: exit status of the program. - */ -int -main(int argc, char* argv[]) -{ - int c; - const char* cfgfile = CONFIGFILE; - const char* winopt = NULL; - const char* log_ident_default; - int cmdline_verbose = 0; - int debug_mode = 0; - int need_pidfile = 1; - -#ifdef UB_ON_WINDOWS - int cmdline_cfg = 0; -#endif - - checklock_start(); - log_init(NULL, 0, NULL); - log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0]; - log_ident_set_default(log_ident_default); - log_ident_set(log_ident_default); - /* parse the options */ - while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) { - switch(c) { - case 'c': - cfgfile = optarg; -#ifdef UB_ON_WINDOWS - cmdline_cfg = 1; -#endif - break; - case 'v': - cmdline_verbose++; - verbosity++; - break; - case 'p': - need_pidfile = 0; - break; - case 'd': - debug_mode++; - break; - case 'w': - winopt = optarg; - break; - case 'V': - print_build_options(); - return 0; - case '?': - case 'h': - default: - usage(); - return 1; - } - } - argc -= optind; - /* argv += optind; not using further arguments */ - - if(winopt) { -#ifdef UB_ON_WINDOWS - wsvc_command_option(winopt, cfgfile, cmdline_verbose, - cmdline_cfg); -#else - fatal_exit("option not supported"); -#endif - } - - if(argc != 0) { - usage(); - return 1; - } - - run_daemon(cfgfile, cmdline_verbose, debug_mode, need_pidfile); - log_init(NULL, 0, NULL); /* close logfile */ -#ifndef unbound_testbound - if(log_get_lock()) { - lock_basic_destroy((lock_basic_type*)log_get_lock()); - } -#endif - return 0; -} diff --git a/crates/libunbound-sys/unbound/daemon/worker.c b/crates/libunbound-sys/unbound/daemon/worker.c deleted file mode 100644 index 8c6fa3b9..00000000 --- a/crates/libunbound-sys/unbound/daemon/worker.c +++ /dev/null @@ -1,2514 +0,0 @@ -/* - * daemon/worker.c - worker that handles a pending list of requests. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file implements the worker that handles callbacks on events, for - * pending requests. - */ -#include "config.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/random.h" -#include "daemon/worker.h" -#include "daemon/daemon.h" -#include "daemon/remote.h" -#include "daemon/acl_list.h" -#include "util/netevent.h" -#include "util/config_file.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/storage/slabhash.h" -#include "services/listen_dnsport.h" -#include "services/outside_network.h" -#include "services/outbound_list.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "services/cache/dns.h" -#include "services/authzone.h" -#include "services/mesh.h" -#include "services/localzone.h" -#include "services/rpz.h" -#include "util/data/msgparse.h" -#include "util/data/msgencode.h" -#include "util/data/dname.h" -#include "util/fptr_wlist.h" -#include "util/tube.h" -#include "util/edns.h" -#include "util/timeval_func.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_hints.h" -#include "iterator/iter_utils.h" -#include "validator/autotrust.h" -#include "validator/val_anchor.h" -#include "respip/respip.h" -#include "libunbound/context.h" -#include "libunbound/libworker.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "util/shm_side/shm_main.h" -#include "dnscrypt/dnscrypt.h" -#include "dnstap/dtstream.h" - -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#include -#ifdef UB_ON_WINDOWS -#include "winrc/win_svc.h" -#endif - -/** Size of an UDP datagram */ -#define NORMAL_UDP_SIZE 512 /* bytes */ -/** ratelimit for error responses */ -#define ERROR_RATELIMIT 100 /* qps */ - -/** - * seconds to add to prefetch leeway. This is a TTL that expires old rrsets - * earlier than they should in order to put the new update into the cache. - * This additional value is to make sure that if not all TTLs are equal in - * the message to be updated(and replaced), that rrsets with up to this much - * extra TTL are also replaced. This means that the resulting new message - * will have (most likely) this TTL at least, avoiding very small 'split - * second' TTLs due to operators choosing relative primes for TTLs (or so). - * Also has to be at least one to break ties (and overwrite cached entry). - */ -#define PREFETCH_EXPIRY_ADD 60 - -/** Report on memory usage by this thread and global */ -static void -worker_mem_report(struct worker* ATTR_UNUSED(worker), - struct serviced_query* ATTR_UNUSED(cur_serv)) -{ -#ifdef UNBOUND_ALLOC_STATS - /* measure memory leakage */ - extern size_t unbound_mem_alloc, unbound_mem_freed; - /* debug func in validator module */ - size_t total, front, back, mesh, msg, rrset, infra, ac, superac; - size_t me, iter, val, anch; - int i; -#ifdef CLIENT_SUBNET - size_t subnet = 0; -#endif /* CLIENT_SUBNET */ - if(verbosity < VERB_ALGO) - return; - front = listen_get_mem(worker->front); - back = outnet_get_mem(worker->back); - msg = slabhash_get_mem(worker->env.msg_cache); - rrset = slabhash_get_mem(&worker->env.rrset_cache->table); - infra = infra_get_mem(worker->env.infra_cache); - mesh = mesh_get_mem(worker->env.mesh); - ac = alloc_get_mem(worker->alloc); - superac = alloc_get_mem(&worker->daemon->superalloc); - anch = anchors_get_mem(worker->env.anchors); - iter = 0; - val = 0; - for(i=0; ienv.mesh->mods.num; i++) { - fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> - mods.mod[i]->get_mem)); - if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) - val += (*worker->env.mesh->mods.mod[i]->get_mem) - (&worker->env, i); -#ifdef CLIENT_SUBNET - else if(strcmp(worker->env.mesh->mods.mod[i]->name, - "subnetcache")==0) - subnet += (*worker->env.mesh->mods.mod[i]->get_mem) - (&worker->env, i); -#endif /* CLIENT_SUBNET */ - else iter += (*worker->env.mesh->mods.mod[i]->get_mem) - (&worker->env, i); - } - me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig) - + comm_point_get_mem(worker->cmd_com) - + sizeof(worker->rndstate) - + regional_get_mem(worker->scratchpad) - + sizeof(*worker->env.scratch_buffer) - + sldns_buffer_capacity(worker->env.scratch_buffer) - + forwards_get_mem(worker->env.fwds) - + hints_get_mem(worker->env.hints); - if(worker->thread_num == 0) - me += acl_list_get_mem(worker->daemon->acl); - if(cur_serv) { - me += serviced_get_mem(cur_serv); - } - total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me; -#ifdef CLIENT_SUBNET - total += subnet; - log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u " - "rrset=%u infra=%u iter=%u val=%u subnet=%u anchors=%u " - "alloccache=%u globalalloccache=%u me=%u", - (unsigned)total, (unsigned)front, (unsigned)back, - (unsigned)mesh, (unsigned)msg, (unsigned)rrset, (unsigned)infra, - (unsigned)iter, (unsigned)val, - (unsigned)subnet, (unsigned)anch, (unsigned)ac, - (unsigned)superac, (unsigned)me); -#else /* no CLIENT_SUBNET */ - log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u " - "rrset=%u infra=%u iter=%u val=%u anchors=%u " - "alloccache=%u globalalloccache=%u me=%u", - (unsigned)total, (unsigned)front, (unsigned)back, - (unsigned)mesh, (unsigned)msg, (unsigned)rrset, - (unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch, - (unsigned)ac, (unsigned)superac, (unsigned)me); -#endif /* CLIENT_SUBNET */ - log_info("Total heap memory estimate: %u total-alloc: %u " - "total-free: %u", (unsigned)total, - (unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed); -#else /* no UNBOUND_ALLOC_STATS */ - size_t val = 0; -#ifdef CLIENT_SUBNET - size_t subnet = 0; -#endif /* CLIENT_SUBNET */ - int i; - if(verbosity < VERB_QUERY) - return; - for(i=0; ienv.mesh->mods.num; i++) { - fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> - mods.mod[i]->get_mem)); - if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) - val += (*worker->env.mesh->mods.mod[i]->get_mem) - (&worker->env, i); -#ifdef CLIENT_SUBNET - else if(strcmp(worker->env.mesh->mods.mod[i]->name, - "subnetcache")==0) - subnet += (*worker->env.mesh->mods.mod[i]->get_mem) - (&worker->env, i); -#endif /* CLIENT_SUBNET */ - } -#ifdef CLIENT_SUBNET - verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u " - "subnet=%u", - (unsigned)slabhash_get_mem(worker->env.msg_cache), - (unsigned)slabhash_get_mem(&worker->env.rrset_cache->table), - (unsigned)infra_get_mem(worker->env.infra_cache), - (unsigned)val, (unsigned)subnet); -#else /* no CLIENT_SUBNET */ - verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u", - (unsigned)slabhash_get_mem(worker->env.msg_cache), - (unsigned)slabhash_get_mem(&worker->env.rrset_cache->table), - (unsigned)infra_get_mem(worker->env.infra_cache), - (unsigned)val); -#endif /* CLIENT_SUBNET */ -#endif /* UNBOUND_ALLOC_STATS */ -} - -void -worker_send_cmd(struct worker* worker, enum worker_commands cmd) -{ - uint32_t c = (uint32_t)htonl(cmd); - if(!tube_write_msg(worker->cmd, (uint8_t*)&c, sizeof(c), 0)) { - log_err("worker send cmd %d failed", (int)cmd); - } -} - -int -worker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info) -{ - struct outbound_entry* e = (struct outbound_entry*)arg; - struct worker* worker = e->qstate->env->worker; - struct serviced_query *sq = e->qsent; - - verbose(VERB_ALGO, "worker svcd callback for qstate %p", e->qstate); - if(error != 0) { - mesh_report_reply(worker->env.mesh, e, reply_info, error); - worker_mem_report(worker, sq); - return 0; - } - /* sanity check. */ - if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) - || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != - LDNS_PACKET_QUERY - || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { - /* error becomes timeout for the module as if this reply - * never arrived. */ - verbose(VERB_ALGO, "worker: bad reply handled as timeout"); - mesh_report_reply(worker->env.mesh, e, reply_info, - NETEVENT_TIMEOUT); - worker_mem_report(worker, sq); - return 0; - } - mesh_report_reply(worker->env.mesh, e, reply_info, NETEVENT_NOERROR); - worker_mem_report(worker, sq); - return 0; -} - -/** ratelimit error replies - * @param worker: the worker struct with ratelimit counter - * @param err: error code that would be wanted. - * @return value of err if okay, or -1 if it should be discarded instead. - */ -static int -worker_err_ratelimit(struct worker* worker, int err) -{ - if(worker->err_limit_time == *worker->env.now) { - /* see if limit is exceeded for this second */ - if(worker->err_limit_count++ > ERROR_RATELIMIT) - return -1; - } else { - /* new second, new limits */ - worker->err_limit_time = *worker->env.now; - worker->err_limit_count = 1; - } - return err; -} - -/** - * Structure holding the result of the worker_check_request function. - * Based on configuration it could be called up to four times; ideally should - * be called once. - */ -struct check_request_result { - int checked; - int value; -}; -/** check request sanity. - * @param pkt: the wire packet to examine for sanity. - * @param worker: parameters for checking. - * @param out: struct to update with the result. -*/ -static void -worker_check_request(sldns_buffer* pkt, struct worker* worker, - struct check_request_result* out) -{ - if(out->checked) return; - out->checked = 1; - if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) { - verbose(VERB_QUERY, "request too short, discarded"); - out->value = -1; - return; - } - if(sldns_buffer_limit(pkt) > NORMAL_UDP_SIZE && - worker->daemon->cfg->harden_large_queries) { - verbose(VERB_QUERY, "request too large, discarded"); - out->value = -1; - return; - } - if(LDNS_QR_WIRE(sldns_buffer_begin(pkt))) { - verbose(VERB_QUERY, "request has QR bit on, discarded"); - out->value = -1; - return; - } - if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))) { - LDNS_TC_CLR(sldns_buffer_begin(pkt)); - verbose(VERB_QUERY, "request bad, has TC bit on"); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); - return; - } - if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY && - LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY) { - verbose(VERB_QUERY, "request unknown opcode %d", - LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt))); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_NOTIMPL); - return; - } - if(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) != 1) { - verbose(VERB_QUERY, "request wrong nr qd=%d", - LDNS_QDCOUNT(sldns_buffer_begin(pkt))); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); - return; - } - if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 && - (LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 1 || - LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY)) { - verbose(VERB_QUERY, "request wrong nr an=%d", - LDNS_ANCOUNT(sldns_buffer_begin(pkt))); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); - return; - } - if(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) { - verbose(VERB_QUERY, "request wrong nr ns=%d", - LDNS_NSCOUNT(sldns_buffer_begin(pkt))); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); - return; - } - if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) { - verbose(VERB_QUERY, "request wrong nr ar=%d", - LDNS_ARCOUNT(sldns_buffer_begin(pkt))); - out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR); - return; - } - out->value = 0; - return; -} - -void -worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg, - size_t len, int error, void* arg) -{ - struct worker* worker = (struct worker*)arg; - enum worker_commands cmd; - if(error != NETEVENT_NOERROR) { - free(msg); - if(error == NETEVENT_CLOSED) - comm_base_exit(worker->base); - else log_info("control event: %d", error); - return; - } - if(len != sizeof(uint32_t)) { - fatal_exit("bad control msg length %d", (int)len); - } - cmd = sldns_read_uint32(msg); - free(msg); - switch(cmd) { - case worker_cmd_quit: - verbose(VERB_ALGO, "got control cmd quit"); - comm_base_exit(worker->base); - break; - case worker_cmd_stats: - verbose(VERB_ALGO, "got control cmd stats"); - server_stats_reply(worker, 1); - break; - case worker_cmd_stats_noreset: - verbose(VERB_ALGO, "got control cmd stats_noreset"); - server_stats_reply(worker, 0); - break; - case worker_cmd_remote: - verbose(VERB_ALGO, "got control cmd remote"); - daemon_remote_exec(worker); - break; - default: - log_err("bad command %d", (int)cmd); - break; - } -} - -/** check if a delegation is secure */ -static enum sec_status -check_delegation_secure(struct reply_info *rep) -{ - /* return smallest security status */ - size_t i; - enum sec_status sec = sec_status_secure; - enum sec_status s; - size_t num = rep->an_numrrsets + rep->ns_numrrsets; - /* check if answer and authority are OK */ - for(i=0; irrsets[i]->entry.data) - ->security; - if(s < sec) - sec = s; - } - /* in additional, only unchecked triggers revalidation */ - for(i=num; irrset_count; i++) { - s = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) - ->security; - if(s == sec_status_unchecked) - return s; - } - return sec; -} - -/** remove nonsecure from a delegation referral additional section */ -static void -deleg_remove_nonsecure_additional(struct reply_info* rep) -{ - /* we can simply edit it, since we are working in the scratch region */ - size_t i; - enum sec_status s; - - for(i = rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { - s = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) - ->security; - if(s != sec_status_secure) { - memmove(rep->rrsets+i, rep->rrsets+i+1, - sizeof(struct ub_packed_rrset_key*)* - (rep->rrset_count - i - 1)); - rep->ar_numrrsets--; - rep->rrset_count--; - i--; - } - } -} - -/** answer nonrecursive query from the cache */ -static int -answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, - uint16_t id, uint16_t flags, struct comm_reply* repinfo, - struct edns_data* edns) -{ - /* for a nonrecursive query return either: - * o an error (servfail; we try to avoid this) - * o a delegation (closest we have; this routine tries that) - * o the answer (checked by answer_from_cache) - * - * So, grab a delegation from the rrset cache. - * Then check if it needs validation, if so, this routine fails, - * so that iterator can prime and validator can verify rrsets. - */ - uint16_t udpsize = edns->udp_size; - int secure = 0; - time_t timenow = *worker->env.now; - int has_cd_bit = (flags&BIT_CD); - int must_validate = (!has_cd_bit || worker->env.cfg->ignore_cd) - && worker->env.need_to_validate; - struct dns_msg *msg = NULL; - struct delegpt *dp; - - dp = dns_cache_find_delegation(&worker->env, qinfo->qname, - qinfo->qname_len, qinfo->qtype, qinfo->qclass, - worker->scratchpad, &msg, timenow, 0, NULL, 0); - if(!dp) { /* no delegation, need to reprime */ - return 0; - } - /* In case we have a local alias, copy it into the delegation message. - * Shallow copy should be fine, as we'll be done with msg in this - * function. */ - msg->qinfo.local_alias = qinfo->local_alias; - if(must_validate) { - switch(check_delegation_secure(msg->rep)) { - case sec_status_unchecked: - /* some rrsets have not been verified yet, go and - * let validator do that */ - return 0; - case sec_status_bogus: - case sec_status_secure_sentinel_fail: - /* some rrsets are bogus, reply servfail */ - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, - msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - return 0; - /* Attach the cached EDE (RFC8914) */ - if(worker->env.cfg->ede && - msg->rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&edns->opt_list_out, - worker->scratchpad, msg->rep->reason_bogus, - msg->rep->reason_bogus_str); - } - error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, - &msg->qinfo, id, flags, edns); - if(worker->stats.extended) { - worker->stats.ans_bogus++; - worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL]++; - } - return 1; - case sec_status_secure: - /* all rrsets are secure */ - /* remove non-secure rrsets from the add. section*/ - if(worker->env.cfg->val_clean_additional) - deleg_remove_nonsecure_additional(msg->rep); - secure = 1; - break; - case sec_status_indeterminate: - case sec_status_insecure: - default: - /* not secure */ - secure = 0; - break; - } - } - /* return this delegation from the cache */ - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep, - (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - return 0; - msg->rep->flags |= BIT_QR|BIT_RA; - /* Attach the cached EDE (RFC8914) if CD bit is set and the answer is - * bogus. */ - if(worker->env.cfg->ede && has_cd_bit && - (check_delegation_secure(msg->rep) == sec_status_bogus || - check_delegation_secure(msg->rep) == sec_status_secure_sentinel_fail) && - msg->rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&edns->opt_list_out, - worker->scratchpad, msg->rep->reason_bogus, - msg->rep->reason_bogus_str); - } - if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags, - repinfo->c->buffer, 0, 1, worker->scratchpad, - udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { - if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, - LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, - &msg->qinfo, id, flags, edns); - } - if(worker->stats.extended) { - if(secure) worker->stats.ans_secure++; - server_stats_insrcode(&worker->stats, repinfo->c->buffer); - } - return 1; -} - -/** Apply, if applicable, a response IP action to a cached answer. - * If the answer is rewritten as a result of an action, '*encode_repp' will - * point to the reply info containing the modified answer. '*encode_repp' will - * be intact otherwise. - * It returns 1 on success, 0 otherwise. */ -static int -apply_respip_action(struct worker* worker, const struct query_info* qinfo, - struct respip_client_info* cinfo, struct reply_info* rep, - struct sockaddr_storage* addr, socklen_t addrlen, - struct ub_packed_rrset_key** alias_rrset, - struct reply_info** encode_repp, struct auth_zones* az) -{ - struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL}; - actinfo.action = respip_none; - - if(qinfo->qtype != LDNS_RR_TYPE_A && - qinfo->qtype != LDNS_RR_TYPE_AAAA && - qinfo->qtype != LDNS_RR_TYPE_ANY) - return 1; - - if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo, - alias_rrset, 0, worker->scratchpad, az, NULL)) - return 0; - - /* xxx_deny actions mean dropping the reply, unless the original reply - * was redirected to response-ip data. */ - if(actinfo.action == respip_always_deny || - ((actinfo.action == respip_deny || - actinfo.action == respip_inform_deny) && - *encode_repp == rep)) - *encode_repp = NULL; - - /* If address info is returned, it means the action should be an - * 'inform' variant and the information should be logged. */ - if(actinfo.addrinfo) { - respip_inform_print(&actinfo, qinfo->qname, - qinfo->qtype, qinfo->qclass, qinfo->local_alias, - addr, addrlen); - - if(worker->stats.extended && actinfo.rpz_used) { - if(actinfo.rpz_disabled) - worker->stats.rpz_action[RPZ_DISABLED_ACTION]++; - if(actinfo.rpz_cname_override) - worker->stats.rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++; - else - worker->stats.rpz_action[ - respip_action_to_rpz_action(actinfo.action)]++; - } - } - - return 1; -} - -/** answer query from the cache. - * Normally, the answer message will be built in repinfo->c->buffer; if the - * answer is supposed to be suppressed or the answer is supposed to be an - * incomplete CNAME chain, the buffer is explicitly cleared to signal the - * caller as such. In the latter case *partial_rep will point to the incomplete - * reply, and this function is (possibly) supposed to be called again with that - * *partial_rep value to complete the chain. In addition, if the query should - * be completely dropped, '*need_drop' will be set to 1. */ -static int -answer_from_cache(struct worker* worker, struct query_info* qinfo, - struct respip_client_info* cinfo, int* need_drop, int* is_expired_answer, - int* is_secure_answer, struct ub_packed_rrset_key** alias_rrset, - struct reply_info** partial_repp, - struct reply_info* rep, uint16_t id, uint16_t flags, - struct comm_reply* repinfo, struct edns_data* edns) -{ - time_t timenow = *worker->env.now; - uint16_t udpsize = edns->udp_size; - struct reply_info* encode_rep = rep; - struct reply_info* partial_rep = *partial_repp; - int has_cd_bit = (flags&BIT_CD); - int must_validate = (!has_cd_bit || worker->env.cfg->ignore_cd) - && worker->env.need_to_validate; - *partial_repp = NULL; /* avoid accidental further pass */ - - /* Check TTL */ - if(rep->ttl < timenow) { - /* Check if we need to serve expired now */ - if(worker->env.cfg->serve_expired && - !worker->env.cfg->serve_expired_client_timeout) { - if(worker->env.cfg->serve_expired_ttl && - rep->serve_expired_ttl < timenow) - return 0; - /* Ignore expired failure answers */ - if(FLAGS_GET_RCODE(rep->flags) != - LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(rep->flags) != - LDNS_RCODE_NXDOMAIN && - FLAGS_GET_RCODE(rep->flags) != - LDNS_RCODE_YXDOMAIN) - return 0; - if(!rrset_array_lock(rep->ref, rep->rrset_count, 0)) - return 0; - *is_expired_answer = 1; - } else { - /* the rrsets may have been updated in the meantime. - * we will refetch the message format from the - * authoritative server - */ - return 0; - } - } else { - if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow)) - return 0; - } - /* locked and ids and ttls are OK. */ - - /* check CNAME chain (if any) */ - if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type == - htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type == - htons(LDNS_RR_TYPE_DNAME))) { - if(!reply_check_cname_chain(qinfo, rep)) { - /* cname chain invalid, redo iterator steps */ - verbose(VERB_ALGO, "Cache reply: cname chain broken"); - goto bail_out; - } - } - /* check security status of the cached answer */ - if(must_validate && (rep->security == sec_status_bogus || - rep->security == sec_status_secure_sentinel_fail)) { - /* BAD cached */ - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep, - LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - goto bail_out; - /* Attach the cached EDE (RFC8914) */ - if(worker->env.cfg->ede && rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&edns->opt_list_out, - worker->scratchpad, rep->reason_bogus, - rep->reason_bogus_str); - } - error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, - qinfo, id, flags, edns); - rrset_array_unlock_touch(worker->env.rrset_cache, - worker->scratchpad, rep->ref, rep->rrset_count); - if(worker->stats.extended) { - worker->stats.ans_bogus ++; - worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++; - } - return 1; - } else if(rep->security == sec_status_unchecked && must_validate) { - verbose(VERB_ALGO, "Cache reply: unchecked entry needs " - "validation"); - goto bail_out; /* need to validate cache entry first */ - } else if(rep->security == sec_status_secure) { - if(reply_all_rrsets_secure(rep)) { - *is_secure_answer = 1; - } else { - if(must_validate) { - verbose(VERB_ALGO, "Cache reply: secure entry" - " changed status"); - goto bail_out; /* rrset changed, re-verify */ - } - *is_secure_answer = 0; - } - } else *is_secure_answer = 0; - - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */ - if((worker->daemon->use_response_ip || worker->daemon->use_rpz) && - !partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep, - &repinfo->client_addr, repinfo->client_addrlen, alias_rrset, - &encode_rep, worker->env.auth_zones)) { - goto bail_out; - } else if(partial_rep && - !respip_merge_cname(partial_rep, qinfo, rep, cinfo, - must_validate, &encode_rep, worker->scratchpad, - worker->env.auth_zones)) { - goto bail_out; - } - if(encode_rep != rep) { - /* if rewritten, it can't be considered "secure" */ - *is_secure_answer = 0; - } - if(!encode_rep || *alias_rrset) { - if(!encode_rep) - *need_drop = 1; - else { - /* If a partial CNAME chain is found, we first need to - * make a copy of the reply in the scratchpad so we - * can release the locks and lookup the cache again. */ - *partial_repp = reply_info_copy(encode_rep, NULL, - worker->scratchpad); - if(!*partial_repp) - goto bail_out; - } - } else { - if(*is_expired_answer == 1 && - worker->env.cfg->ede_serve_expired && worker->env.cfg->ede) { - EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out, - worker->scratchpad, LDNS_EDE_STALE_ANSWER, ""); - } - /* Attach the cached EDE (RFC8914) if CD bit is set and the - * answer is bogus. */ - if(*is_secure_answer == 0 && - worker->env.cfg->ede && has_cd_bit && - encode_rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&edns->opt_list_out, - worker->scratchpad, encode_rep->reason_bogus, - encode_rep->reason_bogus_str); - } - if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, encode_rep, - (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - goto bail_out; - if(!reply_info_answer_encode(qinfo, encode_rep, id, flags, - repinfo->c->buffer, timenow, 1, worker->scratchpad, - udpsize, edns, (int)(edns->bits & EDNS_DO), - *is_secure_answer)) { - if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, - NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo, - worker->scratchpad, worker->env.now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, - qinfo, id, flags, edns); - } - } - /* cannot send the reply right now, because blocking network syscall - * is bad while holding locks. */ - rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad, - rep->ref, rep->rrset_count); - /* go and return this buffer to the client */ - return 1; - -bail_out: - rrset_array_unlock_touch(worker->env.rrset_cache, - worker->scratchpad, rep->ref, rep->rrset_count); - return 0; -} - -/** Reply to client and perform prefetch to keep cache up to date. */ -static void -reply_and_prefetch(struct worker* worker, struct query_info* qinfo, - uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply, - int rpz_passthru, struct edns_option* opt_list) -{ - (void)opt_list; - /* first send answer to client to keep its latency - * as small as a cachereply */ - if(!noreply) { - if(repinfo->c->tcp_req_info) { - sldns_buffer_copy( - repinfo->c->tcp_req_info->spool_buffer, - repinfo->c->buffer); - } - comm_point_send_reply(repinfo); - } - server_stats_prefetch(&worker->stats, worker); -#ifdef CLIENT_SUBNET - /* Check if the subnet module is enabled. In that case pass over the - * comm_reply information for ECS generation later. The mesh states are - * unique when subnet is enabled. */ - if(modstack_find(&worker->env.mesh->mods, "subnetcache") != -1 - && worker->env.unique_mesh) { - mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway + - PREFETCH_EXPIRY_ADD, rpz_passthru, - &repinfo->client_addr, opt_list); - return; - } -#endif - /* create the prefetch in the mesh as a normal lookup without - * client addrs waiting, which has the cache blacklisted (to bypass - * the cache and go to the network for the data). */ - /* this (potentially) runs the mesh for the new query */ - mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway + - PREFETCH_EXPIRY_ADD, rpz_passthru, NULL, NULL); -} - -/** - * Fill CH class answer into buffer. Keeps query. - * @param pkt: buffer - * @param str: string to put into text record (<255). - * array of strings, every string becomes a text record. - * @param num: number of strings in array. - * @param edns: edns reply information. - * @param worker: worker with scratch region. - * @param repinfo: reply information for a communication point. - */ -static void -chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns, - struct worker* worker, struct comm_reply* repinfo) -{ - int i; - unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt)); - unsigned int cd = LDNS_CD_WIRE(sldns_buffer_begin(pkt)); - size_t udpsize = edns->udp_size; - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL, - LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - edns->opt_list_inplace_cb_out = NULL; - sldns_buffer_clear(pkt); - sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */ - sldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA)); - if(rd) LDNS_RD_SET(sldns_buffer_begin(pkt)); - if(cd) LDNS_CD_SET(sldns_buffer_begin(pkt)); - sldns_buffer_write_u16(pkt, 1); /* qdcount */ - sldns_buffer_write_u16(pkt, (uint16_t)num); /* ancount */ - sldns_buffer_write_u16(pkt, 0); /* nscount */ - sldns_buffer_write_u16(pkt, 0); /* arcount */ - (void)query_dname_len(pkt); /* skip qname */ - sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */ - sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */ - for(i=0; i255) len=255; /* cap size of TXT record */ - if(sldns_buffer_position(pkt)+2+2+2+4+2+1+len+ - calc_edns_field_size(edns) > udpsize) { - sldns_buffer_write_u16_at(pkt, 6, i); /* ANCOUNT */ - LDNS_TC_SET(sldns_buffer_begin(pkt)); - break; - } - sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */ - sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT); - sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH); - sldns_buffer_write_u32(pkt, 0); /* TTL */ - sldns_buffer_write_u16(pkt, sizeof(uint8_t) + len); - sldns_buffer_write_u8(pkt, len); - sldns_buffer_write(pkt, str[i], len); - } - sldns_buffer_flip(pkt); - if(sldns_buffer_capacity(pkt) >= - sldns_buffer_limit(pkt)+calc_edns_field_size(edns)) - attach_edns_record(pkt, edns); -} - -/** Reply with one string */ -static void -chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns, - struct worker* worker, struct comm_reply* repinfo) -{ - chaos_replystr(pkt, (char**)&str, 1, edns, worker, repinfo); -} - -/** - * Create CH class trustanchor answer. - * @param pkt: buffer - * @param edns: edns reply information. - * @param w: worker with scratch region. - * @param repinfo: reply information for a communication point. - */ -static void -chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w, - struct comm_reply* repinfo) -{ -#define TA_RESPONSE_MAX_TXT 16 /* max number of TXT records */ -#define TA_RESPONSE_MAX_TAGS 32 /* max number of tags printed per zone */ - char* str_array[TA_RESPONSE_MAX_TXT]; - uint16_t tags[TA_RESPONSE_MAX_TAGS]; - int num = 0; - struct trust_anchor* ta; - - if(!w->env.need_to_validate) { - /* no validator module, reply no trustanchors */ - chaos_replystr(pkt, NULL, 0, edns, w, repinfo); - return; - } - - /* fill the string with contents */ - lock_basic_lock(&w->env.anchors->lock); - RBTREE_FOR(ta, struct trust_anchor*, w->env.anchors->tree) { - char* str; - size_t i, numtag, str_len = 255; - if(num == TA_RESPONSE_MAX_TXT) continue; - str = (char*)regional_alloc(w->scratchpad, str_len); - if(!str) continue; - lock_basic_lock(&ta->lock); - numtag = anchor_list_keytags(ta, tags, TA_RESPONSE_MAX_TAGS); - if(numtag == 0) { - /* empty, insecure point */ - lock_basic_unlock(&ta->lock); - continue; - } - str_array[num] = str; - num++; - - /* spool name of anchor */ - (void)sldns_wire2str_dname_buf(ta->name, ta->namelen, str, str_len); - str_len -= strlen(str); str += strlen(str); - /* spool tags */ - for(i=0; ilock); - } - lock_basic_unlock(&w->env.anchors->lock); - - chaos_replystr(pkt, str_array, num, edns, w, repinfo); - regional_free_all(w->scratchpad); -} - -/** - * Answer CH class queries. - * @param w: worker - * @param qinfo: query info. Pointer into packet buffer. - * @param edns: edns info from query. - * @param repinfo: reply information for a communication point. - * @param pkt: packet buffer. - * @return: true if a reply is to be sent. - */ -static int -answer_chaos(struct worker* w, struct query_info* qinfo, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* pkt) -{ - struct config_file* cfg = w->env.cfg; - if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT) - return 0; - if(query_dname_compare(qinfo->qname, - (uint8_t*)"\002id\006server") == 0 || - query_dname_compare(qinfo->qname, - (uint8_t*)"\010hostname\004bind") == 0) - { - if(cfg->hide_identity) - return 0; - if(cfg->identity==NULL || cfg->identity[0]==0) { - char buf[MAXHOSTNAMELEN+1]; - if (gethostname(buf, MAXHOSTNAMELEN) == 0) { - buf[MAXHOSTNAMELEN] = 0; - chaos_replyonestr(pkt, buf, edns, w, repinfo); - } else { - log_err("gethostname: %s", strerror(errno)); - chaos_replyonestr(pkt, "no hostname", edns, w, repinfo); - } - } - else chaos_replyonestr(pkt, cfg->identity, edns, w, repinfo); - return 1; - } - if(query_dname_compare(qinfo->qname, - (uint8_t*)"\007version\006server") == 0 || - query_dname_compare(qinfo->qname, - (uint8_t*)"\007version\004bind") == 0) - { - if(cfg->hide_version) - return 0; - if(cfg->version==NULL || cfg->version[0]==0) - chaos_replyonestr(pkt, PACKAGE_STRING, edns, w, repinfo); - else chaos_replyonestr(pkt, cfg->version, edns, w, repinfo); - return 1; - } - if(query_dname_compare(qinfo->qname, - (uint8_t*)"\013trustanchor\007unbound") == 0) - { - if(cfg->hide_trustanchor) - return 0; - chaos_trustanchor(pkt, edns, w, repinfo); - return 1; - } - - return 0; -} - -/** - * Answer notify queries. These are notifies for authoritative zones, - * the reply is an ack that the notify has been received. We need to check - * access permission here. - * @param w: worker - * @param qinfo: query info. Pointer into packet buffer. - * @param edns: edns info from query. - * @param addr: client address. - * @param addrlen: client address length. - * @param pkt: packet buffer. - */ -static void -answer_notify(struct worker* w, struct query_info* qinfo, - struct edns_data* edns, sldns_buffer* pkt, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - int refused = 0; - int rcode = LDNS_RCODE_NOERROR; - uint32_t serial = 0; - int has_serial; - if(!w->env.auth_zones) return; - has_serial = auth_zone_parse_notify_serial(pkt, &serial); - if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname, - qinfo->qname_len, qinfo->qclass, addr, - addrlen, has_serial, serial, &refused)) { - rcode = LDNS_RCODE_NOERROR; - } else { - if(refused) - rcode = LDNS_RCODE_REFUSED; - else rcode = LDNS_RCODE_SERVFAIL; - } - - if(verbosity >= VERB_DETAIL) { - char buf[380]; - char zname[255+1]; - char sr[25]; - dname_str(qinfo->qname, zname); - sr[0]=0; - if(has_serial) - snprintf(sr, sizeof(sr), "serial %u ", - (unsigned)serial); - if(rcode == LDNS_RCODE_REFUSED) - snprintf(buf, sizeof(buf), - "refused NOTIFY %sfor %s from", sr, zname); - else if(rcode == LDNS_RCODE_SERVFAIL) - snprintf(buf, sizeof(buf), - "servfail for NOTIFY %sfor %s from", sr, zname); - else snprintf(buf, sizeof(buf), - "received NOTIFY %sfor %s from", sr, zname); - log_addr(VERB_DETAIL, buf, addr, addrlen); - } - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - error_encode(pkt, rcode, qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(pkt), - sldns_buffer_read_u16_at(pkt, 2), edns); - LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY); -} - -static int -deny_refuse(struct comm_point* c, enum acl_access acl, - enum acl_access deny, enum acl_access refuse, - struct worker* worker, struct comm_reply* repinfo, - struct acl_addr* acladdr, int ede, - struct check_request_result* check_result) -{ - if(acl == deny) { - if(verbosity >= VERB_ALGO) { - log_acl_action("dropped", &repinfo->client_addr, - repinfo->client_addrlen, acl, acladdr); - log_buf(VERB_ALGO, "dropped", c->buffer); - } - comm_point_drop_reply(repinfo); - if(worker->stats.extended) - worker->stats.unwanted_queries++; - return 0; - } else if(acl == refuse) { - size_t opt_rr_mark; - - if(verbosity >= VERB_ALGO) { - log_acl_action("refused", &repinfo->client_addr, - repinfo->client_addrlen, acl, acladdr); - log_buf(VERB_ALGO, "refuse", c->buffer); - } - - if(worker->stats.extended) - worker->stats.unwanted_queries++; - worker_check_request(c->buffer, worker, check_result); - if(check_result->value != 0) { - if(check_result->value != -1) { - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - check_result->value); - return 1; - } - comm_point_drop_reply(repinfo); - return 0; - } - /* worker_check_request() above guarantees that the buffer contains at - * least a header and that qdcount == 1 - */ - log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE - && LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1); - - sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */ - - /* check additional section is present and that we respond with EDEs */ - if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1 - || !ede) { - LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_REFUSED); - sldns_buffer_flip(c->buffer); - return 1; - } - - if (!query_dname_len(c->buffer)) { - LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_FORMERR); - sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); - sldns_buffer_flip(c->buffer); - return 1; - } - /* space available for query type and class? */ - if (sldns_buffer_remaining(c->buffer) < 2 * sizeof(uint16_t)) { - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_FORMERR); - LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); - sldns_buffer_flip(c->buffer); - return 1; - } - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_REFUSED); - - sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qtype */ - - sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qclass */ - - /* The OPT RR to be returned should come directly after - * the query, so mark this spot. - */ - opt_rr_mark = sldns_buffer_position(c->buffer); - - /* Skip through the RR records */ - if(LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)) != 0 || - LDNS_NSCOUNT(sldns_buffer_begin(c->buffer)) != 0) { - if(!skip_pkt_rrs(c->buffer, - ((int)LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)))+ - ((int)LDNS_NSCOUNT(sldns_buffer_begin(c->buffer))))) { - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_FORMERR); - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_set_position(c->buffer, opt_rr_mark); - sldns_buffer_flip(c->buffer); - return 1; - } - } - /* Do we have a valid OPT RR here? If not return REFUSED (could be a valid TSIG or something so no FORMERR) */ - /* domain name must be the root of length 1. */ - if(sldns_buffer_remaining(c->buffer) < 1 || *sldns_buffer_current(c->buffer) != 0) { - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_set_position(c->buffer, opt_rr_mark); - sldns_buffer_flip(c->buffer); - return 1; - } else { - sldns_buffer_skip(c->buffer, 1); /* skip root label */ - } - if(sldns_buffer_remaining(c->buffer) < 2 || - sldns_buffer_read_u16(c->buffer) != LDNS_RR_TYPE_OPT) { - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_set_position(c->buffer, opt_rr_mark); - sldns_buffer_flip(c->buffer); - return 1; - } - /* Write OPT RR directly after the query, - * so without the (possibly skipped) Answer and NS RRs - */ - LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_clear(c->buffer); /* reset write limit */ - sldns_buffer_set_position(c->buffer, opt_rr_mark); - - /* Check if OPT record can be written - * 17 == root label (1) + RR type (2) + UDP Size (2) - * + Fields (4) + rdata len (2) + EDE Option code (2) - * + EDE Option length (2) + EDE info-code (2) - */ - if (sldns_buffer_available(c->buffer, 17) == 0) { - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0); - sldns_buffer_flip(c->buffer); - return 1; - } - - LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 1); - - /* root label */ - sldns_buffer_write_u8(c->buffer, 0); - sldns_buffer_write_u16(c->buffer, LDNS_RR_TYPE_OPT); - sldns_buffer_write_u16(c->buffer, EDNS_ADVERTISED_SIZE); - - /* write OPT Record TTL Field */ - sldns_buffer_write_u32(c->buffer, 0); - - /* write rdata len: EDE option + length + info-code */ - sldns_buffer_write_u16(c->buffer, 6); - - /* write OPTIONS; add EDE option code */ - sldns_buffer_write_u16(c->buffer, LDNS_EDNS_EDE); - - /* write single EDE option length (for just 1 info-code) */ - sldns_buffer_write_u16(c->buffer, 2); - - /* write single EDE info-code */ - sldns_buffer_write_u16(c->buffer, LDNS_EDE_PROHIBITED); - - sldns_buffer_flip(c->buffer); - - verbose(VERB_ALGO, "attached EDE code: %d", LDNS_EDE_PROHIBITED); - - return 1; - - } - - return -1; -} - -static int -deny_refuse_all(struct comm_point* c, enum acl_access* acl, - struct worker* worker, struct comm_reply* repinfo, - struct acl_addr** acladdr, int ede, int check_proxy, - struct check_request_result* check_result) -{ - if(check_proxy) { - *acladdr = acl_addr_lookup(worker->daemon->acl, - &repinfo->remote_addr, repinfo->remote_addrlen); - } else { - *acladdr = acl_addr_lookup(worker->daemon->acl, - &repinfo->client_addr, repinfo->client_addrlen); - } - /* If there is no ACL based on client IP use the interface ACL. */ - if(!(*acladdr) && c->socket) { - *acladdr = c->socket->acl; - } - *acl = acl_get_control(*acladdr); - return deny_refuse(c, *acl, acl_deny, acl_refuse, worker, repinfo, - *acladdr, ede, check_result); -} - -static int -deny_refuse_non_local(struct comm_point* c, enum acl_access acl, - struct worker* worker, struct comm_reply* repinfo, - struct acl_addr* acladdr, int ede, - struct check_request_result* check_result) -{ - return deny_refuse(c, acl, acl_deny_non_local, acl_refuse_non_local, - worker, repinfo, acladdr, ede, check_result); -} - -/* Returns 1 if the ip rate limit check can happen before EDNS parsing, - * else 0 */ -static int -pre_edns_ip_ratelimit_check(enum acl_access acl) -{ - if(acl == acl_allow_cookie) return 0; - return 1; -} - -/* Check if the query is blocked by source IP rate limiting. - * Returns 1 if it passes the check, 0 otherwise. */ -static int -check_ip_ratelimit(struct worker* worker, struct sockaddr_storage* addr, - socklen_t addrlen, int has_cookie, sldns_buffer* pkt) -{ - if(!infra_ip_ratelimit_inc(worker->env.infra_cache, addr, addrlen, - *worker->env.now, has_cookie, - worker->env.cfg->ip_ratelimit_backoff, pkt)) { - /* See if we can pass through with slip factor */ - if(!has_cookie && worker->env.cfg->ip_ratelimit_factor != 0 && - ub_random_max(worker->env.rnd, - worker->env.cfg->ip_ratelimit_factor) == 0) { - char addrbuf[128]; - addr_to_str(addr, addrlen, addrbuf, sizeof(addrbuf)); - verbose(VERB_QUERY, "ip_ratelimit allowed through for " - "ip address %s because of slip in " - "ip_ratelimit_factor", addrbuf); - return 1; - } - return 0; - } - return 1; -} - -int -worker_handle_request(struct comm_point* c, void* arg, int error, - struct comm_reply* repinfo) -{ - struct worker* worker = (struct worker*)arg; - int ret; - hashvalue_type h; - struct lruhash_entry* e; - struct query_info qinfo; - struct edns_data edns; - struct edns_option* original_edns_list = NULL; - enum acl_access acl; - struct acl_addr* acladdr; - int pre_edns_ip_ratelimit = 1; - int rc = 0; - int need_drop = 0; - int is_expired_answer = 0; - int is_secure_answer = 0; - int rpz_passthru = 0; - long long wait_queue_time = 0; - /* We might have to chase a CNAME chain internally, in which case - * we'll have up to two replies and combine them to build a complete - * answer. These variables control this case. */ - struct ub_packed_rrset_key* alias_rrset = NULL; - struct reply_info* partial_rep = NULL; - struct query_info* lookup_qinfo = &qinfo; - struct query_info qinfo_tmp; /* placeholder for lookup_qinfo */ - struct respip_client_info* cinfo = NULL, cinfo_tmp; - struct timeval wait_time; - struct check_request_result check_result = {0,0}; - memset(&qinfo, 0, sizeof(qinfo)); - - if((error != NETEVENT_NOERROR && error != NETEVENT_DONE)|| !repinfo) { - /* some bad tcp query DNS formats give these error calls */ - verbose(VERB_ALGO, "handle request called with err=%d", error); - return 0; - } - - if (worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv)) { - timeval_subtract(&wait_time, worker->env.now_tv, &c->recv_tv); - wait_queue_time = wait_time.tv_sec * 1000000 + wait_time.tv_usec; - if (worker->stats.max_query_time_us < wait_queue_time) - worker->stats.max_query_time_us = wait_queue_time; - if(wait_queue_time > - (long long)(worker->env.cfg->sock_queue_timeout * 1000000)) { - /* count and drop queries that were sitting in the socket queue too long */ - worker->stats.num_queries_timed_out++; - return 0; - } - } - -#ifdef USE_DNSCRYPT - repinfo->max_udp_size = worker->daemon->cfg->max_udp_size; - if(!dnsc_handle_curved_request(worker->daemon->dnscenv, repinfo)) { - worker->stats.num_query_dnscrypt_crypted_malformed++; - return 0; - } - if(c->dnscrypt && !repinfo->is_dnscrypted) { - char buf[LDNS_MAX_DOMAINLEN+1]; - /* Check if this is unencrypted and asking for certs */ - worker_check_request(c->buffer, worker, &check_result); - if(check_result.value != 0) { - verbose(VERB_ALGO, - "dnscrypt: worker check request: bad query."); - log_addr(VERB_CLIENT,"from",&repinfo->client_addr, - repinfo->client_addrlen); - comm_point_drop_reply(repinfo); - return 0; - } - if(!query_info_parse(&qinfo, c->buffer)) { - verbose(VERB_ALGO, - "dnscrypt: worker parse request: formerror."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - comm_point_drop_reply(repinfo); - return 0; - } - dname_str(qinfo.qname, buf); - if(!(qinfo.qtype == LDNS_RR_TYPE_TXT && - strcasecmp(buf, - worker->daemon->dnscenv->provider_name) == 0)) { - verbose(VERB_ALGO, - "dnscrypt: not TXT \"%s\". Received: %s \"%s\"", - worker->daemon->dnscenv->provider_name, - sldns_rr_descript(qinfo.qtype)->_name, - buf); - comm_point_drop_reply(repinfo); - worker->stats.num_query_dnscrypt_cleartext++; - return 0; - } - worker->stats.num_query_dnscrypt_cert++; - sldns_buffer_rewind(c->buffer); - } else if(c->dnscrypt && repinfo->is_dnscrypted) { - worker->stats.num_query_dnscrypt_crypted++; - } -#endif -#ifdef USE_DNSTAP - /* - * sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler - */ - if(worker->dtenv.log_client_query_messages) { - log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen); - log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); - dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer, - ((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL)); - } -#endif - /* Check deny/refuse ACLs */ - if(repinfo->is_proxied) { - if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr, - worker->env.cfg->ede, 1, &check_result)) != -1) { - if(ret == 1) - goto send_reply; - return ret; - } - } - if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr, - worker->env.cfg->ede, 0, &check_result)) != -1) { - if(ret == 1) - goto send_reply; - return ret; - } - - worker_check_request(c->buffer, worker, &check_result); - if(check_result.value != 0) { - verbose(VERB_ALGO, "worker check request: bad query."); - log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen); - if(check_result.value != -1) { - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - check_result.value); - return 1; - } - comm_point_drop_reply(repinfo); - return 0; - } - - worker->stats.num_queries++; - pre_edns_ip_ratelimit = pre_edns_ip_ratelimit_check(acl); - - /* If the IP rate limiting check needs extra EDNS information (e.g., - * DNS Cookies) postpone the check until after EDNS is parsed. */ - if(pre_edns_ip_ratelimit) { - /* NOTE: we always check the repinfo->client_address. - * IP ratelimiting is implicitly disabled for proxies. */ - if(!check_ip_ratelimit(worker, &repinfo->client_addr, - repinfo->client_addrlen, 0, c->buffer)) { - worker->stats.num_queries_ip_ratelimited++; - comm_point_drop_reply(repinfo); - return 0; - } - } - - if(!query_info_parse(&qinfo, c->buffer)) { - verbose(VERB_ALGO, "worker parse request: formerror."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */ - if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) { - comm_point_drop_reply(repinfo); - return 0; - } - sldns_buffer_rewind(c->buffer); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_FORMERR); - goto send_reply; - } - if(worker->env.cfg->log_queries) { - char ip[128]; - addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip)); - log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass); - } - if(qinfo.qtype == LDNS_RR_TYPE_AXFR || - qinfo.qtype == LDNS_RR_TYPE_IXFR) { - verbose(VERB_ALGO, "worker request: refused zone transfer."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - sldns_buffer_rewind(c->buffer); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_REFUSED); - if(worker->stats.extended) { - worker->stats.qtype[qinfo.qtype]++; - } - goto send_reply; - } - if(qinfo.qtype == LDNS_RR_TYPE_OPT || - qinfo.qtype == LDNS_RR_TYPE_TSIG || - qinfo.qtype == LDNS_RR_TYPE_TKEY || - qinfo.qtype == LDNS_RR_TYPE_MAILA || - qinfo.qtype == LDNS_RR_TYPE_MAILB || - (qinfo.qtype >= 128 && qinfo.qtype <= 248)) { - verbose(VERB_ALGO, "worker request: formerror for meta-type."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) { - comm_point_drop_reply(repinfo); - return 0; - } - sldns_buffer_rewind(c->buffer); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_FORMERR); - if(worker->stats.extended) { - worker->stats.qtype[qinfo.qtype]++; - } - goto send_reply; - } - if((ret=parse_edns_from_query_pkt( - c->buffer, &edns, worker->env.cfg, c, repinfo, - (worker->env.now ? *worker->env.now : time(NULL)), - worker->scratchpad)) != 0) { - struct edns_data reply_edns; - verbose(VERB_ALGO, "worker parse edns: formerror."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - memset(&reply_edns, 0, sizeof(reply_edns)); - reply_edns.edns_present = 1; - error_encode(c->buffer, ret, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(edns.edns_present) { - if(edns.edns_version != 0) { - edns.opt_list_in = NULL; - edns.opt_list_out = NULL; - edns.opt_list_inplace_cb_out = NULL; - verbose(VERB_ALGO, "query with bad edns version."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - extended_error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), 0, &edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(edns.udp_size < NORMAL_UDP_SIZE && - worker->daemon->cfg->harden_short_bufsize) { - verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored", - (int)edns.udp_size); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - edns.udp_size = NORMAL_UDP_SIZE; - } - } - - /* Get stats for cookies */ - server_stats_downstream_cookie(&worker->stats, &edns); - - /* If the IP rate limiting check was postponed, check now. */ - if(!pre_edns_ip_ratelimit) { - /* NOTE: we always check the repinfo->client_address. - * IP ratelimiting is implicitly disabled for proxies. */ - if(!check_ip_ratelimit(worker, &repinfo->client_addr, - repinfo->client_addrlen, edns.cookie_valid, - c->buffer)) { - worker->stats.num_queries_ip_ratelimited++; - comm_point_drop_reply(repinfo); - return 0; - } - } - - /* "if, else if" sequence below deals with downstream DNS Cookies */ - if(acl != acl_allow_cookie) - ; /* pass; No cookie downstream processing whatsoever */ - - else if(edns.cookie_valid) - ; /* pass; Valid cookie is good! */ - - else if(c->type != comm_udp) - ; /* pass; Stateful transport */ - - else if(edns.cookie_present) { - /* Cookie present, but not valid: Cookie was bad! */ - extended_error_encode(c->buffer, - LDNS_EXT_RCODE_BADCOOKIE, &qinfo, - *(uint16_t*)(void *) - sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), - 0, &edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } else { - /* Cookie required, but no cookie present on UDP */ - verbose(VERB_ALGO, "worker request: " - "need cookie or stateful transport"); - log_addr(VERB_ALGO, "from",&repinfo->remote_addr - , repinfo->remote_addrlen); - EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out, - worker->scratchpad, LDNS_EDE_OTHER, - "DNS Cookie needed for UDP replies"); - error_encode(c->buffer, - (LDNS_RCODE_REFUSED|BIT_TC), &qinfo, - *(uint16_t*)(void *) - sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), - &edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } - - if(edns.udp_size > worker->daemon->cfg->max_udp_size && - c->type == comm_udp) { - verbose(VERB_QUERY, - "worker request: max UDP reply size modified" - " (%d to max-udp-size)", (int)edns.udp_size); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - edns.udp_size = worker->daemon->cfg->max_udp_size; - } - if(edns.udp_size < LDNS_HEADER_SIZE) { - verbose(VERB_ALGO, "worker request: edns is too small."); - log_addr(VERB_CLIENT, "from", &repinfo->client_addr, - repinfo->client_addrlen); - LDNS_QR_SET(sldns_buffer_begin(c->buffer)); - LDNS_TC_SET(sldns_buffer_begin(c->buffer)); - LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), - LDNS_RCODE_SERVFAIL); - sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); - sldns_buffer_write_at(c->buffer, 4, - (uint8_t*)"\0\0\0\0\0\0\0\0", 8); - sldns_buffer_flip(c->buffer); - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(worker->stats.extended) - server_stats_insquery(&worker->stats, c, qinfo.qtype, - qinfo.qclass, &edns, repinfo); - if(c->type != comm_udp) - edns.udp_size = 65535; /* max size for TCP replies */ - if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo, - &edns, repinfo, c->buffer)) { - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) == - LDNS_PACKET_NOTIFY) { - answer_notify(worker, &qinfo, &edns, c->buffer, - &repinfo->client_addr, repinfo->client_addrlen); - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(local_zones_answer(worker->daemon->local_zones, &worker->env, &qinfo, - &edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist, - acladdr->taglen, acladdr->tag_actions, - acladdr->tag_actions_size, acladdr->tag_datas, - acladdr->tag_datas_size, worker->daemon->cfg->tagname, - worker->daemon->cfg->num_tags, acladdr->view)) { - regional_free_all(worker->scratchpad); - if(sldns_buffer_limit(c->buffer) == 0) { - comm_point_drop_reply(repinfo); - return 0; - } - goto send_reply; - } - if(worker->env.auth_zones && - rpz_callback_from_worker_request(worker->env.auth_zones, - &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad, - repinfo, acladdr->taglist, acladdr->taglen, &worker->stats, - &rpz_passthru)) { - regional_free_all(worker->scratchpad); - if(sldns_buffer_limit(c->buffer) == 0) { - comm_point_drop_reply(repinfo); - return 0; - } - goto send_reply; - } - if(worker->env.auth_zones && - auth_zones_answer(worker->env.auth_zones, &worker->env, - &qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) { - regional_free_all(worker->scratchpad); - if(sldns_buffer_limit(c->buffer) == 0) { - comm_point_drop_reply(repinfo); - return 0; - } - /* set RA for everyone that can have recursion (based on - * access control list) */ - if(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer)) && - acl != acl_deny_non_local && acl != acl_refuse_non_local) - LDNS_RA_SET(sldns_buffer_begin(c->buffer)); - goto send_reply; - } - - /* We've looked in our local zones. If the answer isn't there, we - * might need to bail out based on ACLs now. */ - if((ret=deny_refuse_non_local(c, acl, worker, repinfo, acladdr, - worker->env.cfg->ede, &check_result)) != -1) - { - regional_free_all(worker->scratchpad); - if(ret == 1) - goto send_reply; - return ret; - } - - /* If this request does not have the recursion bit set, verify - * ACLs allow the recursion bit to be treated as set. */ - if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) && - acl == acl_allow_setrd ) { - LDNS_RD_SET(sldns_buffer_begin(c->buffer)); - } - - /* If this request does not have the recursion bit set, verify - * ACLs allow the snooping. */ - if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) && - acl != acl_allow_snoop ) { - if(worker->env.cfg->ede) { - EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out, - worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, ""); - } - error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), &edns); - regional_free_all(worker->scratchpad); - log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", - &repinfo->client_addr, repinfo->client_addrlen); - - goto send_reply; - } - - /* If we've found a local alias, replace the qname with the alias - * target before resolving it. */ - if(qinfo.local_alias) { - struct ub_packed_rrset_key* rrset = qinfo.local_alias->rrset; - struct packed_rrset_data* d = rrset->entry.data; - - /* Sanity check: our current implementation only supports - * a single CNAME RRset as a local alias. */ - if(qinfo.local_alias->next || - rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) || - d->count != 1) { - log_err("assumption failure: unexpected local alias"); - regional_free_all(worker->scratchpad); - return 0; /* drop it */ - } - qinfo.qname = d->rr_data[0] + 2; - qinfo.qname_len = d->rr_len[0] - 2; - } - - /* If we may apply IP-based actions to the answer, build the client - * information. As this can be expensive, skip it if there is - * absolutely no possibility of it. */ - if((worker->daemon->use_response_ip || worker->daemon->use_rpz) && - (qinfo.qtype == LDNS_RR_TYPE_A || - qinfo.qtype == LDNS_RR_TYPE_AAAA || - qinfo.qtype == LDNS_RR_TYPE_ANY)) { - cinfo_tmp.taglist = acladdr->taglist; - cinfo_tmp.taglen = acladdr->taglen; - cinfo_tmp.tag_actions = acladdr->tag_actions; - cinfo_tmp.tag_actions_size = acladdr->tag_actions_size; - cinfo_tmp.tag_datas = acladdr->tag_datas; - cinfo_tmp.tag_datas_size = acladdr->tag_datas_size; - cinfo_tmp.view = acladdr->view; - cinfo_tmp.respip_set = worker->daemon->respip_set; - cinfo = &cinfo_tmp; - } - - /* Keep the original edns list around. The pointer could change if there is - * a cached answer (through the inplace callback function there). - * No need to actually copy the contents as they shouldn't change. - * Used while prefetching and subnet is enabled. */ - original_edns_list = edns.opt_list_in; -lookup_cache: - /* Lookup the cache. In case we chase an intermediate CNAME chain - * this is a two-pass operation, and lookup_qinfo is different for - * each pass. We should still pass the original qinfo to - * answer_from_cache(), however, since it's used to build the reply. */ - if(!edns_bypass_cache_stage(edns.opt_list_in, &worker->env)) { - is_expired_answer = 0; - is_secure_answer = 0; - h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2)); - if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) { - struct reply_info* rep = (struct reply_info*)e->data; - /* answer from cache - we have acquired a readlock on it */ - if(answer_from_cache(worker, &qinfo, cinfo, &need_drop, - &is_expired_answer, &is_secure_answer, - &alias_rrset, &partial_rep, rep, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), repinfo, - &edns)) { - /* prefetch it if the prefetch TTL expired. - * Note that if there is more than one pass - * its qname must be that used for cache - * lookup. */ - if((worker->env.cfg->prefetch && - *worker->env.now >= rep->prefetch_ttl) || - (worker->env.cfg->serve_expired && - *worker->env.now > rep->ttl)) { - - time_t leeway = rep->ttl - *worker->env.now; - if(rep->ttl < *worker->env.now) - leeway = 0; - lock_rw_unlock(&e->lock); - - reply_and_prefetch(worker, lookup_qinfo, - sldns_buffer_read_u16_at(c->buffer, 2), - repinfo, leeway, - (partial_rep || need_drop), - rpz_passthru, - original_edns_list); - if(!partial_rep) { - rc = 0; - regional_free_all(worker->scratchpad); - goto send_reply_rc; - } - } else if(!partial_rep) { - lock_rw_unlock(&e->lock); - regional_free_all(worker->scratchpad); - goto send_reply; - } else { - /* Note that we've already released the - * lock if we're here after prefetch. */ - lock_rw_unlock(&e->lock); - } - /* We've found a partial reply ending with an - * alias. Replace the lookup qinfo for the - * alias target and lookup the cache again to - * (possibly) complete the reply. As we're - * passing the "base" reply, there will be no - * more alias chasing. */ - memset(&qinfo_tmp, 0, sizeof(qinfo_tmp)); - get_cname_target(alias_rrset, &qinfo_tmp.qname, - &qinfo_tmp.qname_len); - if(!qinfo_tmp.qname) { - log_err("unexpected: invalid answer alias"); - regional_free_all(worker->scratchpad); - return 0; /* drop query */ - } - qinfo_tmp.qtype = qinfo.qtype; - qinfo_tmp.qclass = qinfo.qclass; - lookup_qinfo = &qinfo_tmp; - goto lookup_cache; - } - verbose(VERB_ALGO, "answer from the cache failed"); - lock_rw_unlock(&e->lock); - } - - if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) { - if(answer_norec_from_cache(worker, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), repinfo, - &edns)) { - regional_free_all(worker->scratchpad); - goto send_reply; - } - verbose(VERB_ALGO, "answer norec from cache -- " - "need to validate or not primed"); - } - } - sldns_buffer_rewind(c->buffer); - server_stats_querymiss(&worker->stats, worker); - - if(verbosity >= VERB_CLIENT) { - if(c->type == comm_udp) - log_addr(VERB_CLIENT, "udp request from", - &repinfo->client_addr, repinfo->client_addrlen); - else log_addr(VERB_CLIENT, "tcp request from", - &repinfo->client_addr, repinfo->client_addrlen); - } - - /* grab a work request structure for this new request */ - mesh_new_client(worker->env.mesh, &qinfo, cinfo, - sldns_buffer_read_u16_at(c->buffer, 2), - &edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - rpz_passthru); - regional_free_all(worker->scratchpad); - worker_mem_report(worker, NULL); - return 0; - -send_reply: - rc = 1; -send_reply_rc: - if(need_drop) { - comm_point_drop_reply(repinfo); - return 0; - } - if(is_expired_answer) { - worker->stats.ans_expired++; - } - server_stats_insrcode(&worker->stats, c->buffer); - if(worker->stats.extended) { - if(is_secure_answer) worker->stats.ans_secure++; - } -#ifdef USE_DNSTAP - /* - * sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.) - */ - if(worker->dtenv.log_client_response_messages) { - log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); - log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); - dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer); - } -#endif - if(worker->env.cfg->log_replies) - { - struct timeval tv; - memset(&tv, 0, sizeof(tv)); - if(qinfo.local_alias && qinfo.local_alias->rrset && - qinfo.local_alias->rrset->rk.dname) { - /* log original qname, before the local alias was - * used to resolve that CNAME to something else */ - qinfo.qname = qinfo.local_alias->rrset->rk.dname; - log_reply_info(NO_VERBOSE, &qinfo, - &repinfo->client_addr, repinfo->client_addrlen, - tv, 1, c->buffer); - } else { - log_reply_info(NO_VERBOSE, &qinfo, - &repinfo->client_addr, repinfo->client_addrlen, - tv, 1, c->buffer); - } - } -#ifdef USE_DNSCRYPT - if(!dnsc_handle_uncurved_request(repinfo)) { - return 0; - } -#endif - return rc; -} - -void -worker_sighandler(int sig, void* arg) -{ - /* note that log, print, syscalls here give race conditions. - * And cause hangups if the log-lock is held by the application. */ - struct worker* worker = (struct worker*)arg; - switch(sig) { -#ifdef SIGHUP - case SIGHUP: - comm_base_exit(worker->base); - break; -#endif -#ifdef SIGBREAK - case SIGBREAK: -#endif - case SIGINT: - worker->need_to_exit = 1; - comm_base_exit(worker->base); - break; -#ifdef SIGQUIT - case SIGQUIT: - worker->need_to_exit = 1; - comm_base_exit(worker->base); - break; -#endif - case SIGTERM: - worker->need_to_exit = 1; - comm_base_exit(worker->base); - break; - default: - /* unknown signal, ignored */ - break; - } -} - -/** restart statistics timer for worker, if enabled */ -static void -worker_restart_timer(struct worker* worker) -{ - if(worker->env.cfg->stat_interval > 0) { - struct timeval tv; -#ifndef S_SPLINT_S - tv.tv_sec = worker->env.cfg->stat_interval; - tv.tv_usec = 0; -#endif - comm_timer_set(worker->stat_timer, &tv); - } -} - -void worker_stat_timer_cb(void* arg) -{ - struct worker* worker = (struct worker*)arg; - server_stats_log(&worker->stats, worker, worker->thread_num); - mesh_stats(worker->env.mesh, "mesh has"); - worker_mem_report(worker, NULL); - /* SHM is enabled, process data to SHM */ - if (worker->daemon->cfg->shm_enable) { - shm_main_run(worker); - } - if(!worker->daemon->cfg->stat_cumulative) { - worker_stats_clear(worker); - } - /* start next timer */ - worker_restart_timer(worker); -} - -void worker_probe_timer_cb(void* arg) -{ - struct worker* worker = (struct worker*)arg; - struct timeval tv; -#ifndef S_SPLINT_S - tv.tv_sec = (time_t)autr_probe_timer(&worker->env); - tv.tv_usec = 0; -#endif - if(tv.tv_sec != 0) - comm_timer_set(worker->env.probe_timer, &tv); -} - -struct worker* -worker_create(struct daemon* daemon, int id, int* ports, int n) -{ - unsigned int seed; - struct worker* worker = (struct worker*)calloc(1, - sizeof(struct worker)); - if(!worker) - return NULL; - worker->numports = n; - worker->ports = (int*)memdup(ports, sizeof(int)*n); - if(!worker->ports) { - free(worker); - return NULL; - } - worker->daemon = daemon; - worker->thread_num = id; - if(!(worker->cmd = tube_create())) { - free(worker->ports); - free(worker); - return NULL; - } - /* create random state here to avoid locking trouble in RAND_bytes */ - if(!(worker->rndstate = ub_initstate(daemon->rand))) { - log_err("could not init random numbers."); - tube_delete(worker->cmd); - free(worker->ports); - free(worker); - return NULL; - } - explicit_bzero(&seed, sizeof(seed)); - return worker; -} - -int -worker_init(struct worker* worker, struct config_file *cfg, - struct listen_port* ports, int do_sigs) -{ -#ifdef USE_DNSTAP - struct dt_env* dtenv = &worker->dtenv; -#else - void* dtenv = NULL; -#endif -#ifdef HAVE_GETTID - worker->thread_tid = gettid(); -#endif - worker->need_to_exit = 0; - worker->base = comm_base_create(do_sigs); - if(!worker->base) { - log_err("could not create event handling base"); - worker_delete(worker); - return 0; - } - comm_base_set_slow_accept_handlers(worker->base, &worker_stop_accept, - &worker_start_accept, worker); - if(do_sigs) { -#ifdef SIGHUP - ub_thread_sig_unblock(SIGHUP); -#endif -#ifdef SIGBREAK - ub_thread_sig_unblock(SIGBREAK); -#endif - ub_thread_sig_unblock(SIGINT); -#ifdef SIGQUIT - ub_thread_sig_unblock(SIGQUIT); -#endif - ub_thread_sig_unblock(SIGTERM); -#ifndef LIBEVENT_SIGNAL_PROBLEM - worker->comsig = comm_signal_create(worker->base, - worker_sighandler, worker); - if(!worker->comsig -#ifdef SIGHUP - || !comm_signal_bind(worker->comsig, SIGHUP) -#endif -#ifdef SIGQUIT - || !comm_signal_bind(worker->comsig, SIGQUIT) -#endif - || !comm_signal_bind(worker->comsig, SIGTERM) -#ifdef SIGBREAK - || !comm_signal_bind(worker->comsig, SIGBREAK) -#endif - || !comm_signal_bind(worker->comsig, SIGINT)) { - log_err("could not create signal handlers"); - worker_delete(worker); - return 0; - } -#endif /* LIBEVENT_SIGNAL_PROBLEM */ - if(!daemon_remote_open_accept(worker->daemon->rc, - worker->daemon->rc_ports, worker)) { - worker_delete(worker); - return 0; - } -#ifdef UB_ON_WINDOWS - wsvc_setup_worker(worker); -#endif /* UB_ON_WINDOWS */ - } else { /* !do_sigs */ - worker->comsig = NULL; - } -#ifdef USE_DNSTAP - if(cfg->dnstap) { - log_assert(worker->daemon->dtenv != NULL); - memcpy(&worker->dtenv, worker->daemon->dtenv, sizeof(struct dt_env)); - if(!dt_init(&worker->dtenv, worker->base)) - fatal_exit("dt_init failed"); - } -#endif - worker->front = listen_create(worker->base, ports, - cfg->msg_buffer_size, (int)cfg->incoming_num_tcp, - cfg->do_tcp_keepalive - ? cfg->tcp_keepalive_timeout - : cfg->tcp_idle_timeout, - cfg->harden_large_queries, cfg->http_max_streams, - cfg->http_endpoint, cfg->http_notls_downstream, - worker->daemon->tcl, worker->daemon->listen_sslctx, - dtenv, worker_handle_request, worker); - if(!worker->front) { - log_err("could not create listening sockets"); - worker_delete(worker); - return 0; - } - worker->back = outside_network_create(worker->base, - cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports, - cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, - cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp, - worker->daemon->env->infra_cache, worker->rndstate, - cfg->use_caps_bits_for_id, worker->ports, worker->numports, - cfg->unwanted_threshold, cfg->outgoing_tcp_mss, - &worker_alloc_cleanup, worker, - cfg->do_udp || cfg->udp_upstream_without_downstream, - worker->daemon->connect_sslctx, cfg->delay_close, - cfg->tls_use_sni, dtenv, cfg->udp_connect, - cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout, - cfg->tcp_auth_query_timeout); - if(!worker->back) { - log_err("could not create outgoing sockets"); - worker_delete(worker); - return 0; - } - iterator_set_ip46_support(&worker->daemon->mods, worker->daemon->env, - worker->back); - /* start listening to commands */ - if(!tube_setup_bg_listen(worker->cmd, worker->base, - &worker_handle_control_cmd, worker)) { - log_err("could not create control compt."); - worker_delete(worker); - return 0; - } - worker->stat_timer = comm_timer_create(worker->base, - worker_stat_timer_cb, worker); - if(!worker->stat_timer) { - log_err("could not create statistics timer"); - } - - /* we use the msg_buffer_size as a good estimate for what the - * user wants for memory usage sizes */ - worker->scratchpad = regional_create_custom(cfg->msg_buffer_size); - if(!worker->scratchpad) { - log_err("malloc failure"); - worker_delete(worker); - return 0; - } - - server_stats_init(&worker->stats, cfg); - worker->alloc = worker->daemon->worker_allocs[worker->thread_num]; - alloc_set_id_cleanup(worker->alloc, &worker_alloc_cleanup, worker); - worker->env = *worker->daemon->env; - comm_base_timept(worker->base, &worker->env.now, &worker->env.now_tv); - worker->env.worker = worker; - worker->env.worker_base = worker->base; - worker->env.send_query = &worker_send_query; - worker->env.alloc = worker->alloc; - worker->env.outnet = worker->back; - worker->env.rnd = worker->rndstate; - /* If case prefetch is triggered, the corresponding mesh will clear - * the scratchpad for the module env in the middle of request handling. - * It would be prone to a use-after-free kind of bug, so we avoid - * sharing it with worker's own scratchpad at the cost of having - * one more pad per worker. */ - worker->env.scratch = regional_create_custom(cfg->msg_buffer_size); - if(!worker->env.scratch) { - log_err("malloc failure"); - worker_delete(worker); - return 0; - } - worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env); - if(!worker->env.mesh) { - log_err("malloc failure"); - worker_delete(worker); - return 0; - } - /* Pass on daemon variables that we would need in the mesh area */ - worker->env.mesh->use_response_ip = worker->daemon->use_response_ip; - worker->env.mesh->use_rpz = worker->daemon->use_rpz; - - worker->env.detach_subs = &mesh_detach_subs; - worker->env.attach_sub = &mesh_attach_sub; - worker->env.add_sub = &mesh_add_sub; - worker->env.kill_sub = &mesh_state_delete; - worker->env.detect_cycle = &mesh_detect_cycle; - worker->env.scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size); - if(!worker->env.scratch_buffer) { - log_err("malloc failure"); - worker_delete(worker); - return 0; - } - if(!(worker->env.fwds = forwards_create()) || - !forwards_apply_cfg(worker->env.fwds, cfg)) { - log_err("Could not set forward zones"); - worker_delete(worker); - return 0; - } - if(!(worker->env.hints = hints_create()) || - !hints_apply_cfg(worker->env.hints, cfg)) { - log_err("Could not set root or stub hints"); - worker_delete(worker); - return 0; - } - /* one probe timer per process -- if we have 5011 anchors */ - if(autr_get_num_anchors(worker->env.anchors) > 0 -#ifndef THREADS_DISABLED - && worker->thread_num == 0 -#endif - ) { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - worker->env.probe_timer = comm_timer_create(worker->base, - worker_probe_timer_cb, worker); - if(!worker->env.probe_timer) { - log_err("could not create 5011-probe timer"); - } else { - /* let timer fire, then it can reset itself */ - comm_timer_set(worker->env.probe_timer, &tv); - } - } - /* zone transfer tasks, setup once per process, if any */ - if(worker->env.auth_zones -#ifndef THREADS_DISABLED - && worker->thread_num == 0 -#endif - ) { - auth_xfer_pickup_initial(worker->env.auth_zones, &worker->env); - auth_zones_pickup_zonemd_verify(worker->env.auth_zones, - &worker->env); - } -#ifdef USE_DNSTAP - if(worker->daemon->cfg->dnstap -#ifndef THREADS_DISABLED - && worker->thread_num == 0 -#endif - ) { - if(!dt_io_thread_start(dtenv->dtio, comm_base_internal( - worker->base), worker->daemon->num)) { - log_err("could not start dnstap io thread"); - worker_delete(worker); - return 0; - } - } -#endif /* USE_DNSTAP */ - worker_mem_report(worker, NULL); - /* if statistics enabled start timer */ - if(worker->env.cfg->stat_interval > 0) { - verbose(VERB_ALGO, "set statistics interval %d secs", - worker->env.cfg->stat_interval); - worker_restart_timer(worker); - } - return 1; -} - -void -worker_work(struct worker* worker) -{ - comm_base_dispatch(worker->base); -} - -void -worker_delete(struct worker* worker) -{ - if(!worker) - return; - if(worker->env.mesh && verbosity >= VERB_OPS) { - server_stats_log(&worker->stats, worker, worker->thread_num); - mesh_stats(worker->env.mesh, "mesh has"); - worker_mem_report(worker, NULL); - } - outside_network_quit_prepare(worker->back); - mesh_delete(worker->env.mesh); - sldns_buffer_free(worker->env.scratch_buffer); - forwards_delete(worker->env.fwds); - hints_delete(worker->env.hints); - listen_delete(worker->front); - outside_network_delete(worker->back); - comm_signal_delete(worker->comsig); - tube_delete(worker->cmd); - comm_timer_delete(worker->stat_timer); - comm_timer_delete(worker->env.probe_timer); - free(worker->ports); - if(worker->thread_num == 0) { -#ifdef UB_ON_WINDOWS - wsvc_desetup_worker(worker); -#endif /* UB_ON_WINDOWS */ - } -#ifdef USE_DNSTAP - if(worker->daemon->cfg->dnstap -#ifndef THREADS_DISABLED - && worker->thread_num == 0 -#endif - ) { - dt_io_thread_stop(worker->dtenv.dtio); - } - dt_deinit(&worker->dtenv); -#endif /* USE_DNSTAP */ - comm_base_delete(worker->base); - ub_randfree(worker->rndstate); - /* don't touch worker->alloc, as it's maintained in daemon */ - regional_destroy(worker->env.scratch); - regional_destroy(worker->scratchpad); - free(worker); -} - -struct outbound_entry* -worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, - int want_dnssec, int nocaps, int check_ratelimit, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, - struct module_qstate* q, int* was_ratelimited) -{ - struct worker* worker = q->env->worker; - struct outbound_entry* e = (struct outbound_entry*)regional_alloc( - q->region, sizeof(*e)); - if(!e) - return NULL; - e->qstate = q; - e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec, - want_dnssec, nocaps, check_ratelimit, tcp_upstream, - ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q, - worker_handle_service_reply, e, worker->back->udp_buff, q->env, - was_ratelimited); - if(!e->qsent) { - return NULL; - } - return e; -} - -void -worker_alloc_cleanup(void* arg) -{ - struct worker* worker = (struct worker*)arg; - slabhash_clear(&worker->env.rrset_cache->table); - slabhash_clear(worker->env.msg_cache); -} - -void worker_stats_clear(struct worker* worker) -{ - server_stats_init(&worker->stats, worker->env.cfg); - mesh_stats_clear(worker->env.mesh); - worker->back->unwanted_replies = 0; - worker->back->num_tcp_outgoing = 0; - worker->back->num_udp_outgoing = 0; -} - -void worker_start_accept(void* arg) -{ - struct worker* worker = (struct worker*)arg; - listen_start_accept(worker->front); - if(worker->thread_num == 0) - daemon_remote_start_accept(worker->daemon->rc); -} - -void worker_stop_accept(void* arg) -{ - struct worker* worker = (struct worker*)arg; - listen_stop_accept(worker->front); - if(worker->thread_num == 0) - daemon_remote_stop_accept(worker->daemon->rc); -} - -/* --- fake callbacks for fptr_wlist to work --- */ -struct outbound_entry* libworker_send_query( - struct query_info* ATTR_UNUSED(qinfo), - uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), - int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), - int ATTR_UNUSED(check_ratelimit), - struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), - uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), - int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), - struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); - return 0; -} - -int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), - uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), - int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) -{ - log_assert(0); - return 0; -} - -int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -#ifdef USE_DNSTAP -void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), - void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif - -#ifdef USE_DNSTAP -void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), - void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif diff --git a/crates/libunbound-sys/unbound/daemon/worker.h b/crates/libunbound-sys/unbound/daemon/worker.h deleted file mode 100644 index ab2fc728..00000000 --- a/crates/libunbound-sys/unbound/daemon/worker.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * daemon/worker.h - worker that handles a pending list of requests. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file describes the worker structure that holds a list of - * pending requests and handles them. - */ - -#ifndef DAEMON_WORKER_H -#define DAEMON_WORKER_H - -#include "libunbound/worker.h" -#include "util/netevent.h" -#include "util/locks.h" -#include "util/alloc.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -#include "daemon/stats.h" -#include "util/module.h" -#include "dnstap/dnstap.h" -struct listen_dnsport; -struct outside_network; -struct config_file; -struct daemon; -struct listen_port; -struct ub_randstate; -struct regional; -struct tube; -struct daemon_remote; -struct query_info; - -/** worker commands */ -enum worker_commands { - /** make the worker quit */ - worker_cmd_quit, - /** obtain statistics */ - worker_cmd_stats, - /** obtain statistics without statsclear */ - worker_cmd_stats_noreset, - /** execute remote control command */ - worker_cmd_remote -}; - -/** - * Structure holding working information for unbound. - * Holds globally visible information. - */ -struct worker { - /** the thread number (in daemon array). First in struct for debug. */ - int thread_num; - /** global shared daemon structure */ - struct daemon* daemon; - /** thread id */ - ub_thread_type thr_id; -#ifdef HAVE_GETTID - /** thread tid, the LWP id. */ - pid_t thread_tid; -#endif - /** pipe, for commands for this worker */ - struct tube* cmd; - /** the event base this worker works with */ - struct comm_base* base; - /** the frontside listening interface where request events come in */ - struct listen_dnsport* front; - /** the backside outside network interface to the auth servers */ - struct outside_network* back; - /** ports to be used by this worker. */ - int* ports; - /** number of ports for this worker */ - int numports; - /** the signal handler */ - struct comm_signal* comsig; - /** commpoint to listen to commands. */ - struct comm_point* cmd_com; - /** timer for statistics */ - struct comm_timer* stat_timer; - /** ratelimit for errors, time value */ - time_t err_limit_time; - /** ratelimit for errors, packet count */ - unsigned int err_limit_count; - - /** random() table for this worker. */ - struct ub_randstate* rndstate; - /** do we need to restart or quit (on signal) */ - int need_to_exit; - /** allocation cache for this thread */ - struct alloc_cache *alloc; - /** per thread statistics */ - struct ub_server_stats stats; - /** thread scratch regional */ - struct regional* scratchpad; - - /** module environment passed to modules, changed for this thread */ - struct module_env env; - -#ifdef USE_DNSTAP - /** dnstap environment, changed for this thread */ - struct dt_env dtenv; -#endif - /** reuse existing cache on reload if other conditions allow it. */ - int reuse_cache; -}; - -/** - * Create the worker structure. Bare bones version, zeroed struct, - * with backpointers only. Use worker_init on it later. - * @param daemon: the daemon that this worker thread is part of. - * @param id: the thread number from 0.. numthreads-1. - * @param ports: the ports it is allowed to use, array. - * @param n: the number of ports. - * @return: the new worker or NULL on alloc failure. - */ -struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n); - -/** - * Initialize worker. - * Allocates event base, listens to ports - * @param worker: worker to initialize, created with worker_create. - * @param cfg: configuration settings. - * @param ports: list of shared query ports. - * @param do_sigs: if true, worker installs signal handlers. - * @return: false on error. - */ -int worker_init(struct worker* worker, struct config_file *cfg, - struct listen_port* ports, int do_sigs); - -/** - * Make worker work. - */ -void worker_work(struct worker* worker); - -/** - * Delete worker. - */ -void worker_delete(struct worker* worker); - -/** - * Send a command to a worker. Uses blocking writes. - * @param worker: worker to send command to. - * @param cmd: command to send. - */ -void worker_send_cmd(struct worker* worker, enum worker_commands cmd); - -/** - * Init worker stats - includes server_stats_init, outside network and mesh. - * @param worker: the worker to init - */ -void worker_stats_clear(struct worker* worker); - -#endif /* DAEMON_WORKER_H */ diff --git a/crates/libunbound-sys/unbound/dns64/dns64.c b/crates/libunbound-sys/unbound/dns64/dns64.c deleted file mode 100644 index 1e31f51e..00000000 --- a/crates/libunbound-sys/unbound/dns64/dns64.c +++ /dev/null @@ -1,1043 +0,0 @@ -/* - * dns64/dns64.c - DNS64 module - * - * Copyright (c) 2009, Viagénie. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of Viagénie nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs DNS64 query processing. - */ - -#include "config.h" -#include "dns64/dns64.h" -#include "services/cache/dns.h" -#include "services/cache/rrset.h" -#include "util/config_file.h" -#include "util/data/msgreply.h" -#include "util/fptr_wlist.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/storage/dnstree.h" -#include "util/data/dname.h" -#include "sldns/str2wire.h" - -/****************************************************************************** - * * - * STATIC CONSTANTS * - * * - ******************************************************************************/ - -/** - * This is the default DNS64 prefix that is used when the dns64 module is listed - * in module-config but when the dns64-prefix variable is not present. - */ -static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96"; - -/** - * Maximum length of a domain name in a PTR query in the .in-addr.arpa tree. - */ -#define MAX_PTR_QNAME_IPV4 30 - -/** - * State of DNS64 processing for a query. - */ -enum dns64_state { - DNS64_INTERNAL_QUERY, /**< Internally-generated query, no DNS64 - processing. */ - DNS64_NEW_QUERY, /**< Query for which we're the first module in - line. */ - DNS64_SUBQUERY_FINISHED /**< Query for which we generated a sub-query, and - for which this sub-query is finished. */ -}; - -/** - * Per-query module-specific state. For the DNS64 module. - */ -struct dns64_qstate { - /** State of the DNS64 module. */ - enum dns64_state state; - /** If the dns64 module started with no_cache bool set in the qstate, - * a message to tell it to not modify the cache contents, then this - * is true. The dns64 module is then free to modify that flag for - * its own purposes. - * Otherwise, it is false, the dns64 module was not told to no_cache */ - int started_no_cache_store; -}; - -/****************************************************************************** - * * - * STRUCTURES * - * * - ******************************************************************************/ - -/** - * This structure contains module configuration information. One instance of - * this structure exists per instance of the module. Normally there is only one - * instance of the module. - */ -struct dns64_env { - /** - * DNS64 prefix address. We're using a full sockaddr instead of just an - * in6_addr because we can reuse Unbound's generic string parsing functions. - * It will always contain a sockaddr_in6, and only the sin6_addr member will - * ever be used. - */ - struct sockaddr_storage prefix_addr; - - /** - * This is always sizeof(sockaddr_in6). - */ - socklen_t prefix_addrlen; - - /** - * This is the CIDR length of the prefix. It needs to be between 0 and 96. - */ - int prefix_net; - - /** - * Tree of names for which AAAA is ignored. always synthesize from A. - */ - rbtree_type ignore_aaaa; -}; - - -/****************************************************************************** - * * - * UTILITY FUNCTIONS * - * * - ******************************************************************************/ - -/** - * Generic macro for swapping two variables. - * - * \param t Type of the variables. (e.g. int) - * \param a First variable. - * \param b Second variable. - * - * \warning Do not attempt something foolish such as swap(int,a++,b++)! - */ -#define swap(t,a,b) do {t x = a; a = b; b = x;} while(0) - -/** - * Reverses a string. - * - * \param begin Points to the first character of the string. - * \param end Points one past the last character of the string. - */ -static void -reverse(char* begin, char* end) -{ - while ( begin < --end ) { - swap(char, *begin, *end); - ++begin; - } -} - -/** - * Convert an unsigned integer to a string. The point of this function is that - * of being faster than sprintf(). - * - * \param n The number to be converted. - * \param s The result will be written here. Must be large enough, be careful! - * - * \return The number of characters written. - */ -static int -uitoa(unsigned n, char* s) -{ - char* ss = s; - do { - *ss++ = '0' + n % 10; - } while (n /= 10); - reverse(s, ss); - return ss - s; -} - -/** - * Extract an IPv4 address embedded in the IPv6 address \a ipv6 at offset \a - * offset (in bits). Note that bits are not necessarily aligned on bytes so we - * need to be careful. - * - * \param ipv6 IPv6 address represented as a 128-bit array in big-endian - * order. - * \param ipv6_len length of the ipv6 byte array. - * \param offset Index of the MSB of the IPv4 address embedded in the IPv6 - * address. - */ -static uint32_t -extract_ipv4(const uint8_t ipv6[], size_t ipv6_len, const int offset) -{ - uint32_t ipv4 = 0; - int i, pos; - log_assert(ipv6_len == 16); (void)ipv6_len; - log_assert(offset == 32 || offset == 40 || offset == 48 || offset == 56 || - offset == 64 || offset == 96); - for(i = 0, pos = offset / 8; i < 4; i++, pos++) { - if (pos == 8) - pos++; - ipv4 = ipv4 << 8; - ipv4 |= ipv6[pos]; - } - return ipv4; -} - -/** - * Builds the PTR query name corresponding to an IPv4 address. For example, - * given the number 3,464,175,361, this will build the string - * "\03206\03123\0231\011\07in-addr\04arpa". - * - * \param ipv4 IPv4 address represented as an unsigned 32-bit number. - * \param ptr The result will be written here. Must be large enough, be - * careful! - * \param nm_len length of the ptr buffer. - * - * \return The number of characters written. - */ -static size_t -ipv4_to_ptr(uint32_t ipv4, char ptr[], size_t nm_len) -{ - static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa"; - int i; - char* c = ptr; - log_assert(nm_len == MAX_PTR_QNAME_IPV4); (void)nm_len; - - for (i = 0; i < 4; ++i) { - *c = uitoa((unsigned int)(ipv4 % 256), c + 1); - c += *c + 1; - log_assert(c < ptr+nm_len); - ipv4 /= 256; - } - - log_assert(c + sizeof(IPV4_PTR_SUFFIX) <= ptr+nm_len); - memmove(c, IPV4_PTR_SUFFIX, sizeof(IPV4_PTR_SUFFIX)); - - return c + sizeof(IPV4_PTR_SUFFIX) - ptr; -} - -/** - * Converts an IPv6-related domain name string from a PTR query into an IPv6 - * address represented as a 128-bit array. - * - * \param ptr The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa") - * \param ipv6 The result will be written here, in network byte order. - * \param ipv6_len length of the ipv6 byte array. - * - * \return 1 on success, 0 on failure. - */ -static int -ptr_to_ipv6(const char* ptr, uint8_t ipv6[], size_t ipv6_len) -{ - int i; - log_assert(ipv6_len == 16); (void)ipv6_len; - - for (i = 0; i < 64; i++) { - int x; - - if (ptr[i++] != 1) - return 0; - - if (ptr[i] >= '0' && ptr[i] <= '9') { - x = ptr[i] - '0'; - } else if (ptr[i] >= 'a' && ptr[i] <= 'f') { - x = ptr[i] - 'a' + 10; - } else if (ptr[i] >= 'A' && ptr[i] <= 'F') { - x = ptr[i] - 'A' + 10; - } else { - return 0; - } - - ipv6[15-i/4] |= x << (2 * ((i-1) % 4)); - } - - return 1; -} - -/** - * Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix. - * - * \param prefix_addr DNS64 prefix address. - * \param prefix_addr_len length of the prefix_addr buffer. - * \param prefix_net CIDR length of the DNS64 prefix. Must be between 0 and 96. - * \param a IPv4 address. - * \param a_len length of the a buffer. - * \param aaaa IPv6 address. The result will be written here. - * \param aaaa_len length of the aaaa buffer. - */ -static void -synthesize_aaaa(const uint8_t prefix_addr[], size_t prefix_addr_len, - int prefix_net, const uint8_t a[], size_t a_len, uint8_t aaaa[], - size_t aaaa_len) -{ - size_t i; - int pos; - log_assert(prefix_addr_len == 16 && a_len == 4 && aaaa_len == 16); - log_assert(prefix_net == 32 || prefix_net == 40 || prefix_net == 48 || - prefix_net == 56 || prefix_net == 64 || prefix_net == 96); - (void)prefix_addr_len; (void)a_len; (void)aaaa_len; - memcpy(aaaa, prefix_addr, 16); - for(i = 0, pos = prefix_net / 8; i < a_len; i++, pos++) { - if(pos == 8) - aaaa[pos++] = 0; - aaaa[pos] = a[i]; - } -} - - -/****************************************************************************** - * * - * DNS64 MODULE FUNCTIONS * - * * - ******************************************************************************/ - -/** - * insert ignore_aaaa element into the tree - * @param dns64_env: module env. - * @param str: string with domain name. - * @return false on failure. - */ -static int -dns64_insert_ignore_aaaa(struct dns64_env* dns64_env, char* str) -{ - /* parse and insert element */ - struct name_tree_node* node; - node = (struct name_tree_node*)calloc(1, sizeof(*node)); - if(!node) { - log_err("out of memory"); - return 0; - } - node->name = sldns_str2wire_dname(str, &node->len); - if(!node->name) { - free(node); - log_err("cannot parse dns64-ignore-aaaa: %s", str); - return 0; - } - node->labs = dname_count_labels(node->name); - node->dclass = LDNS_RR_CLASS_IN; - if(!name_tree_insert(&dns64_env->ignore_aaaa, node, - node->name, node->len, node->labs, node->dclass)) { - /* ignore duplicate element */ - free(node->name); - free(node); - return 1; - } - return 1; -} - -/** - * This function applies the configuration found in the parsed configuration - * file \a cfg to this instance of the dns64 module. Currently only the DNS64 - * prefix (a.k.a. Pref64) is configurable. - * - * \param dns64_env Module-specific global parameters. - * \param cfg Parsed configuration file. - */ -static int -dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg) -{ - struct config_strlist* s; - verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix); - if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix : - DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr, - &dns64_env->prefix_addrlen, &dns64_env->prefix_net)) { - log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix); - return 0; - } - if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) { - log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix); - return 0; - } - if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 && - dns64_env->prefix_net != 48 && dns64_env->prefix_net != 56 && - dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) { - log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s", - cfg->dns64_prefix); - return 0; - } - for(s = cfg->dns64_ignore_aaaa; s; s = s->next) { - if(!dns64_insert_ignore_aaaa(dns64_env, s->str)) - return 0; - } - name_tree_init_parents(&dns64_env->ignore_aaaa); - return 1; -} - -/** - * Initializes this instance of the dns64 module. - * - * \param env Global state of all module instances. - * \param id This instance's ID number. - */ -int -dns64_init(struct module_env* env, int id) -{ - struct dns64_env* dns64_env = - (struct dns64_env*)calloc(1, sizeof(struct dns64_env)); - if (!dns64_env) { - log_err("malloc failure"); - return 0; - } - env->modinfo[id] = (void*)dns64_env; - name_tree_init(&dns64_env->ignore_aaaa); - if (!dns64_apply_cfg(dns64_env, env->cfg)) { - log_err("dns64: could not apply configuration settings."); - return 0; - } - return 1; -} - -/** free ignore AAAA elements */ -static void -free_ignore_aaaa_node(rbnode_type* node, void* ATTR_UNUSED(arg)) -{ - struct name_tree_node* n = (struct name_tree_node*)node; - if(!n) return; - free(n->name); - free(n); -} - -/** - * Deinitializes this instance of the dns64 module. - * - * \param env Global state of all module instances. - * \param id This instance's ID number. - */ -void -dns64_deinit(struct module_env* env, int id) -{ - struct dns64_env* dns64_env; - if (!env) - return; - dns64_env = (struct dns64_env*)env->modinfo[id]; - if(dns64_env) { - traverse_postorder(&dns64_env->ignore_aaaa, free_ignore_aaaa_node, - NULL); - } - free(env->modinfo[id]); - env->modinfo[id] = NULL; -} - -/** - * Handle PTR queries for IPv6 addresses. If the address belongs to the DNS64 - * prefix, we must do a PTR query for the corresponding IPv4 address instead. - * - * \param qstate Query state structure. - * \param id This module instance's ID number. - * - * \return The new state of the query. - */ -static enum module_ext_state -handle_ipv6_ptr(struct module_qstate* qstate, int id) -{ - struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id]; - struct module_qstate* subq = NULL; - struct query_info qinfo; - struct sockaddr_in6 sin6; - - /* Convert the PTR query string to an IPv6 address. */ - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr, - sizeof(sin6.sin6_addr.s6_addr))) - return module_wait_module; /* Let other module handle this. */ - - /* - * If this IPv6 address is not part of our DNS64 prefix, then we don't need - * to do anything. Let another module handle the query. - */ - if (addr_in_common((struct sockaddr_storage*)&sin6, 128, - &dns64_env->prefix_addr, dns64_env->prefix_net, - (socklen_t)sizeof(sin6)) != dns64_env->prefix_net) - return module_wait_module; - - verbose(VERB_ALGO, "dns64: rewrite PTR record"); - - /* - * Create a new PTR query info for the domain name corresponding to the IPv4 - * address corresponding to the IPv6 address corresponding to the original - * PTR query domain name. - */ - qinfo = qstate->qinfo; - if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4))) - return module_error; - qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr, - sizeof(sin6.sin6_addr.s6_addr), dns64_env->prefix_net), - (char*)qinfo.qname, MAX_PTR_QNAME_IPV4); - - /* Create the new sub-query. */ - fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0, - &subq)) - return module_error; - if (subq) { - subq->curmod = id; - subq->ext_state[id] = module_state_initial; - subq->minfo[id] = NULL; - } - - return module_wait_subquery; -} - -static enum module_ext_state -generate_type_A_query(struct module_qstate* qstate, int id) -{ - struct module_qstate* subq = NULL; - struct query_info qinfo; - - verbose(VERB_ALGO, "dns64: query A record"); - - /* Create a new query info. */ - qinfo = qstate->qinfo; - qinfo.qtype = LDNS_RR_TYPE_A; - - /* Start the sub-query. */ - fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, - 0, &subq)) - { - verbose(VERB_ALGO, "dns64: sub-query creation failed"); - return module_error; - } - if (subq) { - subq->curmod = id; - subq->ext_state[id] = module_state_initial; - subq->minfo[id] = NULL; - } - - return module_wait_subquery; -} - -/** - * See if query name is in the always synth config. - * The ignore-aaaa list has names for which the AAAA for the domain is - * ignored and the A is always used to create the answer. - * @param qstate: query state. - * @param id: module id. - * @return true if the name is covered by ignore-aaaa. - */ -static int -dns64_always_synth_for_qname(struct module_qstate* qstate, int id) -{ - struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id]; - int labs = dname_count_labels(qstate->qinfo.qname); - struct name_tree_node* node = name_tree_lookup(&dns64_env->ignore_aaaa, - qstate->qinfo.qname, qstate->qinfo.qname_len, labs, - qstate->qinfo.qclass); - return (node != NULL); -} - -/** - * Handles the "pass" event for a query. This event is received when a new query - * is received by this module. The query may have been generated internally by - * another module, in which case we don't want to do any special processing - * (this is an interesting discussion topic), or it may be brand new, e.g. - * received over a socket, in which case we do want to apply DNS64 processing. - * - * \param qstate A structure representing the state of the query that has just - * received the "pass" event. - * \param id This module's instance ID. - * - * \return The new state of the query. - */ -static enum module_ext_state -handle_event_pass(struct module_qstate* qstate, int id) -{ - struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id]; - if (iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR - && qstate->qinfo.qname_len == 74 - && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) - /* Handle PTR queries for IPv6 addresses. */ - return handle_ipv6_ptr(qstate, id); - - if (qstate->env->cfg->dns64_synthall && - iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) - return generate_type_A_query(qstate, id); - - if(dns64_always_synth_for_qname(qstate, id) && - iq && iq->state == DNS64_NEW_QUERY - && !(qstate->query_flags & BIT_CD) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); - return generate_type_A_query(qstate, id); - } - - /* We are finished when our sub-query is finished. */ - if (iq && iq->state == DNS64_SUBQUERY_FINISHED) - return module_finished; - - /* Otherwise, pass request to next module. */ - verbose(VERB_ALGO, "dns64: pass to next module"); - return module_wait_module; -} - -/** - * Handles the "done" event for a query. We need to analyze the response and - * maybe issue a new sub-query for the A record. - * - * \param qstate A structure representing the state of the query that has just - * received the "pass" event. - * \param id This module's instance ID. - * - * \return The new state of the query. - */ -static enum module_ext_state -handle_event_moddone(struct module_qstate* qstate, int id) -{ - struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id]; - /* - * In many cases we have nothing special to do. From most to least common: - * - * - An internal query. - * - A query for a record type other than AAAA. - * - CD FLAG was set on querier - * - An AAAA query for which an error was returned.(qstate.return_rcode) - * -> treated as servfail thus synthesize (sec 5.1.3 6147), thus - * synthesize in (sec 5.1.2 of RFC6147). - * - A successful AAAA query with an answer. - */ - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && !(qstate->return_msg && - qstate->return_msg->rep && - reply_find_answer_rrset(&qstate->qinfo, - qstate->return_msg->rep))) - /* not internal, type AAAA, not CD, and no answer RRset, - * So, this is a AAAA noerror/nodata answer */ - return generate_type_A_query(qstate, id); - - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && dns64_always_synth_for_qname(qstate, id)) { - /* if it is not internal, AAAA, not CD and listed domain, - * generate from A record and ignore AAAA */ - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); - return generate_type_A_query(qstate, id); - } - - /* Store the response in cache. */ - if ( (!iq || !iq->started_no_cache_store) && - qstate->return_msg && qstate->return_msg->rep && - !dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep, - 0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime)) - log_err("out of memory"); - - /* do nothing */ - return module_finished; -} - -/** - * This is the module's main() function. It gets called each time a query - * receives an event which we may need to handle. We respond by updating the - * state of the query. - * - * \param qstate Structure containing the state of the query. - * \param event Event that has just been received. - * \param id This module's instance ID. - * \param outbound State of a DNS query on an authoritative server. We never do - * our own queries ourselves (other modules do it for us), so - * this is unused. - */ -void -dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct dns64_qstate* iq; - (void)outbound; - verbose(VERB_QUERY, "dns64[module %d] operate: extstate:%s event:%s", - id, strextstate(qstate->ext_state[id]), - strmodulevent(event)); - log_query_info(VERB_QUERY, "dns64 operate: query", &qstate->qinfo); - - switch(event) { - case module_event_new: - /* Tag this query as being new and fall through. */ - if (!(iq = (struct dns64_qstate*)regional_alloc( - qstate->region, sizeof(*iq)))) { - log_err("out of memory"); - qstate->ext_state[id] = module_error; - return; - } - qstate->minfo[id] = iq; - iq->state = DNS64_NEW_QUERY; - iq->started_no_cache_store = qstate->no_cache_store; - qstate->no_cache_store = 1; - /* fallthrough */ - case module_event_pass: - qstate->ext_state[id] = handle_event_pass(qstate, id); - break; - case module_event_moddone: - qstate->ext_state[id] = handle_event_moddone(qstate, id); - break; - default: - qstate->ext_state[id] = module_finished; - break; - } - if(qstate->ext_state[id] == module_finished) { - iq = (struct dns64_qstate*)qstate->minfo[id]; - if(iq && iq->state != DNS64_INTERNAL_QUERY) - qstate->no_cache_store = iq->started_no_cache_store; - } -} - -static void -dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk, - const struct packed_rrset_data* fd, - struct ub_packed_rrset_key *dk, - struct packed_rrset_data **dd_out, struct regional *region, - struct dns64_env* dns64_env ) -{ - struct packed_rrset_data *dd; - size_t i; - /* - * Create synthesized AAAA RR set data. We need to allocated extra memory - * for the RRs themselves. Each RR has a length, TTL, pointer to wireformat - * data, 2 bytes of data length, and 16 bytes of IPv6 address. - */ - if(fd->count > RR_COUNT_MAX) { - *dd_out = NULL; - return; /* integer overflow protection in alloc */ - } - if (!(dd = *dd_out = regional_alloc_zero(region, - sizeof(struct packed_rrset_data) - + fd->count * (sizeof(size_t) + sizeof(time_t) + - sizeof(uint8_t*) + 2 + 16)))) { - log_err("out of memory"); - return; - } - - /* Copy attributes from A RR set. */ - dd->ttl = fd->ttl; - dd->count = fd->count; - dd->rrsig_count = 0; - dd->trust = fd->trust; - dd->security = fd->security; - - /* - * Synthesize AAAA records. Adjust pointers in structure. - */ - dd->rr_len = - (size_t*)((uint8_t*)dd + sizeof(struct packed_rrset_data)); - dd->rr_data = (uint8_t**)&dd->rr_len[dd->count]; - dd->rr_ttl = (time_t*)&dd->rr_data[dd->count]; - for(i = 0; i < fd->count; ++i) { - if (fd->rr_len[i] != 6 || fd->rr_data[i][0] != 0 - || fd->rr_data[i][1] != 4) { - *dd_out = NULL; - return; - } - dd->rr_len[i] = 18; - dd->rr_data[i] = - (uint8_t*)&dd->rr_ttl[dd->count] + 18*i; - dd->rr_data[i][0] = 0; - dd->rr_data[i][1] = 16; - synthesize_aaaa( - ((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr, - sizeof(((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr), - dns64_env->prefix_net, &fd->rr_data[i][2], - fd->rr_len[i]-2, &dd->rr_data[i][2], - dd->rr_len[i]-2); - dd->rr_ttl[i] = fd->rr_ttl[i]; - } - - /* - * Create synthesized AAAA RR set key. This is mostly just bookkeeping, - * nothing interesting here. - */ - if(!dk) { - log_err("no key"); - *dd_out = NULL; - return; - } - - dk->rk.dname = (uint8_t*)regional_alloc_init(region, - fk->rk.dname, fk->rk.dname_len); - - if(!dk->rk.dname) { - log_err("out of memory"); - *dd_out = NULL; - return; - } - - dk->rk.type = htons(LDNS_RR_TYPE_AAAA); - memset(&dk->entry, 0, sizeof(dk->entry)); - dk->entry.key = dk; - dk->entry.hash = rrset_key_hash(&dk->rk); - dk->entry.data = dd; - -} - -/** - * Synthesize an AAAA RR set from an A sub-query's answer and add it to the - * original empty response. - * - * \param id This module's instance ID. - * \param super Original AAAA query. - * \param qstate A query. - */ -static void -dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate) -{ - struct dns64_env* dns64_env = (struct dns64_env*)super->env->modinfo[id]; - struct reply_info *rep, *cp; - size_t i, s; - struct packed_rrset_data* fd, *dd; - struct ub_packed_rrset_key* fk, *dk; - - verbose(VERB_ALGO, "converting A answers to AAAA answers"); - - log_assert(super->region); - log_assert(qstate->return_msg); - log_assert(qstate->return_msg->rep); - - /* If dns64-synthall is enabled, return_msg is not initialized */ - if(!super->return_msg) { - super->return_msg = (struct dns_msg*)regional_alloc( - super->region, sizeof(struct dns_msg)); - if(!super->return_msg) - return; - memset(super->return_msg, 0, sizeof(*super->return_msg)); - super->return_msg->qinfo = super->qinfo; - } - - rep = qstate->return_msg->rep; - - /* - * Build the actual reply. - */ - cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount, - rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl, - rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets, - rep->rrset_count, rep->security, LDNS_EDE_NONE); - if(!cp) - return; - - /* allocate ub_key structures special or not */ - if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) { - return; - } - - /* copy everything and replace A by AAAA */ - for(i=0; irrset_count; i++) { - fk = rep->rrsets[i]; - dk = cp->rrsets[i]; - fd = (struct packed_rrset_data*)fk->entry.data; - dk->rk = fk->rk; - dk->id = fk->id; - - if(ian_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) { - /* also sets dk->entry.hash */ - dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env); - if(!dd) - return; - /* Delete negative AAAA record from cache stored by - * the iterator module */ - rrset_cache_remove(super->env->rrset_cache, dk->rk.dname, - dk->rk.dname_len, LDNS_RR_TYPE_AAAA, - LDNS_RR_CLASS_IN, 0); - /* Delete negative AAAA in msg cache for CNAMEs, - * stored by the iterator module */ - if(i != 0) /* if not the first RR */ - msg_cache_remove(super->env, dk->rk.dname, - dk->rk.dname_len, LDNS_RR_TYPE_AAAA, - LDNS_RR_CLASS_IN, 0); - } else { - dk->entry.hash = fk->entry.hash; - dk->rk.dname = (uint8_t*)regional_alloc_init(super->region, - fk->rk.dname, fk->rk.dname_len); - - if(!dk->rk.dname) - return; - - s = packed_rrset_sizeof(fd); - dd = (struct packed_rrset_data*)regional_alloc_init( - super->region, fd, s); - - if(!dd) - return; - } - - packed_rrset_ptr_fixup(dd); - dk->entry.data = (void*)dd; - } - - /* Commit changes. */ - super->return_msg->rep = cp; -} - -/** - * Generate a response for the original IPv6 PTR query based on an IPv4 PTR - * sub-query's response. - * - * \param qstate IPv4 PTR sub-query. - * \param super Original IPv6 PTR query. - */ -static void -dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super) -{ - struct ub_packed_rrset_key* answer; - - verbose(VERB_ALGO, "adjusting PTR reply"); - - /* Copy the sub-query's reply to the parent. */ - if (!(super->return_msg = (struct dns_msg*)regional_alloc(super->region, - sizeof(struct dns_msg)))) - return; - super->return_msg->qinfo = super->qinfo; - if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, - NULL, super->region))) - return; - - /* - * Adjust the domain name of the answer RR set so that it matches the - * initial query's domain name. - */ - answer = reply_find_answer_rrset(&qstate->qinfo, super->return_msg->rep); - if(answer) { - answer->rk.dname = super->qinfo.qname; - answer->rk.dname_len = super->qinfo.qname_len; - } -} - -/** - * This function is called when a sub-query finishes to inform the parent query. - * - * We issue two kinds of sub-queries: PTR and A. - * - * \param qstate State of the sub-query. - * \param id This module's instance ID. - * \param super State of the super-query. - */ -void -dns64_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) -{ - struct dns64_qstate* super_dq = (struct dns64_qstate*)super->minfo[id]; - log_query_info(VERB_ALGO, "dns64: inform_super, sub is", - &qstate->qinfo); - log_query_info(VERB_ALGO, "super is", &super->qinfo); - - /* - * Signal that the sub-query is finished, no matter whether we are - * successful or not. This lets the state machine terminate. - */ - if(!super_dq) { - super_dq = (struct dns64_qstate*)regional_alloc(super->region, - sizeof(*super_dq)); - if(!super_dq) { - log_err("out of memory"); - super->return_rcode = LDNS_RCODE_SERVFAIL; - super->return_msg = NULL; - return; - } - super->minfo[id] = super_dq; - memset(super_dq, 0, sizeof(*super_dq)); - super_dq->started_no_cache_store = super->no_cache_store; - } - super_dq->state = DNS64_SUBQUERY_FINISHED; - - /* If there is no successful answer, we're done. */ - if (qstate->return_rcode != LDNS_RCODE_NOERROR - || !qstate->return_msg - || !qstate->return_msg->rep) { - return; - } - - /* Use return code from A query in response to client. */ - if (super->return_rcode != LDNS_RCODE_NOERROR) - super->return_rcode = qstate->return_rcode; - - /* Generate a response suitable for the original query. */ - if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) { - dns64_adjust_a(id, super, qstate); - } else { - log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR); - dns64_adjust_ptr(qstate, super); - } - - /* Store the generated response in cache. */ - if ( (!super_dq || !super_dq->started_no_cache_store) && - !dns_cache_store(super->env, &super->qinfo, super->return_msg->rep, - 0, 0, 0, NULL, super->query_flags, qstate->qstarttime)) - log_err("out of memory"); -} - -/** - * Clear module-specific data from query state. Since we do not allocate memory, - * it's just a matter of setting a pointer to NULL. - * - * \param qstate Query state. - * \param id This module's instance ID. - */ -void -dns64_clear(struct module_qstate* qstate, int id) -{ - qstate->minfo[id] = NULL; -} - -/** - * Returns the amount of global memory that this module uses, not including - * per-query data. - * - * \param env Module environment. - * \param id This module's instance ID. - */ -size_t -dns64_get_mem(struct module_env* env, int id) -{ - struct dns64_env* dns64_env = (struct dns64_env*)env->modinfo[id]; - if (!dns64_env) - return 0; - return sizeof(*dns64_env); -} - -/** - * The dns64 function block. - */ -static struct module_func_block dns64_block = { - "dns64", - &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super, - &dns64_clear, &dns64_get_mem -}; - -/** - * Function for returning the above function block. - */ -struct module_func_block * -dns64_get_funcblock(void) -{ - return &dns64_block; -} diff --git a/crates/libunbound-sys/unbound/dns64/dns64.h b/crates/libunbound-sys/unbound/dns64/dns64.h deleted file mode 100644 index 2f0c01a2..00000000 --- a/crates/libunbound-sys/unbound/dns64/dns64.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * dns64/dns64.h - DNS64 module - * - * Copyright (c) 2009, Viagénie. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs DNS64 query processing. - */ - -#ifndef DNS64_DNS64_H -#define DNS64_DNS64_H -#include "util/module.h" - -/** - * Get the dns64 function block. - * @return: function block with function pointers to dns64 methods. - */ -struct module_func_block *dns64_get_funcblock(void); - -/** dns64 init */ -int dns64_init(struct module_env* env, int id); - -/** dns64 deinit */ -void dns64_deinit(struct module_env* env, int id); - -/** dns64 operate on a query */ -void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound); - -void dns64_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** dns64 cleanup query state */ -void dns64_clear(struct module_qstate* qstate, int id); - -/** dns64 alloc size routine */ -size_t dns64_get_mem(struct module_env* env, int id); - -#endif /* DNS64_DNS64_H */ diff --git a/crates/libunbound-sys/unbound/dnscrypt/cert.h b/crates/libunbound-sys/unbound/dnscrypt/cert.h deleted file mode 100644 index 7cad146d..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/cert.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef UNBOUND_DNSCRYPT_CERT_H -#define UNBOUND_DNSCRYPT_CERT_H - -/** - * \file - * certificate type for dnscrypt for use in other header files - */ - -#include -#define CERT_MAGIC_CERT "DNSC" -#define CERT_MAJOR_VERSION 1 -#define CERT_MINOR_VERSION 0 -#define CERT_OLD_MAGIC_HEADER "7PYqwfzt" - -#define CERT_FILE_EXPIRE_DAYS 365 - -struct SignedCert { - uint8_t magic_cert[4]; - uint8_t version_major[2]; - uint8_t version_minor[2]; - - // Signed Content - uint8_t signed_content[64]; - uint8_t server_publickey[crypto_box_PUBLICKEYBYTES]; - uint8_t magic_query[8]; - uint8_t serial[4]; - uint8_t ts_begin[4]; - uint8_t ts_end[4]; -}; - - -#endif diff --git a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.c b/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.c deleted file mode 100644 index 4902447f..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.c +++ /dev/null @@ -1,1110 +0,0 @@ - -#include "config.h" -#include -#include -#ifdef HAVE_TIME_H -#include -#endif -#include -#include -#include -#include "sldns/sbuffer.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/netevent.h" -#include "util/log.h" -#include "util/storage/slabhash.h" -#include "util/storage/lookup3.h" - -#include "dnscrypt/cert.h" -#include "dnscrypt/dnscrypt.h" -#include "dnscrypt/dnscrypt_config.h" - -#include - - -/** - * \file - * dnscrypt functions for encrypting DNS packets. - */ - -#define DNSCRYPT_QUERY_BOX_OFFSET \ - (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + \ - crypto_box_HALF_NONCEBYTES) - -// 8 bytes: magic header (CERT_MAGIC_HEADER) -// 12 bytes: the client's nonce -// 12 bytes: server nonce extension -// 16 bytes: Poly1305 MAC (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) - -#define DNSCRYPT_REPLY_BOX_OFFSET \ - (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES + \ - crypto_box_HALF_NONCEBYTES) - - -/** - * Shared secret cache key length. - * secret key. - * 1 byte: ES_VERSION[1] - * 32 bytes: client crypto_box_PUBLICKEYBYTES - * 32 bytes: server crypto_box_SECRETKEYBYTES - */ -#define DNSCRYPT_SHARED_SECRET_KEY_LENGTH \ - (1 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES) - - -struct shared_secret_cache_key { - /** the hash table key */ - uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH]; - /** the hash table entry, data is uint8_t pointer of size crypto_box_BEFORENMBYTES which contains the shared secret. */ - struct lruhash_entry entry; -}; - - -struct nonce_cache_key { - /** the nonce used by the client */ - uint8_t nonce[crypto_box_HALF_NONCEBYTES]; - /** the client_magic used by the client, this is associated to 1 cert only */ - uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN]; - /** the client public key */ - uint8_t client_publickey[crypto_box_PUBLICKEYBYTES]; - /** the hash table entry, data is uint8_t */ - struct lruhash_entry entry; -}; - -/** - * Generate a key suitable to find shared secret in slabhash. - * \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH - * \param[in] esversion: The es version least significant byte. - * \param[in] pk: The public key of the client. uint8_t pointer of size - * crypto_box_PUBLICKEYBYTES. - * \param[in] sk: The secret key of the server matching the magic query number. - * uint8_t pointer of size crypto_box_SECRETKEYBYTES. - * \return the hash of the key. - */ -static uint32_t -dnsc_shared_secrets_cache_key(uint8_t* key, - uint8_t esversion, - uint8_t* pk, - uint8_t* sk) -{ - key[0] = esversion; - memcpy(key + 1, pk, crypto_box_PUBLICKEYBYTES); - memcpy(key + 1 + crypto_box_PUBLICKEYBYTES, sk, crypto_box_SECRETKEYBYTES); - return hashlittle(key, DNSCRYPT_SHARED_SECRET_KEY_LENGTH, 0); -} - -/** - * Inserts a shared secret into the shared_secrets_cache slabhash. - * The shared secret is copied so the caller can use it freely without caring - * about the cache entry being evicted or not. - * \param[in] cache: the slabhash in which to look for the key. - * \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH - * which contains the key of the shared secret. - * \param[in] hash: the hash of the key. - * \param[in] nmkey: a uint8_t pointer of size crypto_box_BEFORENMBYTES which - * contains the shared secret. - */ -static void -dnsc_shared_secret_cache_insert(struct slabhash *cache, - uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH], - uint32_t hash, - uint8_t nmkey[crypto_box_BEFORENMBYTES]) -{ - struct shared_secret_cache_key* k = - (struct shared_secret_cache_key*)calloc(1, sizeof(*k)); - uint8_t* d = malloc(crypto_box_BEFORENMBYTES); - if(!k || !d) { - free(k); - free(d); - return; - } - memcpy(d, nmkey, crypto_box_BEFORENMBYTES); - lock_rw_init(&k->entry.lock); - memcpy(k->key, key, DNSCRYPT_SHARED_SECRET_KEY_LENGTH); - k->entry.hash = hash; - k->entry.key = k; - k->entry.data = d; - slabhash_insert(cache, - hash, &k->entry, - d, - NULL); -} - -/** - * Lookup a record in shared_secrets_cache. - * \param[in] cache: a pointer to shared_secrets_cache slabhash. - * \param[in] key: a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH - * containing the key to look for. - * \param[in] hash: a hash of the key. - * \return a pointer to the locked cache entry or NULL on failure. - */ -static struct lruhash_entry* -dnsc_shared_secrets_lookup(struct slabhash* cache, - uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH], - uint32_t hash) -{ - return slabhash_lookup(cache, hash, key, 0); -} - -/** - * Generate a key hash suitable to find a nonce in slabhash. - * \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES - * \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN - * \param[in] pk: The public key of the client. uint8_t pointer of size - * crypto_box_PUBLICKEYBYTES. - * \return the hash of the key. - */ -static uint32_t -dnsc_nonce_cache_key_hash(const uint8_t nonce[crypto_box_HALF_NONCEBYTES], - const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], - const uint8_t pk[crypto_box_PUBLICKEYBYTES]) -{ - uint32_t h = 0; - h = hashlittle(nonce, crypto_box_HALF_NONCEBYTES, h); - h = hashlittle(magic_query, DNSCRYPT_MAGIC_HEADER_LEN, h); - return hashlittle(pk, crypto_box_PUBLICKEYBYTES, h); -} - -/** - * Inserts a nonce, magic_query, pk tuple into the nonces_cache slabhash. - * \param[in] cache: the slabhash in which to look for the key. - * \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES - * \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN - * \param[in] pk: The public key of the client. uint8_t pointer of size - * crypto_box_PUBLICKEYBYTES. - * \param[in] hash: the hash of the key. - */ -static void -dnsc_nonce_cache_insert(struct slabhash *cache, - const uint8_t nonce[crypto_box_HALF_NONCEBYTES], - const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], - const uint8_t pk[crypto_box_PUBLICKEYBYTES], - uint32_t hash) -{ - struct nonce_cache_key* k = - (struct nonce_cache_key*)calloc(1, sizeof(*k)); - if(!k) { - free(k); - return; - } - lock_rw_init(&k->entry.lock); - memcpy(k->nonce, nonce, crypto_box_HALF_NONCEBYTES); - memcpy(k->magic_query, magic_query, DNSCRYPT_MAGIC_HEADER_LEN); - memcpy(k->client_publickey, pk, crypto_box_PUBLICKEYBYTES); - k->entry.hash = hash; - k->entry.key = k; - k->entry.data = NULL; - slabhash_insert(cache, - hash, &k->entry, - NULL, - NULL); -} - -/** - * Lookup a record in nonces_cache. - * \param[in] cache: the slabhash in which to look for the key. - * \param[in] nonce: a uint8_t pointer of size crypto_box_HALF_NONCEBYTES - * \param[in] magic_query: a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN - * \param[in] pk: The public key of the client. uint8_t pointer of size - * crypto_box_PUBLICKEYBYTES. - * \param[in] hash: the hash of the key. - * \return a pointer to the locked cache entry or NULL on failure. - */ -static struct lruhash_entry* -dnsc_nonces_lookup(struct slabhash* cache, - const uint8_t nonce[crypto_box_HALF_NONCEBYTES], - const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], - const uint8_t pk[crypto_box_PUBLICKEYBYTES], - uint32_t hash) -{ - struct nonce_cache_key k; - memset(&k, 0, sizeof(k)); - k.entry.hash = hash; - memcpy(k.nonce, nonce, crypto_box_HALF_NONCEBYTES); - memcpy(k.magic_query, magic_query, DNSCRYPT_MAGIC_HEADER_LEN); - memcpy(k.client_publickey, pk, crypto_box_PUBLICKEYBYTES); - - return slabhash_lookup(cache, hash, &k, 0); -} - -/** - * Decrypt a query using the dnsccert that was found using dnsc_find_cert. - * The client nonce will be extracted from the encrypted query and stored in - * client_nonce, a shared secret will be computed and stored in nmkey and the - * buffer will be decrypted inplace. - * \param[in] env the dnscrypt environment. - * \param[in] cert the cert that matches this encrypted query. - * \param[in] client_nonce where the client nonce will be stored. - * \param[in] nmkey where the shared secret key will be written. - * \param[in] buffer the encrypted buffer. - * \return 0 on success. - */ -static int -dnscrypt_server_uncurve(struct dnsc_env* env, - const dnsccert *cert, - uint8_t client_nonce[crypto_box_HALF_NONCEBYTES], - uint8_t nmkey[crypto_box_BEFORENMBYTES], - struct sldns_buffer* buffer) -{ - size_t len = sldns_buffer_limit(buffer); - uint8_t *const buf = sldns_buffer_begin(buffer); - uint8_t nonce[crypto_box_NONCEBYTES]; - struct dnscrypt_query_header *query_header; - // shared secret cache - uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH]; - struct lruhash_entry* entry; - uint32_t hash; - - uint32_t nonce_hash; - - if (len <= DNSCRYPT_QUERY_HEADER_SIZE) { - return -1; - } - - query_header = (struct dnscrypt_query_header *)buf; - - /* Detect replay attacks */ - nonce_hash = dnsc_nonce_cache_key_hash( - query_header->nonce, - cert->magic_query, - query_header->publickey); - - lock_basic_lock(&env->nonces_cache_lock); - entry = dnsc_nonces_lookup( - env->nonces_cache, - query_header->nonce, - cert->magic_query, - query_header->publickey, - nonce_hash); - - if(entry) { - lock_rw_unlock(&entry->lock); - env->num_query_dnscrypt_replay++; - lock_basic_unlock(&env->nonces_cache_lock); - return -1; - } - - dnsc_nonce_cache_insert( - env->nonces_cache, - query_header->nonce, - cert->magic_query, - query_header->publickey, - nonce_hash); - lock_basic_unlock(&env->nonces_cache_lock); - - /* Find existing shared secret */ - hash = dnsc_shared_secrets_cache_key(key, - cert->es_version[1], - query_header->publickey, - cert->keypair->crypt_secretkey); - entry = dnsc_shared_secrets_lookup(env->shared_secrets_cache, - key, - hash); - - if(!entry) { - lock_basic_lock(&env->shared_secrets_cache_lock); - env->num_query_dnscrypt_secret_missed_cache++; - lock_basic_unlock(&env->shared_secrets_cache_lock); - if(cert->es_version[1] == 2) { -#ifdef USE_DNSCRYPT_XCHACHA20 - if (crypto_box_curve25519xchacha20poly1305_beforenm( - nmkey, query_header->publickey, - cert->keypair->crypt_secretkey) != 0) { - return -1; - } -#else - return -1; -#endif - } else { - if (crypto_box_beforenm(nmkey, - query_header->publickey, - cert->keypair->crypt_secretkey) != 0) { - return -1; - } - } - // Cache the shared secret we just computed. - dnsc_shared_secret_cache_insert(env->shared_secrets_cache, - key, - hash, - nmkey); - } else { - /* copy shared secret and unlock entry */ - memcpy(nmkey, entry->data, crypto_box_BEFORENMBYTES); - lock_rw_unlock(&entry->lock); - } - - memcpy(nonce, query_header->nonce, crypto_box_HALF_NONCEBYTES); - memset(nonce + crypto_box_HALF_NONCEBYTES, 0, crypto_box_HALF_NONCEBYTES); - - if(cert->es_version[1] == 2) { -#ifdef USE_DNSCRYPT_XCHACHA20 - if (crypto_box_curve25519xchacha20poly1305_open_easy_afternm - (buf, - buf + DNSCRYPT_QUERY_BOX_OFFSET, - len - DNSCRYPT_QUERY_BOX_OFFSET, nonce, - nmkey) != 0) { - return -1; - } -#else - return -1; -#endif - } else { - if (crypto_box_open_easy_afternm - (buf, - buf + DNSCRYPT_QUERY_BOX_OFFSET, - len - DNSCRYPT_QUERY_BOX_OFFSET, nonce, - nmkey) != 0) { - return -1; - } - } - - len -= DNSCRYPT_QUERY_HEADER_SIZE; - - while (*sldns_buffer_at(buffer, --len) == 0) - ; - - if (*sldns_buffer_at(buffer, len) != 0x80) { - return -1; - } - - memcpy(client_nonce, nonce, crypto_box_HALF_NONCEBYTES); - - sldns_buffer_set_position(buffer, 0); - sldns_buffer_set_limit(buffer, len); - - return 0; -} - - -/** - * Add random padding to a buffer, according to a client nonce. - * The length has to depend on the query in order to avoid reply attacks. - * - * @param buf a buffer - * @param len the initial size of the buffer - * @param max_len the maximum size - * @param nonce a nonce, made of the client nonce repeated twice - * @param secretkey - * @return the new size, after padding - */ -size_t -dnscrypt_pad(uint8_t *buf, const size_t len, const size_t max_len, - const uint8_t *nonce, const uint8_t *secretkey) -{ - uint8_t *buf_padding_area = buf + len; - size_t padded_len; - uint32_t rnd; - - // no padding - if (max_len < len + DNSCRYPT_MIN_PAD_LEN) - return len; - - assert(nonce[crypto_box_HALF_NONCEBYTES] == nonce[0]); - - crypto_stream((unsigned char *)&rnd, (unsigned long long)sizeof(rnd), nonce, - secretkey); - padded_len = - len + DNSCRYPT_MIN_PAD_LEN + rnd % (max_len - len - - DNSCRYPT_MIN_PAD_LEN + 1); - padded_len += DNSCRYPT_BLOCK_SIZE - padded_len % DNSCRYPT_BLOCK_SIZE; - if (padded_len > max_len) - padded_len = max_len; - - memset(buf_padding_area, 0, padded_len - len); - *buf_padding_area = 0x80; - - return padded_len; -} - -uint64_t -dnscrypt_hrtime(void) -{ - struct timeval tv; - uint64_t ts = (uint64_t)0U; - int ret; - - ret = gettimeofday(&tv, NULL); - if (ret == 0) { - ts = (uint64_t)tv.tv_sec * 1000000U + (uint64_t)tv.tv_usec; - } else { - log_err("gettimeofday: %s", strerror(errno)); - } - return ts; -} - -/** - * Add the server nonce part to once. - * The nonce is made half of client nonce and the second half of the server - * nonce, both of them of size crypto_box_HALF_NONCEBYTES. - * \param[in] nonce: a uint8_t* of size crypto_box_NONCEBYTES - */ -static void -add_server_nonce(uint8_t *nonce) -{ - randombytes_buf(nonce + crypto_box_HALF_NONCEBYTES, 8/*tsn*/+4/*suffix*/); -} - -/** - * Encrypt a reply using the dnsccert that was used with the query. - * The client nonce will be extracted from the encrypted query and stored in - * The buffer will be encrypted inplace. - * \param[in] cert the dnsccert that matches this encrypted query. - * \param[in] client_nonce client nonce used during the query - * \param[in] nmkey shared secret key used during the query. - * \param[in] buffer the buffer where to encrypt the reply. - * \param[in] udp if whether or not it is a UDP query. - * \param[in] max_udp_size configured max udp size. - * \return 0 on success. - */ -static int -dnscrypt_server_curve(const dnsccert *cert, - uint8_t client_nonce[crypto_box_HALF_NONCEBYTES], - uint8_t nmkey[crypto_box_BEFORENMBYTES], - struct sldns_buffer* buffer, - uint8_t udp, - size_t max_udp_size) -{ - size_t dns_reply_len = sldns_buffer_limit(buffer); - size_t max_len = dns_reply_len + DNSCRYPT_MAX_PADDING \ - + DNSCRYPT_REPLY_HEADER_SIZE; - size_t max_reply_size = max_udp_size - 20U - 8U; - uint8_t nonce[crypto_box_NONCEBYTES]; - uint8_t *boxed; - uint8_t *const buf = sldns_buffer_begin(buffer); - size_t len = sldns_buffer_limit(buffer); - - if(udp){ - if (max_len > max_reply_size) - max_len = max_reply_size; - } - - - memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES); - memcpy(nonce + crypto_box_HALF_NONCEBYTES, client_nonce, - crypto_box_HALF_NONCEBYTES); - - boxed = buf + DNSCRYPT_REPLY_BOX_OFFSET; - memmove(boxed + crypto_box_MACBYTES, buf, len); - len = dnscrypt_pad(boxed + crypto_box_MACBYTES, len, - max_len - DNSCRYPT_REPLY_HEADER_SIZE, nonce, - cert->keypair->crypt_secretkey); - sldns_buffer_set_at(buffer, - DNSCRYPT_REPLY_BOX_OFFSET - crypto_box_BOXZEROBYTES, - 0, crypto_box_ZEROBYTES); - - // add server nonce extension - add_server_nonce(nonce); - - if(cert->es_version[1] == 2) { -#ifdef USE_DNSCRYPT_XCHACHA20 - if (crypto_box_curve25519xchacha20poly1305_easy_afternm - (boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) { - return -1; - } -#else - return -1; -#endif - } else { - if (crypto_box_easy_afternm - (boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) { - return -1; - } - } - - sldns_buffer_write_at(buffer, - 0, - DNSCRYPT_MAGIC_RESPONSE, - DNSCRYPT_MAGIC_HEADER_LEN); - sldns_buffer_write_at(buffer, - DNSCRYPT_MAGIC_HEADER_LEN, - nonce, - crypto_box_NONCEBYTES); - sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE); - return 0; -} - -/** - * Read the content of fname into buf. - * \param[in] fname name of the file to read. - * \param[in] buf the buffer in which to read the content of the file. - * \param[in] count number of bytes to read. - * \return 0 on success. - */ -static int -dnsc_read_from_file(char *fname, char *buf, size_t count) -{ - int fd; - fd = open(fname, O_RDONLY); - if (fd == -1) { - return -1; - } - if (read(fd, buf, count) != (ssize_t)count) { - close(fd); - return -2; - } - close(fd); - return 0; -} - -/** - * Given an absolute path on the original root, returns the absolute path - * within the chroot. If chroot is disabled, the path is not modified. - * No char * is malloced so there is no need to free this. - * \param[in] cfg the configuration. - * \param[in] path the path from the original root. - * \return the path from inside the chroot. - */ -static char * -dnsc_chroot_path(struct config_file *cfg, char *path) -{ - char *nm; - nm = path; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - nm += strlen(cfg->chrootdir); - return nm; -} - -/** - * Parse certificates files provided by the configuration and load them into - * dnsc_env. - * \param[in] env the dnsc_env structure to load the certs into. - * \param[in] cfg the configuration. - * \return the number of certificates loaded. - */ -static int -dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg) -{ - struct config_strlist *head, *head2; - size_t signed_cert_id; - size_t rotated_cert_id; - char *nm; - - env->signed_certs_count = 0U; - env->rotated_certs_count = 0U; - for (head = cfg->dnscrypt_provider_cert; head; head = head->next) { - env->signed_certs_count++; - } - for (head = cfg->dnscrypt_provider_cert_rotated; head; head = head->next) { - env->rotated_certs_count++; - } - env->signed_certs = sodium_allocarray(env->signed_certs_count, - sizeof *env->signed_certs); - - env->rotated_certs = sodium_allocarray(env->rotated_certs_count, - sizeof env->signed_certs); - signed_cert_id = 0U; - rotated_cert_id = 0U; - for(head = cfg->dnscrypt_provider_cert; head; head = head->next, signed_cert_id++) { - nm = dnsc_chroot_path(cfg, head->str); - if(dnsc_read_from_file( - nm, - (char *)(env->signed_certs + signed_cert_id), - sizeof(struct SignedCert)) != 0) { - fatal_exit("dnsc_parse_certs: failed to load %s: %s", head->str, strerror(errno)); - } - for(head2 = cfg->dnscrypt_provider_cert_rotated; head2; head2 = head2->next) { - if(strcmp(head->str, head2->str) == 0) { - *(env->rotated_certs + rotated_cert_id) = env->signed_certs + signed_cert_id; - rotated_cert_id++; - verbose(VERB_OPS, "Cert %s is rotated and will not be distributed via DNS", head->str); - break; - } - } - verbose(VERB_OPS, "Loaded cert %s", head->str); - } - return signed_cert_id; -} - -/** - * Helper function to convert a binary key into a printable fingerprint. - * \param[in] fingerprint the buffer in which to write the printable key. - * \param[in] key the key to convert. - */ -void -dnsc_key_to_fingerprint(char fingerprint[80U], const uint8_t * const key) -{ - const size_t fingerprint_size = 80U; - size_t fingerprint_pos = (size_t) 0U; - size_t key_pos = (size_t) 0U; - - for (;;) { - assert(fingerprint_size > fingerprint_pos); - snprintf(&fingerprint[fingerprint_pos], - fingerprint_size - fingerprint_pos, "%02X%02X", - key[key_pos], key[key_pos + 1U]); - key_pos += 2U; - if (key_pos >= crypto_box_PUBLICKEYBYTES) { - break; - } - fingerprint[fingerprint_pos + 4U] = ':'; - fingerprint_pos += 5U; - } -} - -/** - * Find the cert matching a DNSCrypt query. - * \param[in] dnscenv The DNSCrypt environment, which contains the list of certs - * supported by the server. - * \param[in] buffer The encrypted DNS query. - * \return a dnsccert * if we found a cert matching the magic_number of the - * query, NULL otherwise. - */ -static const dnsccert * -dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer) -{ - const dnsccert *certs = dnscenv->certs; - struct dnscrypt_query_header *dnscrypt_header; - size_t i; - - if (sldns_buffer_limit(buffer) < DNSCRYPT_QUERY_HEADER_SIZE) { - return NULL; - } - dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer); - for (i = 0U; i < dnscenv->signed_certs_count; i++) { - if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query, - DNSCRYPT_MAGIC_HEADER_LEN) == 0) { - return &certs[i]; - } - } - return NULL; -} - -/** - * Insert local-zone and local-data into configuration. - * In order to be able to serve certs over TXT, we can reuse the local-zone and - * local-data config option. The zone and qname are inferred from the - * provider_name and the content of the TXT record from the certificate content. - * returns the number of certificate TXT record that were loaded. - * < 0 in case of error. - */ -static int -dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg) -{ - size_t i, j; - // Insert 'local-zone: "2.dnscrypt-cert.example.com" deny' - if(!cfg_str2list_insert(&cfg->local_zones, - strdup(dnscenv->provider_name), - strdup("deny"))) { - log_err("Could not load dnscrypt local-zone: %s deny", - dnscenv->provider_name); - return -1; - } - - // Add local data entry of type: - // 2.dnscrypt-cert.example.com 86400 IN TXT "DNSC......" - for(i=0; isigned_certs_count; i++) { - const char *ttl_class_type = " 86400 IN TXT \""; - int rotated_cert = 0; - uint32_t serial; - uint16_t rrlen; - char* rr; - struct SignedCert *cert = dnscenv->signed_certs + i; - // Check if the certificate is being rotated and should not be published - for(j=0; jrotated_certs_count; j++){ - if(cert == dnscenv->rotated_certs[j]) { - rotated_cert = 1; - break; - } - } - memcpy(&serial, cert->serial, sizeof serial); - serial = htonl(serial); - if(rotated_cert) { - verbose(VERB_OPS, - "DNSCrypt: not adding cert with serial #%" - PRIu32 - " to local-data as it is rotated", - serial - ); - continue; - } - if((unsigned)strlen(dnscenv->provider_name) >= (unsigned)0xffff0000) { - /* guard against integer overflow in rrlen calculation */ - verbose(VERB_OPS, "cert #%" PRIu32 " is too long", serial); - continue; - } - rrlen = strlen(dnscenv->provider_name) + - strlen(ttl_class_type) + - 4 * sizeof(struct SignedCert) + // worst case scenario - 1 + // trailing double quote - 1; - rr = malloc(rrlen); - if(!rr) { - log_err("Could not allocate memory"); - return -2; - } - snprintf(rr, rrlen - 1, "%s 86400 IN TXT \"", dnscenv->provider_name); - for(j=0; jlocal_data, strdup(rr)); - free(rr); - } - return dnscenv->signed_certs_count; -} - -static const char * -key_get_es_version(uint8_t version[2]) -{ - struct es_version { - uint8_t es_version[2]; - const char *name; - }; - - const int num_versions = 2; - struct es_version es_versions[] = { - {{0x00, 0x01}, "X25519-XSalsa20Poly1305"}, - {{0x00, 0x02}, "X25519-XChacha20Poly1305"}, - }; - int i; - for(i=0; i < num_versions; i++){ - if(es_versions[i].es_version[0] == version[0] && - es_versions[i].es_version[1] == version[1]){ - return es_versions[i].name; - } - } - return NULL; -} - - -/** - * Parse the secret key files from `dnscrypt-secret-key` config and populates - * a list of dnsccert with es_version, magic number and secret/public keys - * supported by dnscrypt listener. - * \param[in] env The dnsc_env structure which will hold the keypairs. - * \param[in] cfg The config with the secret key file paths. - */ -static int -dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg) -{ - struct config_strlist *head; - size_t cert_id, keypair_id; - size_t c; - char *nm; - - env->keypairs_count = 0U; - for (head = cfg->dnscrypt_secret_key; head; head = head->next) { - env->keypairs_count++; - } - - env->keypairs = sodium_allocarray(env->keypairs_count, - sizeof *env->keypairs); - env->certs = sodium_allocarray(env->signed_certs_count, - sizeof *env->certs); - - cert_id = 0U; - keypair_id = 0U; - for(head = cfg->dnscrypt_secret_key; head; head = head->next, keypair_id++) { - char fingerprint[80]; - int found_cert = 0; - KeyPair *current_keypair = &env->keypairs[keypair_id]; - nm = dnsc_chroot_path(cfg, head->str); - if(dnsc_read_from_file( - nm, - (char *)(current_keypair->crypt_secretkey), - crypto_box_SECRETKEYBYTES) != 0) { - fatal_exit("dnsc_parse_keys: failed to load %s: %s", head->str, strerror(errno)); - } - verbose(VERB_OPS, "Loaded key %s", head->str); - if (crypto_scalarmult_base(current_keypair->crypt_publickey, - current_keypair->crypt_secretkey) != 0) { - fatal_exit("dnsc_parse_keys: could not generate public key from %s", head->str); - } - dnsc_key_to_fingerprint(fingerprint, current_keypair->crypt_publickey); - verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s", head->str, fingerprint); - // find the cert matching this key - for(c = 0; c < env->signed_certs_count; c++) { - if(memcmp(current_keypair->crypt_publickey, - env->signed_certs[c].server_publickey, - crypto_box_PUBLICKEYBYTES) == 0) { - dnsccert *current_cert = &env->certs[cert_id++]; - found_cert = 1; - current_cert->keypair = current_keypair; - memcpy(current_cert->magic_query, - env->signed_certs[c].magic_query, - sizeof env->signed_certs[c].magic_query); - memcpy(current_cert->es_version, - env->signed_certs[c].version_major, - sizeof env->signed_certs[c].version_major - ); - dnsc_key_to_fingerprint(fingerprint, - current_cert->keypair->crypt_publickey); - verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s", - head->str, fingerprint); - verbose(VERB_OPS, "Using %s", - key_get_es_version(current_cert->es_version)); -#ifndef USE_DNSCRYPT_XCHACHA20 - if (current_cert->es_version[1] == 0x02) { - fatal_exit("Certificate for XChacha20 but libsodium does not support it."); - } -#endif - - } - } - if (!found_cert) { - fatal_exit("dnsc_parse_keys: could not match certificate for key " - "%s. Unable to determine ES version.", - head->str); - } - } - return cert_id; -} - -#ifdef SODIUM_MISUSE_HANDLER -static void -sodium_misuse_handler(void) -{ - fatal_exit( - "dnscrypt: libsodium could not be initialized, this typically" - " happens when no good source of entropy is found. If you run" - " unbound in a chroot, make sure /dev/urandom is available. See" - " https://www.unbound.net/documentation/unbound.conf.html"); -} -#endif - - -/** - * ######################################################### - * ############# Publicly accessible functions ############# - * ######################################################### - */ - -int -dnsc_handle_curved_request(struct dnsc_env* dnscenv, - struct comm_reply* repinfo) -{ - struct comm_point* c = repinfo->c; - - repinfo->is_dnscrypted = 0; - if( !c->dnscrypt ) { - return 1; - } - // Attempt to decrypt the query. If it is not crypted, we may still need - // to serve the certificate. - verbose(VERB_ALGO, "handle request called on DNSCrypt socket"); - if ((repinfo->dnsc_cert = dnsc_find_cert(dnscenv, c->buffer)) != NULL) { - if(dnscrypt_server_uncurve(dnscenv, - repinfo->dnsc_cert, - repinfo->client_nonce, - repinfo->nmkey, - c->buffer) != 0){ - verbose(VERB_ALGO, "dnscrypt: Failed to uncurve"); - comm_point_drop_reply(repinfo); - return 0; - } - repinfo->is_dnscrypted = 1; - sldns_buffer_rewind(c->buffer); - } - return 1; -} - -int -dnsc_handle_uncurved_request(struct comm_reply *repinfo) -{ - if(!repinfo->c->dnscrypt) { - return 1; - } - sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer); - if(!repinfo->is_dnscrypted) { - return 1; - } - if(dnscrypt_server_curve(repinfo->dnsc_cert, - repinfo->client_nonce, - repinfo->nmkey, - repinfo->c->dnscrypt_buffer, - repinfo->c->type == comm_udp, - repinfo->max_udp_size) != 0){ - verbose(VERB_ALGO, "dnscrypt: Failed to curve cached missed answer"); - comm_point_drop_reply(repinfo); - return 0; - } - return 1; -} - -struct dnsc_env * -dnsc_create(void) -{ - struct dnsc_env *env; -#ifdef SODIUM_MISUSE_HANDLER - sodium_set_misuse_handler(sodium_misuse_handler); -#endif - if (sodium_init() == -1) { - fatal_exit("dnsc_create: could not initialize libsodium."); - } - env = (struct dnsc_env *) calloc(1, sizeof(struct dnsc_env)); - lock_basic_init(&env->shared_secrets_cache_lock); - lock_protect(&env->shared_secrets_cache_lock, - &env->num_query_dnscrypt_secret_missed_cache, - sizeof(env->num_query_dnscrypt_secret_missed_cache)); - lock_basic_init(&env->nonces_cache_lock); - lock_protect(&env->nonces_cache_lock, - &env->nonces_cache, - sizeof(env->nonces_cache)); - lock_protect(&env->nonces_cache_lock, - &env->num_query_dnscrypt_replay, - sizeof(env->num_query_dnscrypt_replay)); - - return env; -} - -int -dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg) -{ - if(dnsc_parse_certs(env, cfg) <= 0) { - fatal_exit("dnsc_apply_cfg: no cert file loaded"); - } - if(dnsc_parse_keys(env, cfg) <= 0) { - fatal_exit("dnsc_apply_cfg: no key file loaded"); - } - randombytes_buf(env->hash_key, sizeof env->hash_key); - env->provider_name = cfg->dnscrypt_provider; - - if(dnsc_load_local_data(env, cfg) <= 0) { - fatal_exit("dnsc_apply_cfg: could not load local data"); - } - lock_basic_lock(&env->shared_secrets_cache_lock); - env->shared_secrets_cache = slabhash_create( - cfg->dnscrypt_shared_secret_cache_slabs, - HASH_DEFAULT_STARTARRAY, - cfg->dnscrypt_shared_secret_cache_size, - dnsc_shared_secrets_sizefunc, - dnsc_shared_secrets_compfunc, - dnsc_shared_secrets_delkeyfunc, - dnsc_shared_secrets_deldatafunc, - NULL - ); - lock_basic_unlock(&env->shared_secrets_cache_lock); - if(!env->shared_secrets_cache){ - fatal_exit("dnsc_apply_cfg: could not create shared secrets cache."); - } - lock_basic_lock(&env->nonces_cache_lock); - env->nonces_cache = slabhash_create( - cfg->dnscrypt_nonce_cache_slabs, - HASH_DEFAULT_STARTARRAY, - cfg->dnscrypt_nonce_cache_size, - dnsc_nonces_sizefunc, - dnsc_nonces_compfunc, - dnsc_nonces_delkeyfunc, - dnsc_nonces_deldatafunc, - NULL - ); - lock_basic_unlock(&env->nonces_cache_lock); - return 0; -} - -void -dnsc_delete(struct dnsc_env *env) -{ - if(!env) { - return; - } - verbose(VERB_OPS, "DNSCrypt: Freeing environment."); - sodium_free(env->signed_certs); - sodium_free(env->rotated_certs); - sodium_free(env->certs); - sodium_free(env->keypairs); - lock_basic_destroy(&env->shared_secrets_cache_lock); - lock_basic_destroy(&env->nonces_cache_lock); - slabhash_delete(env->shared_secrets_cache); - slabhash_delete(env->nonces_cache); - free(env); -} - -/** - * ######################################################### - * ############# Shared secrets cache functions ############ - * ######################################################### - */ - -size_t -dnsc_shared_secrets_sizefunc(void *k, void* ATTR_UNUSED(d)) -{ - struct shared_secret_cache_key* ssk = (struct shared_secret_cache_key*)k; - size_t key_size = sizeof(struct shared_secret_cache_key) - + lock_get_mem(&ssk->entry.lock); - size_t data_size = crypto_box_BEFORENMBYTES; - (void)ssk; /* otherwise ssk is unused if no threading, or fixed locksize */ - return key_size + data_size; -} - -int -dnsc_shared_secrets_compfunc(void *m1, void *m2) -{ - return sodium_memcmp(m1, m2, DNSCRYPT_SHARED_SECRET_KEY_LENGTH); -} - -void -dnsc_shared_secrets_delkeyfunc(void *k, void* ATTR_UNUSED(arg)) -{ - struct shared_secret_cache_key* ssk = (struct shared_secret_cache_key*)k; - lock_rw_destroy(&ssk->entry.lock); - free(ssk); -} - -void -dnsc_shared_secrets_deldatafunc(void* d, void* ATTR_UNUSED(arg)) -{ - uint8_t* data = (uint8_t*)d; - free(data); -} - -/** - * ######################################################### - * ############### Nonces cache functions ################## - * ######################################################### - */ - -size_t -dnsc_nonces_sizefunc(void *k, void* ATTR_UNUSED(d)) -{ - struct nonce_cache_key* nk = (struct nonce_cache_key*)k; - size_t key_size = sizeof(struct nonce_cache_key) - + lock_get_mem(&nk->entry.lock); - (void)nk; /* otherwise ssk is unused if no threading, or fixed locksize */ - return key_size; -} - -int -dnsc_nonces_compfunc(void *m1, void *m2) -{ - struct nonce_cache_key *k1 = m1, *k2 = m2; - return - sodium_memcmp( - k1->nonce, - k2->nonce, - crypto_box_HALF_NONCEBYTES) != 0 || - sodium_memcmp( - k1->magic_query, - k2->magic_query, - DNSCRYPT_MAGIC_HEADER_LEN) != 0 || - sodium_memcmp( - k1->client_publickey, k2->client_publickey, - crypto_box_PUBLICKEYBYTES) != 0; -} - -void -dnsc_nonces_delkeyfunc(void *k, void* ATTR_UNUSED(arg)) -{ - struct nonce_cache_key* nk = (struct nonce_cache_key*)k; - lock_rw_destroy(&nk->entry.lock); - free(nk); -} - -void -dnsc_nonces_deldatafunc(void* ATTR_UNUSED(d), void* ATTR_UNUSED(arg)) -{ - return; -} diff --git a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.h b/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.h deleted file mode 100644 index b0da9b73..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef UNBOUND_DNSCRYPT_H -#define UNBOUND_DNSCRYPT_H - -/** - * \file - * dnscrypt functions for encrypting DNS packets. - */ - -#include "dnscrypt/dnscrypt_config.h" -#ifdef USE_DNSCRYPT - -#define DNSCRYPT_MAGIC_HEADER_LEN 8U -#define DNSCRYPT_MAGIC_RESPONSE "r6fnvWj8" - -#ifndef DNSCRYPT_MAX_PADDING -# define DNSCRYPT_MAX_PADDING 256U -#endif -#ifndef DNSCRYPT_BLOCK_SIZE -# define DNSCRYPT_BLOCK_SIZE 64U -#endif -#ifndef DNSCRYPT_MIN_PAD_LEN -# define DNSCRYPT_MIN_PAD_LEN 8U -#endif - -#define crypto_box_HALF_NONCEBYTES (crypto_box_NONCEBYTES / 2U) - -#include "config.h" -#include "dnscrypt/cert.h" -#include "util/locks.h" - -#define DNSCRYPT_QUERY_HEADER_SIZE \ - (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES + crypto_box_MACBYTES) -#define DNSCRYPT_RESPONSE_HEADER_SIZE \ - (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_NONCEBYTES + crypto_box_MACBYTES) - -#define DNSCRYPT_REPLY_HEADER_SIZE \ - (DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES * 2 + crypto_box_MACBYTES) - -struct sldns_buffer; -struct config_file; -struct comm_reply; -struct slabhash; - -typedef struct KeyPair_ { - uint8_t crypt_publickey[crypto_box_PUBLICKEYBYTES]; - uint8_t crypt_secretkey[crypto_box_SECRETKEYBYTES]; -} KeyPair; - -typedef struct cert_ { - uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN]; - uint8_t es_version[2]; - KeyPair *keypair; -} dnsccert; - -struct dnsc_env { - struct SignedCert *signed_certs; - struct SignedCert **rotated_certs; - dnsccert *certs; - size_t signed_certs_count; - size_t rotated_certs_count; - uint8_t provider_publickey[crypto_sign_ed25519_PUBLICKEYBYTES]; - uint8_t provider_secretkey[crypto_sign_ed25519_SECRETKEYBYTES]; - KeyPair *keypairs; - size_t keypairs_count; - uint64_t nonce_ts_last; - unsigned char hash_key[crypto_shorthash_KEYBYTES]; - char * provider_name; - - /** Caches */ - struct slabhash *shared_secrets_cache; - /** lock on shared secret cache counters */ - lock_basic_type shared_secrets_cache_lock; - /** number of misses from shared_secrets_cache */ - size_t num_query_dnscrypt_secret_missed_cache; - - /** slabhash keeping track of nonce/cient pk/server sk pairs. */ - struct slabhash *nonces_cache; - /** lock on nonces_cache, used to avoid race condition in updating the hash */ - lock_basic_type nonces_cache_lock; - /** number of replayed queries */ - size_t num_query_dnscrypt_replay; -}; - -struct dnscrypt_query_header { - uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN]; - uint8_t publickey[crypto_box_PUBLICKEYBYTES]; - uint8_t nonce[crypto_box_HALF_NONCEBYTES]; - uint8_t mac[crypto_box_MACBYTES]; -}; - -/** - * Initialize DNSCrypt environment. - * Initialize sodium library and allocate the dnsc_env structure. - * \return an uninitialized struct dnsc_env. - */ -struct dnsc_env * dnsc_create(void); - -/** - * Apply configuration. - * Read certificates and secret keys from configuration. Initialize hashkey and - * provider name as well as loading cert TXT records. - * In case of issue applying configuration, this function fatals. - * \param[in] env the struct dnsc_env to populate. - * \param[in] cfg the config_file struct with dnscrypt options. - * \return 0 on success. - */ -int dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg); - -/** - * Delete DNSCrypt environment - * - */ -void dnsc_delete(struct dnsc_env *env); - -/** - * handle a crypted dnscrypt request. - * Determine whether or not a query is coming over the dnscrypt listener and - * attempt to uncurve it or detect if it is a certificate query. - * return 0 in case of failure. - */ -int dnsc_handle_curved_request(struct dnsc_env* dnscenv, - struct comm_reply* repinfo); -/** - * handle an unencrypted dnscrypt request. - * Determine whether or not a query is going over the dnscrypt channel and - * attempt to curve it unless it was not crypted like when it is a - * certificate query. - * \return 0 in case of failure. - */ - -int dnsc_handle_uncurved_request(struct comm_reply *repinfo); - -/** - * Computes the size of the shared secret cache entry. - */ -size_t dnsc_shared_secrets_sizefunc(void *k, void *d); - -/** - * Compares two shared secret cache keys. - */ -int dnsc_shared_secrets_compfunc(void *m1, void *m2); - -/** - * Function to delete a shared secret cache key. - */ -void dnsc_shared_secrets_delkeyfunc(void *k, void* arg); - -/** - * Function to delete a share secret cache value. - */ -void dnsc_shared_secrets_deldatafunc(void* d, void* arg); - -/** - * Computes the size of the nonce cache entry. - */ -size_t dnsc_nonces_sizefunc(void *k, void *d); - -/** - * Compares two nonce cache keys. - */ -int dnsc_nonces_compfunc(void *m1, void *m2); - -/** - * Function to delete a nonce cache key. - */ -void dnsc_nonces_delkeyfunc(void *k, void* arg); - -/** - * Function to delete a nonce cache value. - */ -void dnsc_nonces_deldatafunc(void* d, void* arg); - - -#endif /* USE_DNSCRYPT */ -#endif diff --git a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.m4 b/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.m4 deleted file mode 100644 index 68964242..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt.m4 +++ /dev/null @@ -1,44 +0,0 @@ -# dnscrypt.m4 - -# dnsc_DNSCRYPT([action-if-true], [action-if-false]) -# -------------------------------------------------------------------------- -# Check for required dnscrypt libraries and add dnscrypt configure args. -AC_DEFUN([dnsc_DNSCRYPT], -[ - AC_ARG_ENABLE([dnscrypt], - AS_HELP_STRING([--enable-dnscrypt], - [Enable dnscrypt support (requires libsodium)]), - [opt_dnscrypt=$enableval], [opt_dnscrypt=no]) - - if test "x$opt_dnscrypt" != "xno"; then - AC_ARG_WITH([libsodium], AS_HELP_STRING([--with-libsodium=path], - [Path where libsodium is installed, for dnscrypt]), [ - CFLAGS="$CFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" - ]) - AC_SEARCH_LIBS([sodium_init], [sodium], [], - AC_MSG_ERROR([The sodium library was not found. Please install sodium!])) - AC_SEARCH_LIBS([crypto_box_curve25519xchacha20poly1305_beforenm], [sodium], - [ - AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [1]) - AC_DEFINE( - [USE_DNSCRYPT_XCHACHA20], [1], - [Define to 1 to enable dnscrypt with xchacha20 support]) - ], - [ - AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0]) - ]) - AC_SEARCH_LIBS([sodium_set_misuse_handler], [sodium], - [ - AC_DEFINE( - [SODIUM_MISUSE_HANDLER], [1], - [Define to 1 if libsodium supports sodium_set_misuse_handler]) - ], - [ - ]) - $1 - else - AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0]) - $2 - fi -]) diff --git a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h b/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h deleted file mode 100644 index 8b137891..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h.in b/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h.in deleted file mode 100644 index d9f38a88..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/dnscrypt_config.h.in +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef UNBOUND_DNSCRYPT_CONFIG_H -#define UNBOUND_DNSCRYPT_CONFIG_H - -/* - * Process this file (dnscrypt_config.h.in) with AC_CONFIG_FILES to generate - * dnscrypt_config.h. - * - * This file exists so that USE_DNSCRYPT can be used without including config.h. - */ - -#if @ENABLE_DNSCRYPT@ /* ENABLE_DNSCRYPT */ -# ifndef USE_DNSCRYPT -# define USE_DNSCRYPT 1 -# endif -#endif - -#endif /* UNBOUND_DNSCRYPT_CONFIG_H */ diff --git a/crates/libunbound-sys/unbound/dnscrypt/testdata/gencert.sh b/crates/libunbound-sys/unbound/dnscrypt/testdata/gencert.sh deleted file mode 100755 index ae0b2311..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/testdata/gencert.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -CERT_EXPIRE_DAYS="$(( 365 * 15 ))" -DIR="$(dirname "$0")" - - -if [[ "$PWD" != *tdir ]] -then - echo "You should run this script with a .tdir directory" - exit 1 -fi - -for i in 1 2 -do - # Ephemeral key - rm -f "${i}.key" - dnscrypt-wrapper --gen-crypt-keypair \ - --crypt-secretkey-file="${i}.key" \ - --provider-publickey-file="${DIR}/keys${i}/public.key" \ - --provider-secretkey-file="${DIR}/keys${i}/secret.key" - # Cert file - for cipher in salsa chacha - do - rm -f "${i}_${cipher}.cert" - extraarg="" - if [ "${cipher}" == "chacha" ] - then - extraarg="-x" - fi - - dnscrypt-wrapper ${extraarg} --gen-cert-file \ - --provider-cert-file="${i}_${cipher}.cert" \ - --crypt-secretkey-file="${i}.key" \ - --provider-publickey-file="${DIR}/keys${i}/public.key" \ - --provider-secretkey-file="${DIR}/keys${i}/secret.key" \ - --cert-file-expire-days="${CERT_EXPIRE_DAYS}" - done -done diff --git a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/public.key b/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/public.key deleted file mode 100644 index 45e6aadc..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/public.key +++ /dev/null @@ -1 +0,0 @@ -¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO� \ No newline at end of file diff --git a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/secret.key b/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/secret.key deleted file mode 100644 index 7672c979..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys1/secret.key +++ /dev/null @@ -1 +0,0 @@ --&ç6\Uùõñh`^"…ºz/C9‚ óˆ¸_A¡O#÷ÛÈfó—ÌoD¶_�eŶ)|'T¦éÜòO� \ No newline at end of file diff --git a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/public.key b/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/public.key deleted file mode 100644 index 036b04aa..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/public.key +++ /dev/null @@ -1 +0,0 @@ -ÃR òÒýeµô{ölˆÁKË€Î:5r\±}KÓçƒ \ No newline at end of file diff --git a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/secret.key b/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/secret.key deleted file mode 100644 index 68730295..00000000 --- a/crates/libunbound-sys/unbound/dnscrypt/testdata/keys2/secret.key +++ /dev/null @@ -1 +0,0 @@ -çi%‚ 5 fÍ™–í ÉûŒí Bnêͯ.º“ÃR òÒýeµô{ölˆÁKË€Î:5r\±}KÓçƒ \ No newline at end of file diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap.c b/crates/libunbound-sys/unbound/dnstap/dnstap.c deleted file mode 100644 index d15eb9b0..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap.c +++ /dev/null @@ -1,570 +0,0 @@ -/* dnstap support for Unbound */ - -/* - * Copyright (c) 2013-2014, Farsight Security, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "dnstap/dnstap_config.h" - -#ifdef USE_DNSTAP - -#include "config.h" -#include -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#include -#include "sldns/sbuffer.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/netevent.h" -#include "util/log.h" - -#include - -#include "dnstap/dnstap.h" -#include "dnstap/dtstream.h" -#include "dnstap/dnstap.pb-c.h" - -#define DNSTAP_INITIAL_BUF_SIZE 256 - -struct dt_msg { - void *buf; - size_t len_buf; - Dnstap__Dnstap d; - Dnstap__Message m; -}; - -static int -dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz) -{ - ProtobufCBufferSimple sbuf; - - memset(&sbuf, 0, sizeof(sbuf)); - sbuf.base.append = protobuf_c_buffer_simple_append; - sbuf.len = 0; - sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE; - sbuf.data = malloc(sbuf.alloced); - if (sbuf.data == NULL) - return 0; - sbuf.must_free_data = 1; - - *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf); - if (sbuf.data == NULL) - return 0; - *buf = sbuf.data; - - return 1; -} - -static void -dt_send(const struct dt_env *env, void *buf, size_t len_buf) -{ - dt_msg_queue_submit(env->msgqueue, buf, len_buf); -} - -static void -dt_msg_init(const struct dt_env *env, - struct dt_msg *dm, - Dnstap__Message__Type mtype) -{ - memset(dm, 0, sizeof(*dm)); - dm->d.base.descriptor = &dnstap__dnstap__descriptor; - dm->m.base.descriptor = &dnstap__message__descriptor; - dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE; - dm->d.message = &dm->m; - dm->m.type = mtype; - if (env->identity != NULL) { - dm->d.identity.data = (uint8_t *) env->identity; - dm->d.identity.len = (size_t) env->len_identity; - dm->d.has_identity = 1; - } - if (env->version != NULL) { - dm->d.version.data = (uint8_t *) env->version; - dm->d.version.len = (size_t) env->len_version; - dm->d.has_version = 1; - } -} - -/* check that the socket file can be opened and exists, print error if not */ -static void -check_socket_file(const char* socket_path) -{ - struct stat statbuf; - memset(&statbuf, 0, sizeof(statbuf)); - if(stat(socket_path, &statbuf) < 0) { - log_warn("could not open dnstap-socket-path: %s, %s", - socket_path, strerror(errno)); - } -} - -struct dt_env * -dt_create(struct config_file* cfg) -{ - struct dt_env *env; - - if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] && - (cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) { - char* p = cfg->dnstap_socket_path; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(p, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - p += strlen(cfg->chrootdir); - verbose(VERB_OPS, "attempting to connect to dnstap socket %s", - p); - check_socket_file(p); - } - - env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); - if (!env) - return NULL; - - env->dtio = dt_io_thread_create(); - if(!env->dtio) { - log_err("malloc failure"); - free(env); - return NULL; - } - if(!dt_io_thread_apply_cfg(env->dtio, cfg)) { - dt_io_thread_delete(env->dtio); - free(env); - return NULL; - } - dt_apply_cfg(env, cfg); - return env; -} - -static void -dt_apply_identity(struct dt_env *env, struct config_file *cfg) -{ - char buf[MAXHOSTNAMELEN+1]; - if (!cfg->dnstap_send_identity) - return; - free(env->identity); - if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { - if (gethostname(buf, MAXHOSTNAMELEN) == 0) { - buf[MAXHOSTNAMELEN] = 0; - env->identity = strdup(buf); - } else { - fatal_exit("dt_apply_identity: gethostname() failed"); - } - } else { - env->identity = strdup(cfg->dnstap_identity); - } - if (env->identity == NULL) - fatal_exit("dt_apply_identity: strdup() failed"); - env->len_identity = (unsigned int)strlen(env->identity); - verbose(VERB_OPS, "dnstap identity field set to \"%s\"", - env->identity); -} - -static void -dt_apply_version(struct dt_env *env, struct config_file *cfg) -{ - if (!cfg->dnstap_send_version) - return; - free(env->version); - if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) - env->version = strdup(PACKAGE_STRING); - else - env->version = strdup(cfg->dnstap_version); - if (env->version == NULL) - fatal_exit("dt_apply_version: strdup() failed"); - env->len_version = (unsigned int)strlen(env->version); - verbose(VERB_OPS, "dnstap version field set to \"%s\"", - env->version); -} - -void -dt_apply_cfg(struct dt_env *env, struct config_file *cfg) -{ - if (!cfg->dnstap) - return; - - dt_apply_identity(env, cfg); - dt_apply_version(env, cfg); - if ((env->log_resolver_query_messages = (unsigned int) - cfg->dnstap_log_resolver_query_messages)) - { - verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); - } - if ((env->log_resolver_response_messages = (unsigned int) - cfg->dnstap_log_resolver_response_messages)) - { - verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); - } - if ((env->log_client_query_messages = (unsigned int) - cfg->dnstap_log_client_query_messages)) - { - verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); - } - if ((env->log_client_response_messages = (unsigned int) - cfg->dnstap_log_client_response_messages)) - { - verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); - } - if ((env->log_forwarder_query_messages = (unsigned int) - cfg->dnstap_log_forwarder_query_messages)) - { - verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); - } - if ((env->log_forwarder_response_messages = (unsigned int) - cfg->dnstap_log_forwarder_response_messages)) - { - verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); - } -} - -int -dt_init(struct dt_env *env, struct comm_base* base) -{ - env->msgqueue = dt_msg_queue_create(base); - if(!env->msgqueue) { - log_err("malloc failure"); - return 0; - } - if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) { - log_err("malloc failure"); - dt_msg_queue_delete(env->msgqueue); - env->msgqueue = NULL; - return 0; - } - return 1; -} - -void -dt_deinit(struct dt_env* env) -{ - dt_io_thread_unregister_queue(env->dtio, env->msgqueue); - dt_msg_queue_delete(env->msgqueue); -} - -void -dt_delete(struct dt_env *env) -{ - if (!env) - return; - dt_io_thread_delete(env->dtio); - free(env->identity); - free(env->version); - free(env); -} - -static void -dt_fill_timeval(const struct timeval *tv, - uint64_t *time_sec, protobuf_c_boolean *has_time_sec, - uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec) -{ -#ifndef S_SPLINT_S - *time_sec = tv->tv_sec; - *time_nsec = tv->tv_usec * 1000; -#endif - *has_time_sec = 1; - *has_time_nsec = 1; -} - -static void -dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) -{ - log_assert(b != NULL); - p->len = sldns_buffer_limit(b); - p->data = sldns_buffer_begin(b); - *has = 1; -} - -static void -dt_msg_fill_net(struct dt_msg *dm, - struct sockaddr_storage *qs, - struct sockaddr_storage *rs, - enum comm_point_type cptype, - ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr, - uint32_t *qport, protobuf_c_boolean *has_qport, - ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr, - uint32_t *rport, protobuf_c_boolean *has_rport) -{ - log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET); - if (qs->ss_family == AF_INET6) { - struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs; - - /* socket_family */ - dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; - dm->m.has_socket_family = 1; - - /* addr: query_address or response_address */ - qaddr->data = q->sin6_addr.s6_addr; - qaddr->len = 16; /* IPv6 */ - *has_qaddr = 1; - - /* port: query_port or response_port */ - *qport = ntohs(q->sin6_port); - *has_qport = 1; - } else if (qs->ss_family == AF_INET) { - struct sockaddr_in *q = (struct sockaddr_in *) qs; - - /* socket_family */ - dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; - dm->m.has_socket_family = 1; - - /* addr: query_address or response_address */ - qaddr->data = (uint8_t *) &q->sin_addr.s_addr; - qaddr->len = 4; /* IPv4 */ - *has_qaddr = 1; - - /* port: query_port or response_port */ - *qport = ntohs(q->sin_port); - *has_qport = 1; - } - - /* - * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. - * Additional responsive structure is: struct sockaddr_storage *rs - */ - if (rs && rs->ss_family == AF_INET6) { - struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; - - /* addr: query_address or response_address */ - raddr->data = r->sin6_addr.s6_addr; - raddr->len = 16; /* IPv6 */ - *has_raddr = 1; - - /* port: query_port or response_port */ - *rport = ntohs(r->sin6_port); - *has_rport = 1; - } else if (rs && rs->ss_family == AF_INET) { - struct sockaddr_in *r = (struct sockaddr_in *) rs; - - /* addr: query_address or response_address */ - raddr->data = (uint8_t *) &r->sin_addr.s_addr; - raddr->len = 4; /* IPv4 */ - *has_raddr = 1; - - /* port: query_port or response_port */ - *rport = ntohs(r->sin_port); - *has_rport = 1; - } - - log_assert(cptype == comm_udp || cptype == comm_tcp); - if (cptype == comm_udp) { - /* socket_protocol */ - dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; - dm->m.has_socket_protocol = 1; - } else if (cptype == comm_tcp) { - /* socket_protocol */ - dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; - dm->m.has_socket_protocol = 1; - } -} - -void -dt_msg_send_client_query(struct dt_env *env, - struct sockaddr_storage *qsock, - struct sockaddr_storage *rsock, - enum comm_point_type cptype, - sldns_buffer *qmsg, - struct timeval* tstamp) -{ - struct dt_msg dm; - struct timeval qtime; - - if(tstamp) - memcpy(&qtime, tstamp, sizeof(qtime)); - else gettimeofday(&qtime, NULL); - - /* type */ - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); - - /* query_time */ - dt_fill_timeval(&qtime, - &dm.m.query_time_sec, &dm.m.has_query_time_sec, - &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); - - /* query_message */ - dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); - - /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ - log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, qsock, rsock, cptype, - &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port, - &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port); - - - if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) - dt_send(env, dm.buf, dm.len_buf); -} - -void -dt_msg_send_client_response(struct dt_env *env, - struct sockaddr_storage *qsock, - struct sockaddr_storage *rsock, - enum comm_point_type cptype, - sldns_buffer *rmsg) -{ - struct dt_msg dm; - struct timeval rtime; - - gettimeofday(&rtime, NULL); - - /* type */ - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); - - /* response_time */ - dt_fill_timeval(&rtime, - &dm.m.response_time_sec, &dm.m.has_response_time_sec, - &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); - - /* response_message */ - dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); - - /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ - log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, qsock, rsock, cptype, - &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port, - &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port); - - if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) - dt_send(env, dm.buf, dm.len_buf); -} - -void -dt_msg_send_outside_query(struct dt_env *env, - struct sockaddr_storage *rsock, - struct sockaddr_storage *qsock, - enum comm_point_type cptype, - uint8_t *zone, size_t zone_len, - sldns_buffer *qmsg) -{ - struct dt_msg dm; - struct timeval qtime; - uint16_t qflags; - - gettimeofday(&qtime, NULL); - qflags = sldns_buffer_read_u16_at(qmsg, 2); - - /* type */ - if (qflags & BIT_RD) { - if (!env->log_forwarder_query_messages) - return; - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); - } else { - if (!env->log_resolver_query_messages) - return; - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); - } - - /* query_zone */ - dm.m.query_zone.data = zone; - dm.m.query_zone.len = zone_len; - dm.m.has_query_zone = 1; - - /* query_time_sec, query_time_nsec */ - dt_fill_timeval(&qtime, - &dm.m.query_time_sec, &dm.m.has_query_time_sec, - &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); - - /* query_message */ - dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); - - /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ - log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, rsock, qsock, cptype, - &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port, - &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port); - - if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) - dt_send(env, dm.buf, dm.len_buf); -} - -void -dt_msg_send_outside_response(struct dt_env *env, - struct sockaddr_storage *rsock, - struct sockaddr_storage *qsock, - enum comm_point_type cptype, - uint8_t *zone, size_t zone_len, - uint8_t *qbuf, size_t qbuf_len, - const struct timeval *qtime, - const struct timeval *rtime, - sldns_buffer *rmsg) -{ - struct dt_msg dm; - uint16_t qflags; - - (void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags)); - memcpy(&qflags, qbuf, sizeof(qflags)); - qflags = ntohs(qflags); - - /* type */ - if (qflags & BIT_RD) { - if (!env->log_forwarder_response_messages) - return; - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); - } else { - if (!env->log_resolver_response_messages) - return; - dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); - } - - /* query_zone */ - dm.m.query_zone.data = zone; - dm.m.query_zone.len = zone_len; - dm.m.has_query_zone = 1; - - /* query_time_sec, query_time_nsec */ - dt_fill_timeval(qtime, - &dm.m.query_time_sec, &dm.m.has_query_time_sec, - &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); - - /* response_time_sec, response_time_nsec */ - dt_fill_timeval(rtime, - &dm.m.response_time_sec, &dm.m.has_response_time_sec, - &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); - - /* response_message */ - dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); - - /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ - log_assert(cptype == comm_udp || cptype == comm_tcp); - dt_msg_fill_net(&dm, rsock, qsock, cptype, - &dm.m.response_address, &dm.m.has_response_address, - &dm.m.response_port, &dm.m.has_response_port, - &dm.m.query_address, &dm.m.has_query_address, - &dm.m.query_port, &dm.m.has_query_port); - - if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) - dt_send(env, dm.buf, dm.len_buf); -} - -#endif /* USE_DNSTAP */ diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap.h b/crates/libunbound-sys/unbound/dnstap/dnstap.h deleted file mode 100644 index 169bdc2c..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap.h +++ /dev/null @@ -1,203 +0,0 @@ -/* dnstap support for Unbound */ - -/* - * Copyright (c) 2013-2014, Farsight Security, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UNBOUND_DNSTAP_H -#define UNBOUND_DNSTAP_H - -#include "dnstap/dnstap_config.h" - -#ifdef USE_DNSTAP - -struct config_file; -struct sldns_buffer; -struct dt_msg_queue; - -struct dt_env { - /** the io thread (made by the struct daemon) */ - struct dt_io_thread* dtio; - - /** valid in worker struct, not in daemon struct, the per-worker - * message list */ - struct dt_msg_queue* msgqueue; - - /** dnstap "identity" field, NULL if disabled */ - char *identity; - - /** dnstap "version" field, NULL if disabled */ - char *version; - - /** length of "identity" field */ - unsigned len_identity; - - /** length of "version" field */ - unsigned len_version; - - /** whether to log Message/RESOLVER_QUERY */ - unsigned log_resolver_query_messages : 1; - /** whether to log Message/RESOLVER_RESPONSE */ - unsigned log_resolver_response_messages : 1; - /** whether to log Message/CLIENT_QUERY */ - unsigned log_client_query_messages : 1; - /** whether to log Message/CLIENT_RESPONSE */ - unsigned log_client_response_messages : 1; - /** whether to log Message/FORWARDER_QUERY */ - unsigned log_forwarder_query_messages : 1; - /** whether to log Message/FORWARDER_RESPONSE */ - unsigned log_forwarder_response_messages : 1; -}; - -/** - * Create dnstap environment object. Afterwards, call dt_apply_cfg() to fill in - * the config variables and dt_init() to fill in the per-worker state. Each - * worker needs a copy of this object but with its own I/O queue (the fq field - * of the structure) to ensure lock-free access to its own per-worker circular - * queue. Duplicate the environment object if more than one worker needs to - * share access to the dnstap I/O socket. - * @param cfg: with config settings. - * @return dt_env object, NULL on failure. - */ -struct dt_env * -dt_create(struct config_file* cfg); - -/** - * Apply config settings. - * @param env: dnstap environment object. - * @param cfg: new config settings. - */ -void -dt_apply_cfg(struct dt_env *env, struct config_file *cfg); - -/** - * Initialize per-worker state in dnstap environment object. - * @param env: dnstap environment object to initialize, created with dt_create(). - * @param base: event base for wakeup timer. - * @return: true on success, false on failure. - */ -int -dt_init(struct dt_env *env, struct comm_base* base); - -/** - * Deletes the per-worker state created by dt_init - */ -void dt_deinit(struct dt_env *env); - -/** - * Delete dnstap environment object. Closes dnstap I/O socket and deletes all - * per-worker I/O queues. - */ -void -dt_delete(struct dt_env *env); - -/** - * Create and send a new dnstap "Message" event of type CLIENT_QUERY. - * @param env: dnstap environment object. - * @param qsock: address/port of client. - * @param rsock: local (service) address/port. - * @param cptype: comm_udp or comm_tcp. - * @param qmsg: query message. - * @param tstamp: timestamp or NULL if none provided. - */ -void -dt_msg_send_client_query(struct dt_env *env, - struct sockaddr_storage *qsock, - struct sockaddr_storage *rsock, - enum comm_point_type cptype, - struct sldns_buffer *qmsg, - struct timeval* tstamp); - -/** - * Create and send a new dnstap "Message" event of type CLIENT_RESPONSE. - * @param env: dnstap environment object. - * @param qsock: address/port of client. - * @param rsock: local (service) address/port. - * @param cptype: comm_udp or comm_tcp. - * @param rmsg: response message. - */ -void -dt_msg_send_client_response(struct dt_env *env, - struct sockaddr_storage *qsock, - struct sockaddr_storage *rsock, - enum comm_point_type cptype, - struct sldns_buffer *rmsg); - -/** - * Create and send a new dnstap "Message" event of type RESOLVER_QUERY or - * FORWARDER_QUERY. The type used is dependent on the value of the RD bit - * in the query header. - * @param env: dnstap environment object. - * @param rsock: address/port of server (upstream) the query is being sent to. - * @param qsock: address/port of server (local) the query is being sent from. - * @param cptype: comm_udp or comm_tcp. - * @param zone: query zone. - * @param zone_len: length of zone. - * @param qmsg: query message. - */ -void -dt_msg_send_outside_query(struct dt_env *env, - struct sockaddr_storage *rsock, - struct sockaddr_storage *qsock, - enum comm_point_type cptype, - uint8_t *zone, size_t zone_len, - struct sldns_buffer *qmsg); - -/** - * Create and send a new dnstap "Message" event of type RESOLVER_RESPONSE or - * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit - * in the query header. - * @param env: dnstap environment object. - * @param rsock: address/port of server (upstream) the response was received from. - * @param qsock: address/port of server (local) the response was received to. - * @param cptype: comm_udp or comm_tcp. - * @param zone: query zone. - * @param zone_len: length of zone. - * @param qbuf: outside_network's qbuf key. - * @param qbuf_len: length of outside_network's qbuf key. - * @param qtime: time query message was sent. - * @param rtime: time response message was sent. - * @param rmsg: response message. - */ -void -dt_msg_send_outside_response(struct dt_env *env, - struct sockaddr_storage *rsock, - struct sockaddr_storage *qsock, - enum comm_point_type cptype, - uint8_t *zone, size_t zone_len, - uint8_t *qbuf, size_t qbuf_len, - const struct timeval *qtime, - const struct timeval *rtime, - struct sldns_buffer *rmsg); - -#endif /* USE_DNSTAP */ - -#endif /* UNBOUND_DNSTAP_H */ diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap.m4 b/crates/libunbound-sys/unbound/dnstap/dnstap.m4 deleted file mode 100644 index 1ff6c3fe..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap.m4 +++ /dev/null @@ -1,49 +0,0 @@ -# dnstap.m4 - -# dt_DNSTAP(default_dnstap_socket_path, [action-if-true], [action-if-false]) -# -------------------------------------------------------------------------- -# Check for required dnstap libraries and add dnstap configure args. -AC_DEFUN([dt_DNSTAP], -[ - AC_ARG_ENABLE([dnstap], - AS_HELP_STRING([--enable-dnstap], - [Enable dnstap support (requires protobuf-c)]), - [opt_dnstap=$enableval], [opt_dnstap=no]) - - AC_ARG_WITH([dnstap-socket-path], - AS_HELP_STRING([--with-dnstap-socket-path=pathname], - [set default dnstap socket path]), - [opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"]) - - if test "x$opt_dnstap" != "xno"; then - AC_PATH_PROG([PROTOC_C], [protoc-c]) - if test -z "$PROTOC_C"; then - AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!]) - fi - AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path], - [Path where protobuf-c is installed, for dnstap]), [ - # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0 - if test -f $withval/include/google/protobuf-c/protobuf-c.h; then - CFLAGS="$CFLAGS -I$withval/include/google" - else - CFLAGS="$CFLAGS -I$withval/include" - fi - LDFLAGS="$LDFLAGS -L$withval/lib" - ], [ - # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0 - if test -f /usr/include/google/protobuf-c/protobuf-c.h; then - CFLAGS="$CFLAGS -I/usr/include/google" - else - if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then - CFLAGS="$CFLAGS -I/usr/local/include/google" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - fi - fi - ]) - AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [], - AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!])) - $2 - else - $3 - fi -]) diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap.proto b/crates/libunbound-sys/unbound/dnstap/dnstap.proto deleted file mode 100644 index 88bfb4e9..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap.proto +++ /dev/null @@ -1,263 +0,0 @@ -// dnstap: flexible, structured event replication format for DNS software -// -// This file contains the protobuf schemas for the "dnstap" structured event -// replication format for DNS software. - -// Written in 2013-2014 by Farsight Security, Inc. -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this file to the public -// domain worldwide. This file is distributed without any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication along -// with this file. If not, see: -// -// . -syntax = "proto2"; - -package dnstap; - -// "Dnstap": this is the top-level dnstap type, which is a "union" type that -// contains other kinds of dnstap payloads, although currently only one type -// of dnstap payload is defined. -// See: https://developers.google.com/protocol-buffers/docs/techniques#union -message Dnstap { - // DNS server identity. - // If enabled, this is the identity string of the DNS server which generated - // this message. Typically this would be the same string as returned by an - // "NSID" (RFC 5001) query. - optional bytes identity = 1; - - // DNS server version. - // If enabled, this is the version string of the DNS server which generated - // this message. Typically this would be the same string as returned by a - // "version.bind" query. - optional bytes version = 2; - - // Extra data for this payload. - // This field can be used for adding an arbitrary byte-string annotation to - // the payload. No encoding or interpretation is applied or enforced. - optional bytes extra = 3; - - // Identifies which field below is filled in. - enum Type { - MESSAGE = 1; - } - required Type type = 15; - - // One of the following will be filled in. - optional Message message = 14; -} - -// SocketFamily: the network protocol family of a socket. This specifies how -// to interpret "network address" fields. -enum SocketFamily { - INET = 1; // IPv4 (RFC 791) - INET6 = 2; // IPv6 (RFC 2460) -} - -// SocketProtocol: the transport protocol of a socket. This specifies how to -// interpret "transport port" fields. -enum SocketProtocol { - UDP = 1; // User Datagram Protocol (RFC 768) - TCP = 2; // Transmission Control Protocol (RFC 793) -} - -// Message: a wire-format (RFC 1035 section 4) DNS message and associated -// metadata. Applications generating "Message" payloads should follow -// certain requirements based on the MessageType, see below. -message Message { - - // There are eight types of "Message" defined that correspond to the - // four arrows in the following diagram, slightly modified from RFC 1035 - // section 2: - - // +---------+ +----------+ +--------+ - // | | query | | query | | - // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. | - // | Resolver| | Server | | Name | - // | |<-SR--------CR-| |<-RR----AR-| Server | - // +---------+ response | | response | | - // +----------+ +--------+ - - // Each arrow has two Type values each, one for each "end" of each arrow, - // because these are considered to be distinct events. Each end of each - // arrow on the diagram above has been marked with a two-letter Type - // mnemonic. Clockwise from upper left, these mnemonic values are: - // - // SQ: STUB_QUERY - // CQ: CLIENT_QUERY - // RQ: RESOLVER_QUERY - // AQ: AUTH_QUERY - // AR: AUTH_RESPONSE - // RR: RESOLVER_RESPONSE - // CR: CLIENT_RESPONSE - // SR: STUB_RESPONSE - - // Two additional types of "Message" have been defined for the - // "forwarding" case where an upstream DNS server is responsible for - // further recursion. These are not shown on the diagram above, but have - // the following mnemonic values: - - // FQ: FORWARDER_QUERY - // FR: FORWARDER_RESPONSE - - // The "Message" Type values are defined below. - - enum Type { - // AUTH_QUERY is a DNS query message received from a resolver by an - // authoritative name server, from the perspective of the authoritative - // name server. - AUTH_QUERY = 1; - - // AUTH_RESPONSE is a DNS response message sent from an authoritative - // name server to a resolver, from the perspective of the authoritative - // name server. - AUTH_RESPONSE = 2; - - // RESOLVER_QUERY is a DNS query message sent from a resolver to an - // authoritative name server, from the perspective of the resolver. - // Resolvers typically clear the RD (recursion desired) bit when - // sending queries. - RESOLVER_QUERY = 3; - - // RESOLVER_RESPONSE is a DNS response message received from an - // authoritative name server by a resolver, from the perspective of - // the resolver. - RESOLVER_RESPONSE = 4; - - // CLIENT_QUERY is a DNS query message sent from a client to a DNS - // server which is expected to perform further recursion, from the - // perspective of the DNS server. The client may be a stub resolver or - // forwarder or some other type of software which typically sets the RD - // (recursion desired) bit when querying the DNS server. The DNS server - // may be a simple forwarding proxy or it may be a full recursive - // resolver. - CLIENT_QUERY = 5; - - // CLIENT_RESPONSE is a DNS response message sent from a DNS server to - // a client, from the perspective of the DNS server. The DNS server - // typically sets the RA (recursion available) bit when responding. - CLIENT_RESPONSE = 6; - - // FORWARDER_QUERY is a DNS query message sent from a downstream DNS - // server to an upstream DNS server which is expected to perform - // further recursion, from the perspective of the downstream DNS - // server. - FORWARDER_QUERY = 7; - - // FORWARDER_RESPONSE is a DNS response message sent from an upstream - // DNS server performing recursion to a downstream DNS server, from the - // perspective of the downstream DNS server. - FORWARDER_RESPONSE = 8; - - // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS - // server, from the perspective of the stub resolver. - STUB_QUERY = 9; - - // STUB_RESPONSE is a DNS response message sent from a DNS server to a - // stub resolver, from the perspective of the stub resolver. - STUB_RESPONSE = 10; - } - - // One of the Type values described above. - required Type type = 1; - - // One of the SocketFamily values described above. - optional SocketFamily socket_family = 2; - - // One of the SocketProtocol values described above. - optional SocketProtocol socket_protocol = 3; - - // The network address of the message initiator. - // For SocketFamily INET, this field is 4 octets (IPv4 address). - // For SocketFamily INET6, this field is 16 octets (IPv6 address). - optional bytes query_address = 4; - - // The network address of the message responder. - // For SocketFamily INET, this field is 4 octets (IPv4 address). - // For SocketFamily INET6, this field is 16 octets (IPv6 address). - optional bytes response_address = 5; - - // The transport port of the message initiator. - // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. - optional uint32 query_port = 6; - - // The transport port of the message responder. - // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. - optional uint32 response_port = 7; - - // The time at which the DNS query message was sent or received, depending - // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY. - // This is the number of seconds since the UNIX epoch. - optional uint64 query_time_sec = 8; - - // The time at which the DNS query message was sent or received. - // This is the seconds fraction, expressed as a count of nanoseconds. - optional fixed32 query_time_nsec = 9; - - // The initiator's original wire-format DNS query message, verbatim. - optional bytes query_message = 10; - - // The "zone" or "bailiwick" pertaining to the DNS query message. - // This is a wire-format DNS domain name. - optional bytes query_zone = 11; - - // The time at which the DNS response message was sent or received, - // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or - // CLIENT_RESPONSE. - // This is the number of seconds since the UNIX epoch. - optional uint64 response_time_sec = 12; - - // The time at which the DNS response message was sent or received. - // This is the seconds fraction, expressed as a count of nanoseconds. - optional fixed32 response_time_nsec = 13; - - // The responder's original wire-format DNS response message, verbatim. - optional bytes response_message = 14; -} - -// All fields except for 'type' in the Message schema are optional. -// It is recommended that at least the following fields be filled in for -// particular types of Messages. - -// AUTH_QUERY: -// socket_family, socket_protocol -// query_address, query_port -// query_message -// query_time_sec, query_time_nsec - -// AUTH_RESPONSE: -// socket_family, socket_protocol -// query_address, query_port -// query_time_sec, query_time_nsec -// response_message -// response_time_sec, response_time_nsec - -// RESOLVER_QUERY: -// socket_family, socket_protocol -// query_name, query_type, query_class -// query_message -// query_time_sec, query_time_nsec -// query_zone -// response_address, response_port - -// RESOLVER_RESPONSE: -// socket_family, socket_protocol -// query_name, query_type, query_class -// query_time_sec, query_time_nsec -// query_zone -// response_address, response_port -// response_message -// response_time_sec, response_time_nsec - -// CLIENT_QUERY: -// socket_family, socket_protocol -// query_message -// query_time_sec, query_time_nsec - -// CLIENT_RESPONSE: -// socket_family, socket_protocol -// query_time_sec, query_time_nsec -// response_message -// response_time_sec, response_time_nsec diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap_config.h b/crates/libunbound-sys/unbound/dnstap/dnstap_config.h deleted file mode 100644 index 8b137891..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap_config.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap_config.h.in b/crates/libunbound-sys/unbound/dnstap/dnstap_config.h.in deleted file mode 100644 index c9f74893..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap_config.h.in +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef UNBOUND_DNSTAP_CONFIG_H -#define UNBOUND_DNSTAP_CONFIG_H - -/* - * Process this file (dnstap_config.h.in) with AC_CONFIG_FILES to generate - * dnstap_config.h. - * - * This file exists so that USE_DNSTAP can be used without including config.h. - */ - -#if @ENABLE_DNSTAP@ /* ENABLE_DNSTAP */ -# ifndef USE_DNSTAP -# define USE_DNSTAP 1 -# endif -#endif - -#endif /* UNBOUND_DNSTAP_CONFIG_H */ diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.c b/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.c deleted file mode 100644 index 289e78bd..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * dnstap/dnstap_fstrm.c - Frame Streams protocol for dnstap - * - * Copyright (c) 2020, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * - * Definitions for the Frame Streams data transport protocol for - * dnstap message logs. - */ - -#include "config.h" -#include "dnstap/dnstap_fstrm.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" - -void* fstrm_create_control_frame_start(char* contenttype, size_t* len) -{ - uint32_t* control; - size_t n; - /* start framestream message: - * 4byte 0: control indicator. - * 4byte bigendian: length of control frame - * 4byte bigendian: type START - * 4byte bigendian: option: content-type - * 4byte bigendian: length of string - * string of content type (dnstap) - */ - n = 4+4+4+4+4+strlen(contenttype); - control = malloc(n); - if(!control) - return NULL; - control[0] = 0; - control[1] = htonl(4+4+4+strlen(contenttype)); - control[2] = htonl(FSTRM_CONTROL_FRAME_START); - control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); - control[4] = htonl(strlen(contenttype)); - memmove(&control[5], contenttype, strlen(contenttype)); - *len = n; - return control; -} - -void* fstrm_create_control_frame_stop(size_t* len) -{ - uint32_t* control; - size_t n; - /* stop framestream message: - * 4byte 0: control indicator. - * 4byte bigendian: length of control frame - * 4byte bigendian: type STOP - */ - n = 4+4+4; - control = malloc(n); - if(!control) - return NULL; - control[0] = 0; - control[1] = htonl(4); - control[2] = htonl(FSTRM_CONTROL_FRAME_STOP); - *len = n; - return control; -} - -void* fstrm_create_control_frame_ready(char* contenttype, size_t* len) -{ - uint32_t* control; - size_t n; - /* start bidirectional stream: - * 4 bytes 0 escape - * 4 bytes bigendian length of frame - * 4 bytes bigendian type READY - * 4 bytes bigendian frame option content type - * 4 bytes bigendian length of string - * string of content type. - */ - /* len includes the escape and framelength */ - n = 4+4+4+4+4+strlen(contenttype); - control = malloc(n); - if(!control) { - return NULL; - } - control[0] = 0; - control[1] = htonl(4+4+4+strlen(contenttype)); - control[2] = htonl(FSTRM_CONTROL_FRAME_READY); - control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); - control[4] = htonl(strlen(contenttype)); - memmove(&control[5], contenttype, strlen(contenttype)); - *len = n; - return control; -} - -void* fstrm_create_control_frame_accept(char* contenttype, size_t* len) -{ - uint32_t* control; - size_t n; - /* control frame on reply: - * 4 bytes 0 escape - * 4 bytes bigendian length of frame - * 4 bytes bigendian type ACCEPT - * 4 bytes bigendian frame option content type - * 4 bytes bigendian length of string - * string of content type. - */ - /* len includes the escape and framelength */ - n = 4+4+4+4+4+strlen(contenttype); - control = malloc(n); - if(!control) { - return NULL; - } - control[0] = 0; - control[1] = htonl(4+4+4+strlen(contenttype)); - control[2] = htonl(FSTRM_CONTROL_FRAME_ACCEPT); - control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); - control[4] = htonl(strlen(contenttype)); - memmove(&control[5], contenttype, strlen(contenttype)); - *len = n; - return control; -} - -void* fstrm_create_control_frame_finish(size_t* len) -{ - uint32_t* control; - size_t n; - /* control frame on reply: - * 4 bytes 0 escape - * 4 bytes bigendian length of frame - * 4 bytes bigendian type FINISH - */ - /* len includes the escape and framelength */ - n = 4+4+4; - control = malloc(n); - if(!control) { - return NULL; - } - control[0] = 0; - control[1] = htonl(4); - control[2] = htonl(FSTRM_CONTROL_FRAME_FINISH); - *len = n; - return control; -} - -char* fstrm_describe_control(void* pkt, size_t len) -{ - uint32_t frametype = 0; - char buf[512]; - char* str = buf; - size_t remain, slen = sizeof(buf); - uint8_t* pos; - - buf[0]=0; - if(len < 4) { - snprintf(buf, sizeof(buf), "malformed control frame, " - "too short, len=%u", (unsigned int)len); - return strdup(buf); - } - frametype = sldns_read_uint32(pkt); - if(frametype == FSTRM_CONTROL_FRAME_ACCEPT) { - (void)sldns_str_print(&str, &slen, "accept"); - } else if(frametype == FSTRM_CONTROL_FRAME_START) { - (void)sldns_str_print(&str, &slen, "start"); - } else if(frametype == FSTRM_CONTROL_FRAME_STOP) { - (void)sldns_str_print(&str, &slen, "stop"); - } else if(frametype == FSTRM_CONTROL_FRAME_READY) { - (void)sldns_str_print(&str, &slen, "ready"); - } else if(frametype == FSTRM_CONTROL_FRAME_FINISH) { - (void)sldns_str_print(&str, &slen, "finish"); - } else { - (void)sldns_str_print(&str, &slen, "type%d", (int)frametype); - } - - /* show the content type options */ - pos = pkt + 4; - remain = len - 4; - while(remain >= 8) { - uint32_t field_type = sldns_read_uint32(pos); - uint32_t field_len = sldns_read_uint32(pos+4); - if(remain < field_len) { - (void)sldns_str_print(&str, &slen, "malformed_field"); - break; - } - if(field_type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) { - char tempf[512]; - (void)sldns_str_print(&str, &slen, " content-type("); - if(field_len < sizeof(tempf)-1) { - memmove(tempf, pos+8, field_len); - tempf[field_len] = 0; - (void)sldns_str_print(&str, &slen, "%s", tempf); - } else { - (void)sldns_str_print(&str, &slen, ""); - } - (void)sldns_str_print(&str, &slen, ")"); - } else { - (void)sldns_str_print(&str, &slen, - " field(type %u, length %u)", - (unsigned int)field_type, - (unsigned int)field_len); - } - pos += 8 + field_len; - remain -= (8 + field_len); - } - if(remain > 0) - (void)sldns_str_print(&str, &slen, " trailing-bytes" - "(length %u)", (unsigned int)remain); - return strdup(buf); -} diff --git a/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.h b/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.h deleted file mode 100644 index 8b37d5f9..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dnstap_fstrm.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * dnstap/dnstap_fstrm.h - Frame Streams protocol for dnstap - * - * Copyright (c) 2020, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * - * Definitions for the Frame Streams data transport protocol for - * dnstap message logs. - */ - -#ifndef DNSTAP_FSTRM_H -#define DNSTAP_FSTRM_H - -/* Frame Streams data transfer protocol encode for DNSTAP messages. - * The protocol looks to be specified in the libfstrm library. - * - * Quick writeup for DNSTAP usage, from reading fstrm/control.h eloquent - * comments and fstrm/control.c for some bytesize details (the content type - * length). - * - * The Frame Streams can be unidirectional or bi-directional. - * bi-directional streams use control frame types READY, ACCEPT and FINISH. - * uni-directional streams use control frame types START and STOP. - * unknown control frame types should be ignored by the receiver, they - * do not change the data frame encoding. - * - * bi-directional control frames implement a simple handshake protocol - * between sender and receiver. - * - * The uni-directional control frames have one start and one stop frame, - * before and after the data. The start frame can have a content type. - * The start and stop frames are not optional. - * - * data frames are preceded by 4byte length, bigendian. - * zero length data frames are not possible, they are an escape that - * signals the presence of a control frame. - * - * a control frame consists of 0 value in 4byte bigendian, this is really - * the data frame length, with 0 the escape sequence that indicates one - * control frame follows. - * Then, 4byte bigendian, length of the control frame message. - * Then, the control frame payload (of that length). with in it: - * 4byte bigendian, control type (eg. START, STOP, READY, ACCEPT, FINISH). - * perhaps nothing more (STOP, FINISH), but for other types maybe - * control fields - * 4byte bigendian, the control-field-type, currently only content-type. - * 4byte bigendian, length of the string for this option. - * .. bytes of that string. - * - * The START type can have only one field. Field max len 256. - * control frame max frame length 512 (excludes the 0-escape and control - * frame length bytes). - * - * the bidirectional type of transmission is like this: - * client sends READY (with content type included), - * client waits for ACCEPT (with content type included), - * client sends START (with matched content type from ACCEPT) - * .. data frames - * client sends STOP. - * client waits for FINISH frame. - * - */ - -/** max length of Frame Streams content type field string */ -#define FSTRM_CONTENT_TYPE_LENGTH_MAX 256 -/** control frame value to denote the control frame ACCEPT */ -#define FSTRM_CONTROL_FRAME_ACCEPT 0x01 -/** control frame value to denote the control frame START */ -#define FSTRM_CONTROL_FRAME_START 0x02 -/** control frame value to denote the control frame STOP */ -#define FSTRM_CONTROL_FRAME_STOP 0x03 -/** control frame value to denote the control frame READY */ -#define FSTRM_CONTROL_FRAME_READY 0x04 -/** control frame value to denote the control frame FINISH */ -#define FSTRM_CONTROL_FRAME_FINISH 0x05 -/** the constant that denotes the control field type that is the - * string for the content type of the stream. */ -#define FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE 0x01 -/** the content type for DNSTAP frame streams */ -#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap" - -/** - * This creates an FSTRM control frame of type START. - * @param contenttype: a zero delimited string with the content type. - * eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as - * "protobuf:dnstap.Dnstap", for a dnstap frame stream. - * @param len: if a buffer is returned this is the length of that buffer. - * @return NULL on malloc failure. Returns a malloced buffer with the - * protocol message. The buffer starts with the 4 bytes of 0 that indicate - * a control frame. The buffer should be sent without preceding it with - * the 'len' variable (like data frames are), but straight the content of the - * buffer, because the lengths are included in the buffer. This is so that - * the zero control indicator can be included before the control frame length. - */ -void* fstrm_create_control_frame_start(char* contenttype, size_t* len); - -/** - * This creates an FSTRM control frame of type READY. - * @param contenttype: a zero delimited string with the content type. - * eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as - * "protobuf:dnstap.Dnstap", for a dnstap frame stream. - * @param len: if a buffer is returned this is the length of that buffer. - * @return NULL on malloc failure. Returns a malloced buffer with the - * protocol message. The buffer starts with the 4 bytes of 0 that indicate - * a control frame. The buffer should be sent without preceding it with - * the 'len' variable (like data frames are), but straight the content of the - * buffer, because the lengths are included in the buffer. This is so that - * the zero control indicator can be included before the control frame length. - */ -void* fstrm_create_control_frame_ready(char* contenttype, size_t* len); - -/** - * This creates an FSTRM control frame of type STOP. - * @param len: if a buffer is returned this is the length of that buffer. - * @return NULL on malloc failure. Returns a malloced buffer with the - * protocol message. The buffer starts with the 4 bytes of 0 that indicate - * a control frame. The buffer should be sent without preceding it with - * the 'len' variable (like data frames are), but straight the content of the - * buffer, because the lengths are included in the buffer. This is so that - * the zero control indicator can be included before the control frame length. - */ -void* fstrm_create_control_frame_stop(size_t* len); - -/** - * This creates an FSTRM control frame of type ACCEPT. - * @param contenttype: a zero delimited string with the content type. - * for dnstap streams use DNSTAP_CONTENT_TYPE. - * @param len: if a buffer is returned this is the length of that buffer. - * @return NULL on malloc failure. Returns a malloced buffer with the - * protocol message. The buffer starts with the 4 bytes of 0 that indicate - * a control frame. The buffer should be sent without preceding it with - * the 'len' variable (like data frames are), but straight the content of the - * buffer, because the lengths are included in the buffer. This is so that - * the zero control indicator can be included before the control frame length. - */ -void* fstrm_create_control_frame_accept(char* contenttype, size_t* len); - -/** - * This creates an FSTRM control frame of type FINISH. - * @param len: if a buffer is returned this is the length of that buffer. - * @return NULL on malloc failure. Returns a malloced buffer with the - * protocol message. The buffer starts with the 4 bytes of 0 that indicate - * a control frame. The buffer should be sent without preceding it with - * the 'len' variable (like data frames are), but straight the content of the - * buffer, because the lengths are included in the buffer. This is so that - * the zero control indicator can be included before the control frame length. - */ -void* fstrm_create_control_frame_finish(size_t* len); - -/** - * Return string that describes a control packet. For debug, logs. - * Like 'start content-type(protobuf:dnstap.Dnstap)' or 'stop'. - * @param pkt: the packet data, that is the data after the 4 zero start - * bytes and 4 length bytes. - * @param len: the length of the control packet data, in pkt. This is the - * ntohl of the 4 bytes length preceding the data. - * @return zero delimited string, malloced. Or NULL on malloc failure. - */ -char* fstrm_describe_control(void* pkt, size_t len); - -#endif /* DNSTAP_FSTRM_H */ diff --git a/crates/libunbound-sys/unbound/dnstap/dtstream.c b/crates/libunbound-sys/unbound/dnstap/dtstream.c deleted file mode 100644 index 9153f040..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dtstream.c +++ /dev/null @@ -1,2189 +0,0 @@ -/* - * dnstap/dtstream.c - Frame Streams thread for unbound DNSTAP - * - * Copyright (c) 2020, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * - * An implementation of the Frame Streams data transport protocol for - * the Unbound DNSTAP message logging facility. - */ - -#include "config.h" -#include "dnstap/dtstream.h" -#include "dnstap/dnstap_fstrm.h" -#include "util/config_file.h" -#include "util/ub_event.h" -#include "util/net_help.h" -#include "services/outside_network.h" -#include "sldns/sbuffer.h" -#ifdef HAVE_SYS_UN_H -#include -#endif -#include -#ifdef HAVE_OPENSSL_SSL_H -#include -#endif -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -/** number of messages to process in one output callback */ -#define DTIO_MESSAGES_PER_CALLBACK 100 -/** the msec to wait for reconnect (if not immediate, the first attempt) */ -#define DTIO_RECONNECT_TIMEOUT_MIN 10 -/** the msec to wait for reconnect max after backoff */ -#define DTIO_RECONNECT_TIMEOUT_MAX 1000 -/** the msec to wait for reconnect slow, to stop busy spinning on reconnect */ -#define DTIO_RECONNECT_TIMEOUT_SLOW 1000 -/** number of messages before wakeup of thread */ -#define DTIO_MSG_FOR_WAKEUP 32 - -/** maximum length of received frame */ -#define DTIO_RECV_FRAME_MAX_LEN 1000 - -struct stop_flush_info; -/** DTIO command channel commands */ -enum { - /** DTIO command channel stop */ - DTIO_COMMAND_STOP = 0, - /** DTIO command channel wakeup */ - DTIO_COMMAND_WAKEUP = 1 -} dtio_channel_command; - -/** open the output channel */ -static void dtio_open_output(struct dt_io_thread* dtio); -/** add output event for read and write */ -static int dtio_add_output_event_write(struct dt_io_thread* dtio); -/** start reconnection attempts */ -static void dtio_reconnect_enable(struct dt_io_thread* dtio); -/** stop from stop_flush event loop */ -static void dtio_stop_flush_exit(struct stop_flush_info* info); -/** setup a start control message */ -static int dtio_control_start_send(struct dt_io_thread* dtio); -#ifdef HAVE_SSL -/** enable briefly waiting for a read event, for SSL negotiation */ -static int dtio_enable_brief_read(struct dt_io_thread* dtio); -/** enable briefly waiting for a write event, for SSL negotiation */ -static int dtio_enable_brief_write(struct dt_io_thread* dtio); -#endif - -struct dt_msg_queue* -dt_msg_queue_create(struct comm_base* base) -{ - struct dt_msg_queue* mq = calloc(1, sizeof(*mq)); - if(!mq) return NULL; - mq->maxsize = 1*1024*1024; /* set max size of buffer, per worker, - about 1 M should contain 64K messages with some overhead, - or a whole bunch smaller ones */ - mq->wakeup_timer = comm_timer_create(base, mq_wakeup_cb, mq); - if(!mq->wakeup_timer) { - free(mq); - return NULL; - } - lock_basic_init(&mq->lock); - lock_protect(&mq->lock, mq, sizeof(*mq)); - return mq; -} - -/** clear the message list, caller must hold the lock */ -static void -dt_msg_queue_clear(struct dt_msg_queue* mq) -{ - struct dt_msg_entry* e = mq->first, *next=NULL; - while(e) { - next = e->next; - free(e->buf); - free(e); - e = next; - } - mq->first = NULL; - mq->last = NULL; - mq->cursize = 0; - mq->msgcount = 0; -} - -void -dt_msg_queue_delete(struct dt_msg_queue* mq) -{ - if(!mq) return; - lock_basic_destroy(&mq->lock); - dt_msg_queue_clear(mq); - comm_timer_delete(mq->wakeup_timer); - free(mq); -} - -/** make the dtio wake up by sending a wakeup command */ -static void dtio_wakeup(struct dt_io_thread* dtio) -{ - uint8_t cmd = DTIO_COMMAND_WAKEUP; - if(!dtio) return; - if(!dtio->started) return; - - while(1) { - ssize_t r = write(dtio->commandpipe[1], &cmd, sizeof(cmd)); - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - continue; -#else - if(WSAGetLastError() == WSAEINPROGRESS) - continue; - if(WSAGetLastError() == WSAEWOULDBLOCK) - continue; -#endif - log_err("dnstap io wakeup: write: %s", - sock_strerror(errno)); - break; - } - break; - } -} - -void -mq_wakeup_cb(void* arg) -{ - struct dt_msg_queue* mq = (struct dt_msg_queue*)arg; - /* even if the dtio is already active, because perhaps much - * traffic suddenly, we leave the timer running to save on - * managing it, the once a second timer is less work then - * starting and stopping the timer frequently */ - lock_basic_lock(&mq->dtio->wakeup_timer_lock); - mq->dtio->wakeup_timer_enabled = 0; - lock_basic_unlock(&mq->dtio->wakeup_timer_lock); - dtio_wakeup(mq->dtio); -} - -/** start timer to wakeup dtio because there is content in the queue */ -static void -dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow) -{ - struct timeval tv = {0}; - /* Start a timer to process messages to be logged. - * If we woke up the dtio thread for every message, the wakeup - * messages take up too much processing power. If the queue - * fills up the wakeup happens immediately. The timer wakes it up - * if there are infrequent messages to log. */ - - /* we cannot start a timer in dtio thread, because it is a different - * thread and its event base is in use by the other thread, it would - * give race conditions if we tried to modify its event base, - * and locks would wait until it woke up, and this is what we do. */ - - /* do not start the timer if a timer already exists, perhaps - * in another worker. So this variable is protected by a lock in - * dtio. */ - - /* If we need to wakeupnow, 0 the timer to force the callback. */ - lock_basic_lock(&mq->dtio->wakeup_timer_lock); - if(mq->dtio->wakeup_timer_enabled) { - if(wakeupnow) { - comm_timer_set(mq->wakeup_timer, &tv); - } - lock_basic_unlock(&mq->dtio->wakeup_timer_lock); - return; - } - mq->dtio->wakeup_timer_enabled = 1; /* we are going to start one */ - - /* start the timer, in mq, in the event base of our worker */ - if(!wakeupnow) { - tv.tv_sec = 1; - tv.tv_usec = 0; - } - comm_timer_set(mq->wakeup_timer, &tv); - lock_basic_unlock(&mq->dtio->wakeup_timer_lock); -} - -void -dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len) -{ - int wakeupnow = 0, wakeupstarttimer = 0; - struct dt_msg_entry* entry; - - /* check conditions */ - if(!buf) return; - if(len == 0) { - /* it is not possible to log entries with zero length, - * because the framestream protocol does not carry it. - * However the protobuf serialization does not create zero - * length datagrams for dnstap, so this should not happen. */ - free(buf); - return; - } - if(!mq) { - free(buf); - return; - } - - /* allocate memory for queue entry */ - entry = malloc(sizeof(*entry)); - if(!entry) { - log_err("out of memory logging dnstap"); - free(buf); - return; - } - entry->next = NULL; - entry->buf = buf; - entry->len = len; - - /* acquire lock */ - lock_basic_lock(&mq->lock); - /* if list was empty, start timer for (eventual) wakeup */ - if(mq->first == NULL) - wakeupstarttimer = 1; - /* if list contains more than wakeupnum elements, wakeup now, - * or if list is (going to be) almost full */ - if(mq->msgcount == DTIO_MSG_FOR_WAKEUP || - (mq->cursize < mq->maxsize * 9 / 10 && - mq->cursize+len >= mq->maxsize * 9 / 10)) - wakeupnow = 1; - /* see if it is going to fit */ - if(mq->cursize + len > mq->maxsize) { - /* buffer full, or congested. */ - /* drop */ - lock_basic_unlock(&mq->lock); - free(buf); - free(entry); - return; - } - mq->cursize += len; - mq->msgcount ++; - /* append to list */ - if(mq->last) { - mq->last->next = entry; - } else { - mq->first = entry; - } - mq->last = entry; - /* release lock */ - lock_basic_unlock(&mq->lock); - - if(wakeupnow || wakeupstarttimer) { - dt_msg_queue_start_timer(mq, wakeupnow); - } -} - -struct dt_io_thread* dt_io_thread_create(void) -{ - struct dt_io_thread* dtio = calloc(1, sizeof(*dtio)); - lock_basic_init(&dtio->wakeup_timer_lock); - lock_protect(&dtio->wakeup_timer_lock, &dtio->wakeup_timer_enabled, - sizeof(dtio->wakeup_timer_enabled)); - return dtio; -} - -void dt_io_thread_delete(struct dt_io_thread* dtio) -{ - struct dt_io_list_item* item, *nextitem; - if(!dtio) return; - lock_basic_destroy(&dtio->wakeup_timer_lock); - item=dtio->io_list; - while(item) { - nextitem = item->next; - free(item); - item = nextitem; - } - free(dtio->socket_path); - free(dtio->ip_str); - free(dtio->tls_server_name); - free(dtio->client_key_file); - free(dtio->client_cert_file); - if(dtio->ssl_ctx) { -#ifdef HAVE_SSL - SSL_CTX_free(dtio->ssl_ctx); -#endif - } - free(dtio); -} - -int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg) -{ - if(!cfg->dnstap) { - log_warn("cannot setup dnstap because dnstap-enable is no"); - return 0; - } - - /* what type of connectivity do we have */ - if(cfg->dnstap_ip && cfg->dnstap_ip[0]) { - if(cfg->dnstap_tls) - dtio->upstream_is_tls = 1; - else dtio->upstream_is_tcp = 1; - } else { - dtio->upstream_is_unix = 1; - } - dtio->is_bidirectional = cfg->dnstap_bidirectional; - - if(dtio->upstream_is_unix) { - char* nm; - if(!cfg->dnstap_socket_path || - cfg->dnstap_socket_path[0]==0) { - log_err("dnstap setup: no dnstap-socket-path for " - "socket connect"); - return 0; - } - nm = cfg->dnstap_socket_path; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - nm += strlen(cfg->chrootdir); - free(dtio->socket_path); - dtio->socket_path = strdup(nm); - if(!dtio->socket_path) { - log_err("dnstap setup: malloc failure"); - return 0; - } - } - - if(dtio->upstream_is_tcp || dtio->upstream_is_tls) { - if(!cfg->dnstap_ip || cfg->dnstap_ip[0] == 0) { - log_err("dnstap setup: no dnstap-ip for TCP connect"); - return 0; - } - free(dtio->ip_str); - dtio->ip_str = strdup(cfg->dnstap_ip); - if(!dtio->ip_str) { - log_err("dnstap setup: malloc failure"); - return 0; - } - } - - if(dtio->upstream_is_tls) { -#ifdef HAVE_SSL - if(cfg->dnstap_tls_server_name && - cfg->dnstap_tls_server_name[0]) { - free(dtio->tls_server_name); - dtio->tls_server_name = strdup( - cfg->dnstap_tls_server_name); - if(!dtio->tls_server_name) { - log_err("dnstap setup: malloc failure"); - return 0; - } - if(!check_auth_name_for_ssl(dtio->tls_server_name)) - return 0; - } - if(cfg->dnstap_tls_client_key_file && - cfg->dnstap_tls_client_key_file[0]) { - dtio->use_client_certs = 1; - free(dtio->client_key_file); - dtio->client_key_file = strdup( - cfg->dnstap_tls_client_key_file); - if(!dtio->client_key_file) { - log_err("dnstap setup: malloc failure"); - return 0; - } - if(!cfg->dnstap_tls_client_cert_file || - cfg->dnstap_tls_client_cert_file[0]==0) { - log_err("dnstap setup: client key " - "authentication enabled with " - "dnstap-tls-client-key-file, but " - "no dnstap-tls-client-cert-file " - "is given"); - return 0; - } - free(dtio->client_cert_file); - dtio->client_cert_file = strdup( - cfg->dnstap_tls_client_cert_file); - if(!dtio->client_cert_file) { - log_err("dnstap setup: malloc failure"); - return 0; - } - } else { - dtio->use_client_certs = 0; - dtio->client_key_file = NULL; - dtio->client_cert_file = NULL; - } - - if(cfg->dnstap_tls_cert_bundle) { - dtio->ssl_ctx = connect_sslctx_create( - dtio->client_key_file, - dtio->client_cert_file, - cfg->dnstap_tls_cert_bundle, 0); - } else { - dtio->ssl_ctx = connect_sslctx_create( - dtio->client_key_file, - dtio->client_cert_file, - cfg->tls_cert_bundle, cfg->tls_win_cert); - } - if(!dtio->ssl_ctx) { - log_err("could not setup SSL CTX"); - return 0; - } - dtio->tls_use_sni = cfg->tls_use_sni; -#endif /* HAVE_SSL */ - } - return 1; -} - -int dt_io_thread_register_queue(struct dt_io_thread* dtio, - struct dt_msg_queue* mq) -{ - struct dt_io_list_item* item = malloc(sizeof(*item)); - if(!item) return 0; - lock_basic_lock(&mq->lock); - mq->dtio = dtio; - lock_basic_unlock(&mq->lock); - item->queue = mq; - item->next = dtio->io_list; - dtio->io_list = item; - dtio->io_list_iter = NULL; - return 1; -} - -void dt_io_thread_unregister_queue(struct dt_io_thread* dtio, - struct dt_msg_queue* mq) -{ - struct dt_io_list_item* item, *prev=NULL; - if(!dtio) return; - item = dtio->io_list; - while(item) { - if(item->queue == mq) { - /* found it */ - if(prev) prev->next = item->next; - else dtio->io_list = item->next; - /* the queue itself only registered, not deleted */ - lock_basic_lock(&item->queue->lock); - item->queue->dtio = NULL; - lock_basic_unlock(&item->queue->lock); - free(item); - dtio->io_list_iter = NULL; - return; - } - prev = item; - item = item->next; - } -} - -/** pick a message from the queue, the routine locks and unlocks, - * returns true if there is a message */ -static int dt_msg_queue_pop(struct dt_msg_queue* mq, void** buf, - size_t* len) -{ - lock_basic_lock(&mq->lock); - if(mq->first) { - struct dt_msg_entry* entry = mq->first; - mq->first = entry->next; - if(!entry->next) mq->last = NULL; - mq->cursize -= entry->len; - mq->msgcount --; - lock_basic_unlock(&mq->lock); - - *buf = entry->buf; - *len = entry->len; - free(entry); - return 1; - } - lock_basic_unlock(&mq->lock); - return 0; -} - -/** find message in queue, false if no message, true if message to send */ -static int dtio_find_in_queue(struct dt_io_thread* dtio, - struct dt_msg_queue* mq) -{ - void* buf=NULL; - size_t len=0; - if(dt_msg_queue_pop(mq, &buf, &len)) { - dtio->cur_msg = buf; - dtio->cur_msg_len = len; - dtio->cur_msg_done = 0; - dtio->cur_msg_len_done = 0; - return 1; - } - return 0; -} - -/** find a new message to write, search message queues, false if none */ -static int dtio_find_msg(struct dt_io_thread* dtio) -{ - struct dt_io_list_item *spot, *item; - - spot = dtio->io_list_iter; - /* use the next queue for the next message lookup, - * if we hit the end(NULL) the NULL restarts the iter at start. */ - if(spot) - dtio->io_list_iter = spot->next; - else if(dtio->io_list) - dtio->io_list_iter = dtio->io_list->next; - - /* scan from spot to end-of-io_list */ - item = spot; - while(item) { - if(dtio_find_in_queue(dtio, item->queue)) - return 1; - item = item->next; - } - /* scan starting at the start-of-list (to wrap around the end) */ - item = dtio->io_list; - while(item) { - if(dtio_find_in_queue(dtio, item->queue)) - return 1; - item = item->next; - } - return 0; -} - -/** callback for the dnstap reconnect, to start reconnecting to output */ -void dtio_reconnect_timeout_cb(int ATTR_UNUSED(fd), - short ATTR_UNUSED(bits), void* arg) -{ - struct dt_io_thread* dtio = (struct dt_io_thread*)arg; - dtio->reconnect_is_added = 0; - verbose(VERB_ALGO, "dnstap io: reconnect timer"); - - dtio_open_output(dtio); - if(dtio->event) { - if(!dtio_add_output_event_write(dtio)) - return; - /* nothing wrong so far, wait on the output event */ - return; - } - /* exponential backoff and retry on timer */ - dtio_reconnect_enable(dtio); -} - -/** attempt to reconnect to the output, after a timeout */ -static void dtio_reconnect_enable(struct dt_io_thread* dtio) -{ - struct timeval tv; - int msec; - if(dtio->want_to_exit) return; - if(dtio->reconnect_is_added) - return; /* already done */ - - /* exponential backoff, store the value for next timeout */ - msec = dtio->reconnect_timeout; - if(msec == 0) { - dtio->reconnect_timeout = DTIO_RECONNECT_TIMEOUT_MIN; - } else { - dtio->reconnect_timeout = msec*2; - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MAX) - dtio->reconnect_timeout = DTIO_RECONNECT_TIMEOUT_MAX; - } - verbose(VERB_ALGO, "dnstap io: set reconnect attempt after %d msec", - msec); - - /* setup wait timer */ - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = msec/1000; - tv.tv_usec = (msec%1000)*1000; - if(ub_timer_add(dtio->reconnect_timer, dtio->event_base, - &dtio_reconnect_timeout_cb, dtio, &tv) != 0) { - log_err("dnstap io: could not reconnect ev timer add"); - return; - } - dtio->reconnect_is_added = 1; -} - -/** remove dtio reconnect timer */ -static void dtio_reconnect_del(struct dt_io_thread* dtio) -{ - if(!dtio->reconnect_is_added) - return; - ub_timer_del(dtio->reconnect_timer); - dtio->reconnect_is_added = 0; -} - -/** clear the reconnect exponential backoff timer. - * We have successfully connected so we can try again with short timeouts. */ -static void dtio_reconnect_clear(struct dt_io_thread* dtio) -{ - dtio->reconnect_timeout = 0; - dtio_reconnect_del(dtio); -} - -/** reconnect slowly, because we already know we have to wait for a bit */ -static void dtio_reconnect_slow(struct dt_io_thread* dtio, int msec) -{ - dtio_reconnect_del(dtio); - dtio->reconnect_timeout = msec; - dtio_reconnect_enable(dtio); -} - -/** delete the current message in the dtio, and reset counters */ -static void dtio_cur_msg_free(struct dt_io_thread* dtio) -{ - free(dtio->cur_msg); - dtio->cur_msg = NULL; - dtio->cur_msg_len = 0; - dtio->cur_msg_done = 0; - dtio->cur_msg_len_done = 0; -} - -/** delete the buffer and counters used to read frame */ -static void dtio_read_frame_free(struct dt_frame_read_buf* rb) -{ - if(rb->buf) { - free(rb->buf); - rb->buf = NULL; - } - rb->buf_count = 0; - rb->buf_cap = 0; - rb->frame_len = 0; - rb->frame_len_done = 0; - rb->control_frame = 0; -} - -/** del the output file descriptor event for listening */ -static void dtio_del_output_event(struct dt_io_thread* dtio) -{ - if(!dtio->event_added) - return; - ub_event_del(dtio->event); - dtio->event_added = 0; - dtio->event_added_is_write = 0; -} - -/** close dtio socket and set it to -1 */ -static void dtio_close_fd(struct dt_io_thread* dtio) -{ - sock_close(dtio->fd); - dtio->fd = -1; -} - -/** close and stop the output file descriptor event */ -static void dtio_close_output(struct dt_io_thread* dtio) -{ - if(!dtio->event) - return; - ub_event_free(dtio->event); - dtio->event = NULL; - if(dtio->ssl) { -#ifdef HAVE_SSL - SSL_shutdown(dtio->ssl); - SSL_free(dtio->ssl); - dtio->ssl = NULL; -#endif - } - dtio_close_fd(dtio); - - /* if there is a (partial) message, discard it - * we cannot send (the remainder of) it, and a new - * connection needs to start with a control frame. */ - if(dtio->cur_msg) { - dtio_cur_msg_free(dtio); - } - - dtio->ready_frame_sent = 0; - dtio->accept_frame_received = 0; - dtio_read_frame_free(&dtio->read_frame); - - dtio_reconnect_enable(dtio); -} - -/** check for pending nonblocking connect errors, - * returns 1 if it is okay. -1 on error (close it), 0 to try later */ -static int dtio_check_nb_connect(struct dt_io_thread* dtio) -{ - int error = 0; - socklen_t len = (socklen_t)sizeof(error); - if(!dtio->check_nb_connect) - return 1; /* everything okay */ - if(getsockopt(dtio->fd, SOL_SOCKET, SO_ERROR, (void*)&error, - &len) < 0) { -#ifndef USE_WINSOCK - error = errno; /* on solaris errno is error */ -#else - error = WSAGetLastError(); -#endif - } -#ifndef USE_WINSOCK -#if defined(EINPROGRESS) && defined(EWOULDBLOCK) - if(error == EINPROGRESS || error == EWOULDBLOCK) - return 0; /* try again later */ -#endif -#else - if(error == WSAEINPROGRESS) { - return 0; /* try again later */ - } else if(error == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock((dtio->stop_flush_event? - dtio->stop_flush_event:dtio->event), UB_EV_WRITE); - return 0; /* try again later */ - } -#endif - if(error != 0) { - char* to = dtio->socket_path; - if(!to) to = dtio->ip_str; - if(!to) to = ""; - log_err("dnstap io: failed to connect to \"%s\": %s", - to, sock_strerror(error)); - return -1; /* error, close it */ - } - - if(dtio->ip_str) - verbose(VERB_DETAIL, "dnstap io: connected to %s", - dtio->ip_str); - else if(dtio->socket_path) - verbose(VERB_DETAIL, "dnstap io: connected to \"%s\"", - dtio->socket_path); - dtio_reconnect_clear(dtio); - dtio->check_nb_connect = 0; - return 1; /* everything okay */ -} - -#ifdef HAVE_SSL -/** write to ssl output - * returns number of bytes written, 0 if nothing happened, - * try again later, or -1 if the channel is to be closed. */ -static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf, - size_t len) -{ - int r; - ERR_clear_error(); - r = SSL_write(dtio->ssl, buf, len); - if(r <= 0) { - int want = SSL_get_error(dtio->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - /* closed */ - return -1; - } else if(want == SSL_ERROR_WANT_READ) { - /* we want a brief read event */ - dtio_enable_brief_read(dtio); - return 0; - } else if(want == SSL_ERROR_WANT_WRITE) { - /* write again later */ - return 0; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return -1; /* silence 'broken pipe' */ -#endif -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return -1; /* silence reset by peer */ -#endif - if(errno != 0) { - log_err("dnstap io, SSL_write syscall: %s", - strerror(errno)); - } - return -1; - } - log_crypto_err("dnstap io, could not SSL_write"); - return -1; - } - return r; -} -#endif /* HAVE_SSL */ - -/** write buffer to output. - * returns number of bytes written, 0 if nothing happened, - * try again later, or -1 if the channel is to be closed. */ -static int dtio_write_buf(struct dt_io_thread* dtio, uint8_t* buf, - size_t len) -{ - ssize_t ret; - if(dtio->fd == -1) - return -1; -#ifdef HAVE_SSL - if(dtio->ssl) - return dtio_write_ssl(dtio, buf, len); -#endif - ret = send(dtio->fd, (void*)buf, len, 0); - if(ret == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 0; -#else - if(WSAGetLastError() == WSAEINPROGRESS) - return 0; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock((dtio->stop_flush_event? - dtio->stop_flush_event:dtio->event), - UB_EV_WRITE); - return 0; - } -#endif - log_err("dnstap io: failed send: %s", sock_strerror(errno)); - return -1; - } - return ret; -} - -#ifdef HAVE_WRITEV -/** write with writev, len and message, in one write, if possible. - * return true if message is done, false if incomplete */ -static int dtio_write_with_writev(struct dt_io_thread* dtio) -{ - uint32_t sendlen = htonl(dtio->cur_msg_len); - struct iovec iov[2]; - ssize_t r; - iov[0].iov_base = ((uint8_t*)&sendlen)+dtio->cur_msg_len_done; - iov[0].iov_len = sizeof(sendlen)-dtio->cur_msg_len_done; - iov[1].iov_base = dtio->cur_msg; - iov[1].iov_len = dtio->cur_msg_len; - log_assert(iov[0].iov_len > 0); - r = writev(dtio->fd, iov, 2); - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 0; -#else - if(WSAGetLastError() == WSAEINPROGRESS) - return 0; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock((dtio->stop_flush_event? - dtio->stop_flush_event:dtio->event), - UB_EV_WRITE); - return 0; - } -#endif - log_err("dnstap io: failed writev: %s", sock_strerror(errno)); - /* close the channel */ - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return 0; - } - /* written r bytes */ - dtio->cur_msg_len_done += r; - if(dtio->cur_msg_len_done < 4) - return 0; - if(dtio->cur_msg_len_done > 4) { - dtio->cur_msg_done = dtio->cur_msg_len_done-4; - dtio->cur_msg_len_done = 4; - } - if(dtio->cur_msg_done < dtio->cur_msg_len) - return 0; - return 1; -} -#endif /* HAVE_WRITEV */ - -/** write more of the length, preceding the data frame. - * return true if message is done, false if incomplete. */ -static int dtio_write_more_of_len(struct dt_io_thread* dtio) -{ - uint32_t sendlen; - int r; - if(dtio->cur_msg_len_done >= 4) - return 1; -#ifdef HAVE_WRITEV - if(!dtio->ssl) { - /* we try writev for everything.*/ - return dtio_write_with_writev(dtio); - } -#endif /* HAVE_WRITEV */ - sendlen = htonl(dtio->cur_msg_len); - r = dtio_write_buf(dtio, - ((uint8_t*)&sendlen)+dtio->cur_msg_len_done, - sizeof(sendlen)-dtio->cur_msg_len_done); - if(r == -1) { - /* close the channel */ - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return 0; - } else if(r == 0) { - /* try again later */ - return 0; - } - dtio->cur_msg_len_done += r; - if(dtio->cur_msg_len_done < 4) - return 0; - return 1; -} - -/** write more of the data frame. - * return true if message is done, false if incomplete. */ -static int dtio_write_more_of_data(struct dt_io_thread* dtio) -{ - int r; - if(dtio->cur_msg_done >= dtio->cur_msg_len) - return 1; - r = dtio_write_buf(dtio, - ((uint8_t*)dtio->cur_msg)+dtio->cur_msg_done, - dtio->cur_msg_len - dtio->cur_msg_done); - if(r == -1) { - /* close the channel */ - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return 0; - } else if(r == 0) { - /* try again later */ - return 0; - } - dtio->cur_msg_done += r; - if(dtio->cur_msg_done < dtio->cur_msg_len) - return 0; - return 1; -} - -/** write more of the current message. false if incomplete, true if - * the message is done */ -static int dtio_write_more(struct dt_io_thread* dtio) -{ - if(dtio->cur_msg_len_done < 4) { - if(!dtio_write_more_of_len(dtio)) - return 0; - } - if(dtio->cur_msg_done < dtio->cur_msg_len) { - if(!dtio_write_more_of_data(dtio)) - return 0; - } - return 1; -} - -/** Receive bytes from dtio->fd, store in buffer. Returns 0: closed, - * -1: continue, >0: number of bytes read into buffer */ -static ssize_t receive_bytes(struct dt_io_thread* dtio, void* buf, size_t len) { - ssize_t r; - r = recv(dtio->fd, (void*)buf, len, MSG_DONTWAIT); - if(r == -1) { - char* to = dtio->socket_path; - if(!to) to = dtio->ip_str; - if(!to) to = ""; -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return -1; /* try later */ -#else - if(WSAGetLastError() == WSAEINPROGRESS) { - return -1; /* try later */ - } else if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock( - (dtio->stop_flush_event? - dtio->stop_flush_event:dtio->event), - UB_EV_READ); - return -1; /* try later */ - } -#endif - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - verbosity < 4) - return 0; /* no log retries on low verbosity */ - log_err("dnstap io: output closed, recv %s: %s", to, - strerror(errno)); - /* and close below */ - return 0; - } - if(r == 0) { - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - verbosity < 4) - return 0; /* no log retries on low verbosity */ - verbose(VERB_DETAIL, "dnstap io: output closed by the other side"); - /* and close below */ - return 0; - } - /* something was received */ - return r; -} - -#ifdef HAVE_SSL -/** Receive bytes over TLS from dtio->fd, store in buffer. Returns 0: closed, - * -1: continue, >0: number of bytes read into buffer */ -static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len) -{ - int r; - ERR_clear_error(); - r = SSL_read(dtio->ssl, buf, len); - if(r <= 0) { - int want = SSL_get_error(dtio->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - verbosity < 4) - return 0; /* no log retries on low verbosity */ - verbose(VERB_DETAIL, "dnstap io: output closed by the " - "other side"); - return 0; - } else if(want == SSL_ERROR_WANT_READ) { - /* continue later */ - return -1; - } else if(want == SSL_ERROR_WANT_WRITE) { - (void)dtio_enable_brief_write(dtio); - return -1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - errno == ECONNRESET && verbosity < 4) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - verbose(VERB_DETAIL, "dnstap io: output closed by the " - "other side"); - return 0; - } - log_crypto_err("could not SSL_read"); - verbose(VERB_DETAIL, "dnstap io: output closed by the " - "other side"); - return 0; - } - return r; -} -#endif /* HAVE_SSL */ - -/** check if the output fd has been closed, - * it returns false if the stream is closed. */ -static int dtio_check_close(struct dt_io_thread* dtio) -{ - /* we don't want to read any packets, but if there are we can - * discard the input (ignore it). Ignore of unknown (control) - * packets is okay for the framestream protocol. And also, the - * read call can return that the stream has been closed by the - * other side. */ - uint8_t buf[1024]; - int r = -1; - - - if(dtio->fd == -1) return 0; - - while(r != 0) { - /* not interested in buffer content, overwrite */ - r = receive_bytes(dtio, (void*)buf, sizeof(buf)); - if(r == -1) - return 1; - } - /* the other end has been closed */ - /* close the channel */ - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return 0; -} - -/** Read accept frame. Returns -1: continue reading, 0: closed, - * 1: valid accept received. */ -static int dtio_read_accept_frame(struct dt_io_thread* dtio) -{ - int r; - size_t read_frame_done; - while(dtio->read_frame.frame_len_done < 4) { -#ifdef HAVE_SSL - if(dtio->ssl) { - r = ssl_read_bytes(dtio, - (uint8_t*)&dtio->read_frame.frame_len+ - dtio->read_frame.frame_len_done, - 4-dtio->read_frame.frame_len_done); - } else { -#endif - r = receive_bytes(dtio, - (uint8_t*)&dtio->read_frame.frame_len+ - dtio->read_frame.frame_len_done, - 4-dtio->read_frame.frame_len_done); -#ifdef HAVE_SSL - } -#endif - if(r == -1) - return -1; /* continue reading */ - if(r == 0) { - /* connection closed */ - goto close_connection; - } - dtio->read_frame.frame_len_done += r; - if(dtio->read_frame.frame_len_done < 4) - return -1; /* continue reading */ - - if(dtio->read_frame.frame_len == 0) { - dtio->read_frame.frame_len_done = 0; - dtio->read_frame.control_frame = 1; - continue; - } - dtio->read_frame.frame_len = ntohl(dtio->read_frame.frame_len); - if(dtio->read_frame.frame_len > DTIO_RECV_FRAME_MAX_LEN) { - verbose(VERB_OPS, "dnstap: received frame exceeds max " - "length of %d bytes, closing connection", - DTIO_RECV_FRAME_MAX_LEN); - goto close_connection; - } - dtio->read_frame.buf = calloc(1, dtio->read_frame.frame_len); - dtio->read_frame.buf_cap = dtio->read_frame.frame_len; - if(!dtio->read_frame.buf) { - log_err("dnstap io: out of memory (creating read " - "buffer)"); - goto close_connection; - } - } - if(dtio->read_frame.buf_count < dtio->read_frame.frame_len) { -#ifdef HAVE_SSL - if(dtio->ssl) { - r = ssl_read_bytes(dtio, dtio->read_frame.buf+ - dtio->read_frame.buf_count, - dtio->read_frame.buf_cap- - dtio->read_frame.buf_count); - } else { -#endif - r = receive_bytes(dtio, dtio->read_frame.buf+ - dtio->read_frame.buf_count, - dtio->read_frame.buf_cap- - dtio->read_frame.buf_count); -#ifdef HAVE_SSL - } -#endif - if(r == -1) - return -1; /* continue reading */ - if(r == 0) { - /* connection closed */ - goto close_connection; - } - dtio->read_frame.buf_count += r; - if(dtio->read_frame.buf_count < dtio->read_frame.frame_len) - return -1; /* continue reading */ - } - - /* Complete frame received, check if this is a valid ACCEPT control - * frame. */ - if(dtio->read_frame.frame_len < 4) { - verbose(VERB_OPS, "dnstap: invalid data received"); - goto close_connection; - } - if(sldns_read_uint32(dtio->read_frame.buf) != - FSTRM_CONTROL_FRAME_ACCEPT) { - verbose(VERB_ALGO, "dnstap: invalid control type received, " - "ignored"); - dtio->ready_frame_sent = 0; - dtio->accept_frame_received = 0; - dtio_read_frame_free(&dtio->read_frame); - return -1; - } - read_frame_done = 4; /* control frame type */ - - /* Iterate over control fields, ignore unknown types. - * Need to be able to read at least 8 bytes (control field type + - * length). */ - while(read_frame_done+8 < dtio->read_frame.frame_len) { - uint32_t type = sldns_read_uint32(dtio->read_frame.buf + - read_frame_done); - uint32_t len = sldns_read_uint32(dtio->read_frame.buf + - read_frame_done + 4); - if(type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) { - if(len == strlen(DNSTAP_CONTENT_TYPE) && - read_frame_done+8+len <= - dtio->read_frame.frame_len && - memcmp(dtio->read_frame.buf + read_frame_done + - + 8, DNSTAP_CONTENT_TYPE, len) == 0) { - if(!dtio_control_start_send(dtio)) { - verbose(VERB_OPS, "dnstap io: out of " - "memory while sending START frame"); - goto close_connection; - } - dtio->accept_frame_received = 1; - if(!dtio_add_output_event_write(dtio)) - goto close_connection; - return 1; - } else { - /* unknown content type */ - verbose(VERB_ALGO, "dnstap: ACCEPT frame " - "contains unknown content type, " - "closing connection"); - goto close_connection; - } - } - /* unknown option, try next */ - read_frame_done += 8+len; - } - - -close_connection: - dtio_del_output_event(dtio); - dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW); - dtio_close_output(dtio); - return 0; -} - -/** add the output file descriptor event for listening, read only */ -static int dtio_add_output_event_read(struct dt_io_thread* dtio) -{ - if(!dtio->event) - return 0; - if(dtio->event_added && !dtio->event_added_is_write) - return 1; - /* we have to (re-)register the event */ - if(dtio->event_added) - ub_event_del(dtio->event); - ub_event_del_bits(dtio->event, UB_EV_WRITE); - if(ub_event_add(dtio->event, NULL) != 0) { - log_err("dnstap io: out of memory (adding event)"); - dtio->event_added = 0; - dtio->event_added_is_write = 0; - /* close output and start reattempts to open it */ - dtio_close_output(dtio); - return 0; - } - dtio->event_added = 1; - dtio->event_added_is_write = 0; - return 1; -} - -/** add the output file descriptor event for listening, read and write */ -static int dtio_add_output_event_write(struct dt_io_thread* dtio) -{ - if(!dtio->event) - return 0; - if(dtio->event_added && dtio->event_added_is_write) - return 1; - /* we have to (re-)register the event */ - if(dtio->event_added) - ub_event_del(dtio->event); - ub_event_add_bits(dtio->event, UB_EV_WRITE); - if(ub_event_add(dtio->event, NULL) != 0) { - log_err("dnstap io: out of memory (adding event)"); - dtio->event_added = 0; - dtio->event_added_is_write = 0; - /* close output and start reattempts to open it */ - dtio_close_output(dtio); - return 0; - } - dtio->event_added = 1; - dtio->event_added_is_write = 1; - return 1; -} - -/** put the dtio thread to sleep */ -static void dtio_sleep(struct dt_io_thread* dtio) -{ - /* unregister the event polling for write, because there is - * nothing to be written */ - (void)dtio_add_output_event_read(dtio); -} - -#ifdef HAVE_SSL -/** enable the brief read condition */ -static int dtio_enable_brief_read(struct dt_io_thread* dtio) -{ - dtio->ssl_brief_read = 1; - if(dtio->stop_flush_event) { - ub_event_del(dtio->stop_flush_event); - ub_event_del_bits(dtio->stop_flush_event, UB_EV_WRITE); - if(ub_event_add(dtio->stop_flush_event, NULL) != 0) { - log_err("dnstap io, stop flush, could not ub_event_add"); - return 0; - } - return 1; - } - return dtio_add_output_event_read(dtio); -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** disable the brief read condition */ -static int dtio_disable_brief_read(struct dt_io_thread* dtio) -{ - dtio->ssl_brief_read = 0; - if(dtio->stop_flush_event) { - ub_event_del(dtio->stop_flush_event); - ub_event_add_bits(dtio->stop_flush_event, UB_EV_WRITE); - if(ub_event_add(dtio->stop_flush_event, NULL) != 0) { - log_err("dnstap io, stop flush, could not ub_event_add"); - return 0; - } - return 1; - } - return dtio_add_output_event_write(dtio); -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** enable the brief write condition */ -static int dtio_enable_brief_write(struct dt_io_thread* dtio) -{ - dtio->ssl_brief_write = 1; - return dtio_add_output_event_write(dtio); -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** disable the brief write condition */ -static int dtio_disable_brief_write(struct dt_io_thread* dtio) -{ - dtio->ssl_brief_write = 0; - return dtio_add_output_event_read(dtio); -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** check peer verification after ssl handshake connection, false if closed*/ -static int dtio_ssl_check_peer(struct dt_io_thread* dtio) -{ - if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) { - /* verification */ - if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) { - X509* x = SSL_get_peer_certificate(dtio->ssl); - if(!x) { - verbose(VERB_ALGO, "dnstap io, %s, SSL " - "connection failed no certificate", - dtio->ip_str); - return 0; - } - log_cert(VERB_ALGO, "dnstap io, peer certificate", - x); -#ifdef HAVE_SSL_GET0_PEERNAME - if(SSL_get0_peername(dtio->ssl)) { - verbose(VERB_ALGO, "dnstap io, %s, SSL " - "connection to %s authenticated", - dtio->ip_str, - SSL_get0_peername(dtio->ssl)); - } else { -#endif - verbose(VERB_ALGO, "dnstap io, %s, SSL " - "connection authenticated", - dtio->ip_str); -#ifdef HAVE_SSL_GET0_PEERNAME - } -#endif - X509_free(x); - } else { - X509* x = SSL_get_peer_certificate(dtio->ssl); - if(x) { - log_cert(VERB_ALGO, "dnstap io, peer " - "certificate", x); - X509_free(x); - } - verbose(VERB_ALGO, "dnstap io, %s, SSL connection " - "failed: failed to authenticate", - dtio->ip_str); - return 0; - } - } else { - /* unauthenticated, the verify peer flag was not set - * in ssl when the ssl object was created from ssl_ctx */ - verbose(VERB_ALGO, "dnstap io, %s, SSL connection", - dtio->ip_str); - } - return 1; -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** perform ssl handshake, returns 1 if okay, 0 to stop */ -static int dtio_ssl_handshake(struct dt_io_thread* dtio, - struct stop_flush_info* info) -{ - int r; - if(dtio->ssl_brief_read) { - /* assume the brief read condition is satisfied, - * if we need more or again, we can set it again */ - if(!dtio_disable_brief_read(dtio)) { - if(info) dtio_stop_flush_exit(info); - return 0; - } - } - if(dtio->ssl_handshake_done) - return 1; - - ERR_clear_error(); - r = SSL_do_handshake(dtio->ssl); - if(r != 1) { - int want = SSL_get_error(dtio->ssl, r); - if(want == SSL_ERROR_WANT_READ) { - /* we want to read on the connection */ - if(!dtio_enable_brief_read(dtio)) { - if(info) dtio_stop_flush_exit(info); - return 0; - } - return 0; - } else if(want == SSL_ERROR_WANT_WRITE) { - /* we want to write on the connection */ - return 0; - } else if(r == 0) { - /* closed */ - if(info) dtio_stop_flush_exit(info); - dtio_del_output_event(dtio); - dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW); - dtio_close_output(dtio); - return 0; - } else if(want == SSL_ERROR_SYSCALL) { - /* SYSCALL and errno==0 means closed uncleanly */ - int silent = 0; -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - silent = 1; /* silence 'broken pipe' */ -#endif -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - silent = 1; /* silence reset by peer */ -#endif - if(errno == 0) - silent = 1; - if(!silent) - log_err("dnstap io, SSL_handshake syscall: %s", - strerror(errno)); - /* closed */ - if(info) dtio_stop_flush_exit(info); - dtio_del_output_event(dtio); - dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW); - dtio_close_output(dtio); - return 0; - } else { - unsigned long err = ERR_get_error(); - if(!squelch_err_ssl_handshake(err)) { - log_crypto_err_code("dnstap io, ssl handshake failed", - err); - verbose(VERB_OPS, "dnstap io, ssl handshake failed " - "from %s", dtio->ip_str); - } - /* closed */ - if(info) dtio_stop_flush_exit(info); - dtio_del_output_event(dtio); - dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW); - dtio_close_output(dtio); - return 0; - } - - } - /* check peer verification */ - dtio->ssl_handshake_done = 1; - - if(!dtio_ssl_check_peer(dtio)) { - /* closed */ - if(info) dtio_stop_flush_exit(info); - dtio_del_output_event(dtio); - dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW); - dtio_close_output(dtio); - return 0; - } - return 1; -} -#endif /* HAVE_SSL */ - -/** callback for the dnstap events, to write to the output */ -void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg) -{ - struct dt_io_thread* dtio = (struct dt_io_thread*)arg; - int i; - - if(dtio->check_nb_connect) { - int connect_err = dtio_check_nb_connect(dtio); - if(connect_err == -1) { - /* close the channel */ - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return; - } else if(connect_err == 0) { - /* try again later */ - return; - } - /* nonblocking connect check passed, continue */ - } - -#ifdef HAVE_SSL - if(dtio->ssl && - (!dtio->ssl_handshake_done || dtio->ssl_brief_read)) { - if(!dtio_ssl_handshake(dtio, NULL)) - return; - } -#endif - - if((bits&UB_EV_READ || dtio->ssl_brief_write)) { - if(dtio->ssl_brief_write) - (void)dtio_disable_brief_write(dtio); - if(dtio->ready_frame_sent && !dtio->accept_frame_received) { - if(dtio_read_accept_frame(dtio) <= 0) - return; - } else if(!dtio_check_close(dtio)) - return; - } - - /* loop to process a number of messages. This improves throughput, - * because selecting on write-event if not needed for busy messages - * (dnstap log) generation and if they need to all be written back. - * The write event is usually not blocked up. But not forever, - * because the event loop needs to stay responsive for other events. - * If there are no (more) messages, or if the output buffers get - * full, it returns out of the loop. */ - for(i=0; icur_msg) { - if(!dtio_find_msg(dtio)) { - if(i == 0) { - /* no messages on the first iteration, - * the queues are all empty */ - dtio_sleep(dtio); - } - return; /* nothing to do */ - } - } - - /* write it */ - if(dtio->cur_msg_done < dtio->cur_msg_len) { - if(!dtio_write_more(dtio)) - return; - } - - /* done with the current message */ - dtio_cur_msg_free(dtio); - - /* If this is a bidirectional stream the first message will be - * the READY control frame. We can only continue writing after - * receiving an ACCEPT control frame. */ - if(dtio->is_bidirectional && !dtio->ready_frame_sent) { - dtio->ready_frame_sent = 1; - (void)dtio_add_output_event_read(dtio); - break; - } - } -} - -/** callback for the dnstap commandpipe, to stop the dnstap IO */ -void dtio_cmd_cb(int fd, short ATTR_UNUSED(bits), void* arg) -{ - struct dt_io_thread* dtio = (struct dt_io_thread*)arg; - uint8_t cmd; - ssize_t r; - if(dtio->want_to_exit) - return; - r = read(fd, &cmd, sizeof(cmd)); - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return; /* ignore this */ -#else - if(WSAGetLastError() == WSAEINPROGRESS) - return; - if(WSAGetLastError() == WSAEWOULDBLOCK) - return; -#endif - log_err("dnstap io: failed to read: %s", sock_strerror(errno)); - /* and then fall through to quit the thread */ - } else if(r == 0) { - verbose(VERB_ALGO, "dnstap io: cmd channel closed"); - } else if(r == 1 && cmd == DTIO_COMMAND_STOP) { - verbose(VERB_ALGO, "dnstap io: cmd channel cmd quit"); - } else if(r == 1 && cmd == DTIO_COMMAND_WAKEUP) { - verbose(VERB_ALGO, "dnstap io: cmd channel cmd wakeup"); - - if(dtio->is_bidirectional && !dtio->accept_frame_received) { - verbose(VERB_ALGO, "dnstap io: cmd wakeup ignored, " - "waiting for ACCEPT control frame"); - return; - } - - /* reregister event */ - if(!dtio_add_output_event_write(dtio)) - return; - return; - } else if(r == 1) { - verbose(VERB_ALGO, "dnstap io: cmd channel unknown command"); - } - dtio->want_to_exit = 1; - if(ub_event_base_loopexit((struct ub_event_base*)dtio->event_base) - != 0) { - log_err("dnstap io: could not loopexit"); - } -} - -#ifndef THREADS_DISABLED -/** setup the event base for the dnstap io thread */ -static void dtio_setup_base(struct dt_io_thread* dtio, time_t* secs, - struct timeval* now) -{ - memset(now, 0, sizeof(*now)); - dtio->event_base = ub_default_event_base(0, secs, now); - if(!dtio->event_base) { - fatal_exit("dnstap io: could not create event_base"); - } -} -#endif /* THREADS_DISABLED */ - -/** setup the cmd event for dnstap io */ -static void dtio_setup_cmd(struct dt_io_thread* dtio) -{ - struct ub_event* cmdev; - fd_set_nonblock(dtio->commandpipe[0]); - cmdev = ub_event_new(dtio->event_base, dtio->commandpipe[0], - UB_EV_READ | UB_EV_PERSIST, &dtio_cmd_cb, dtio); - if(!cmdev) { - fatal_exit("dnstap io: out of memory"); - } - dtio->command_event = cmdev; - if(ub_event_add(cmdev, NULL) != 0) { - fatal_exit("dnstap io: out of memory (adding event)"); - } -} - -/** setup the reconnect event for dnstap io */ -static void dtio_setup_reconnect(struct dt_io_thread* dtio) -{ - dtio_reconnect_clear(dtio); - dtio->reconnect_timer = ub_event_new(dtio->event_base, -1, - UB_EV_TIMEOUT, &dtio_reconnect_timeout_cb, dtio); - if(!dtio->reconnect_timer) { - fatal_exit("dnstap io: out of memory"); - } -} - -/** - * structure to keep track of information during stop flush - */ -struct stop_flush_info { - /** the event base during stop flush */ - struct ub_event_base* base; - /** did we already want to exit this stop-flush event base */ - int want_to_exit_flush; - /** has the timer fired */ - int timer_done; - /** the dtio */ - struct dt_io_thread* dtio; - /** the stop control frame */ - void* stop_frame; - /** length of the stop frame */ - size_t stop_frame_len; - /** how much we have done of the stop frame */ - size_t stop_frame_done; -}; - -/** exit the stop flush base */ -static void dtio_stop_flush_exit(struct stop_flush_info* info) -{ - if(info->want_to_exit_flush) - return; - info->want_to_exit_flush = 1; - if(ub_event_base_loopexit(info->base) != 0) { - log_err("dnstap io: could not loopexit"); - } -} - -/** send the stop control, - * return true if completed the frame. */ -static int dtio_control_stop_send(struct stop_flush_info* info) -{ - struct dt_io_thread* dtio = info->dtio; - int r; - if(info->stop_frame_done >= info->stop_frame_len) - return 1; - r = dtio_write_buf(dtio, ((uint8_t*)info->stop_frame) + - info->stop_frame_done, info->stop_frame_len - - info->stop_frame_done); - if(r == -1) { - verbose(VERB_ALGO, "dnstap io: stop flush: output closed"); - dtio_stop_flush_exit(info); - return 0; - } - if(r == 0) { - /* try again later, or timeout */ - return 0; - } - info->stop_frame_done += r; - if(info->stop_frame_done < info->stop_frame_len) - return 0; /* not done yet */ - return 1; -} - -void dtio_stop_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), - void* arg) -{ - struct stop_flush_info* info = (struct stop_flush_info*)arg; - if(info->want_to_exit_flush) - return; - verbose(VERB_ALGO, "dnstap io: stop flush timer expired, stop flush"); - info->timer_done = 1; - dtio_stop_flush_exit(info); -} - -void dtio_stop_ev_cb(int ATTR_UNUSED(fd), short bits, void* arg) -{ - struct stop_flush_info* info = (struct stop_flush_info*)arg; - struct dt_io_thread* dtio = info->dtio; - if(info->want_to_exit_flush) - return; - if(dtio->check_nb_connect) { - /* we don't start the stop_flush if connect still - * in progress, but the check code is here, just in case */ - int connect_err = dtio_check_nb_connect(dtio); - if(connect_err == -1) { - /* close the channel, exit the stop flush */ - dtio_stop_flush_exit(info); - dtio_del_output_event(dtio); - dtio_close_output(dtio); - return; - } else if(connect_err == 0) { - /* try again later */ - return; - } - /* nonblocking connect check passed, continue */ - } -#ifdef HAVE_SSL - if(dtio->ssl && - (!dtio->ssl_handshake_done || dtio->ssl_brief_read)) { - if(!dtio_ssl_handshake(dtio, info)) - return; - } -#endif - - if((bits&UB_EV_READ)) { - if(!dtio_check_close(dtio)) { - if(dtio->fd == -1) { - verbose(VERB_ALGO, "dnstap io: " - "stop flush: output closed"); - dtio_stop_flush_exit(info); - } - return; - } - } - /* write remainder of last frame */ - if(dtio->cur_msg) { - if(dtio->cur_msg_done < dtio->cur_msg_len) { - if(!dtio_write_more(dtio)) { - if(dtio->fd == -1) { - verbose(VERB_ALGO, "dnstap io: " - "stop flush: output closed"); - dtio_stop_flush_exit(info); - } - return; - } - } - verbose(VERB_ALGO, "dnstap io: stop flush completed " - "last frame"); - dtio_cur_msg_free(dtio); - } - /* write stop frame */ - if(info->stop_frame_done < info->stop_frame_len) { - if(!dtio_control_stop_send(info)) - return; - verbose(VERB_ALGO, "dnstap io: stop flush completed " - "stop control frame"); - } - /* when last frame and stop frame are sent, exit */ - dtio_stop_flush_exit(info); -} - -/** flush at end, last packet and stop control */ -static void dtio_control_stop_flush(struct dt_io_thread* dtio) -{ - /* briefly attempt to flush the previous packet to the output, - * this could be a partial packet, or even the start control frame */ - time_t secs = 0; - struct timeval now; - struct stop_flush_info info; - struct timeval tv; - struct ub_event* timer, *stopev; - - if(dtio->fd == -1 || dtio->check_nb_connect) { - /* no connection or we have just connected, so nothing is - * sent yet, so nothing to stop or flush */ - return; - } - if(dtio->ssl && !dtio->ssl_handshake_done) { - /* no SSL connection has been established yet */ - return; - } - - memset(&info, 0, sizeof(info)); - memset(&now, 0, sizeof(now)); - info.dtio = dtio; - info.base = ub_default_event_base(0, &secs, &now); - if(!info.base) { - log_err("dnstap io: malloc failure"); - return; - } - timer = ub_event_new(info.base, -1, UB_EV_TIMEOUT, - &dtio_stop_timer_cb, &info); - if(!timer) { - log_err("dnstap io: malloc failure"); - ub_event_base_free(info.base); - return; - } - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = 2; - if(ub_timer_add(timer, info.base, &dtio_stop_timer_cb, &info, - &tv) != 0) { - log_err("dnstap io: cannot event_timer_add"); - ub_event_free(timer); - ub_event_base_free(info.base); - return; - } - stopev = ub_event_new(info.base, dtio->fd, UB_EV_READ | - UB_EV_WRITE | UB_EV_PERSIST, &dtio_stop_ev_cb, &info); - if(!stopev) { - log_err("dnstap io: malloc failure"); - ub_timer_del(timer); - ub_event_free(timer); - ub_event_base_free(info.base); - return; - } - if(ub_event_add(stopev, NULL) != 0) { - log_err("dnstap io: cannot event_add"); - ub_event_free(stopev); - ub_timer_del(timer); - ub_event_free(timer); - ub_event_base_free(info.base); - return; - } - info.stop_frame = fstrm_create_control_frame_stop( - &info.stop_frame_len); - if(!info.stop_frame) { - log_err("dnstap io: malloc failure"); - ub_event_del(stopev); - ub_event_free(stopev); - ub_timer_del(timer); - ub_event_free(timer); - ub_event_base_free(info.base); - return; - } - dtio->stop_flush_event = stopev; - - /* wait briefly, or until finished */ - verbose(VERB_ALGO, "dnstap io: stop flush started"); - if(ub_event_base_dispatch(info.base) < 0) { - log_err("dnstap io: dispatch flush failed, errno is %s", - strerror(errno)); - } - verbose(VERB_ALGO, "dnstap io: stop flush ended"); - free(info.stop_frame); - dtio->stop_flush_event = NULL; - ub_event_del(stopev); - ub_event_free(stopev); - ub_timer_del(timer); - ub_event_free(timer); - ub_event_base_free(info.base); -} - -/** perform desetup and free stuff when the dnstap io thread exits */ -static void dtio_desetup(struct dt_io_thread* dtio) -{ - dtio_control_stop_flush(dtio); - dtio_del_output_event(dtio); - dtio_close_output(dtio); - ub_event_del(dtio->command_event); - ub_event_free(dtio->command_event); -#ifndef USE_WINSOCK - close(dtio->commandpipe[0]); -#else - _close(dtio->commandpipe[0]); -#endif - dtio->commandpipe[0] = -1; - dtio_reconnect_del(dtio); - ub_event_free(dtio->reconnect_timer); - dtio_cur_msg_free(dtio); -#ifndef THREADS_DISABLED - ub_event_base_free(dtio->event_base); -#endif -} - -/** setup a start control message */ -static int dtio_control_start_send(struct dt_io_thread* dtio) -{ - log_assert(dtio->cur_msg == NULL && dtio->cur_msg_len == 0); - dtio->cur_msg = fstrm_create_control_frame_start(DNSTAP_CONTENT_TYPE, - &dtio->cur_msg_len); - if(!dtio->cur_msg) { - return 0; - } - /* setup to send the control message */ - /* set that the buffer needs to be sent, but the length - * of that buffer is already written, that way the buffer can - * start with 0 length and then the length of the control frame - * in it */ - dtio->cur_msg_done = 0; - dtio->cur_msg_len_done = 4; - return 1; -} - -/** setup a ready control message */ -static int dtio_control_ready_send(struct dt_io_thread* dtio) -{ - log_assert(dtio->cur_msg == NULL && dtio->cur_msg_len == 0); - dtio->cur_msg = fstrm_create_control_frame_ready(DNSTAP_CONTENT_TYPE, - &dtio->cur_msg_len); - if(!dtio->cur_msg) { - return 0; - } - /* setup to send the control message */ - /* set that the buffer needs to be sent, but the length - * of that buffer is already written, that way the buffer can - * start with 0 length and then the length of the control frame - * in it */ - dtio->cur_msg_done = 0; - dtio->cur_msg_len_done = 4; - return 1; -} - -/** open the output file descriptor for af_local */ -static int dtio_open_output_local(struct dt_io_thread* dtio) -{ -#ifdef HAVE_SYS_UN_H - struct sockaddr_un s; - dtio->fd = socket(AF_LOCAL, SOCK_STREAM, 0); - if(dtio->fd == -1) { - log_err("dnstap io: failed to create socket: %s", - sock_strerror(errno)); - return 0; - } - memset(&s, 0, sizeof(s)); -#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - /* this member exists on BSDs, not Linux */ - s.sun_len = (unsigned)sizeof(s); -#endif - s.sun_family = AF_LOCAL; - /* length is 92-108, 104 on FreeBSD */ - (void)strlcpy(s.sun_path, dtio->socket_path, sizeof(s.sun_path)); - fd_set_nonblock(dtio->fd); - if(connect(dtio->fd, (struct sockaddr*)&s, (socklen_t)sizeof(s)) - == -1) { - char* to = dtio->socket_path; - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - verbosity < 4) { - dtio_close_fd(dtio); - return 0; /* no log retries on low verbosity */ - } - log_err("dnstap io: failed to connect to \"%s\": %s", - to, sock_strerror(errno)); - dtio_close_fd(dtio); - return 0; - } - return 1; -#else - log_err("cannot create af_local socket"); - return 0; -#endif /* HAVE_SYS_UN_H */ -} - -/** open the output file descriptor for af_inet and af_inet6 */ -static int dtio_open_output_tcp(struct dt_io_thread* dtio) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - memset(&addr, 0, sizeof(addr)); - addrlen = (socklen_t)sizeof(addr); - - if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen, UNBOUND_DNS_PORT)) { - log_err("could not parse IP '%s'", dtio->ip_str); - return 0; - } - dtio->fd = socket(addr.ss_family, SOCK_STREAM, 0); - if(dtio->fd == -1) { - log_err("can't create socket: %s", sock_strerror(errno)); - return 0; - } - fd_set_nonblock(dtio->fd); - if(connect(dtio->fd, (struct sockaddr*)&addr, addrlen) == -1) { - if(errno == EINPROGRESS) - return 1; /* wait until connect done*/ - if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN && - verbosity < 4) { - dtio_close_fd(dtio); - return 0; /* no log retries on low verbosity */ - } -#ifndef USE_WINSOCK - if(tcp_connect_errno_needs_log( - (struct sockaddr *)&addr, addrlen)) { - log_err("dnstap io: failed to connect to %s: %s", - dtio->ip_str, strerror(errno)); - } -#else - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEWOULDBLOCK) - return 1; /* wait until connect done*/ - if(tcp_connect_errno_needs_log( - (struct sockaddr *)&addr, addrlen)) { - log_err("dnstap io: failed to connect to %s: %s", - dtio->ip_str, wsa_strerror(WSAGetLastError())); - } -#endif - dtio_close_fd(dtio); - return 0; - } - return 1; -} - -/** setup the SSL structure for new connection */ -static int dtio_setup_ssl(struct dt_io_thread* dtio) -{ - dtio->ssl = outgoing_ssl_fd(dtio->ssl_ctx, dtio->fd); - if(!dtio->ssl) return 0; - dtio->ssl_handshake_done = 0; - dtio->ssl_brief_read = 0; - - if(!set_auth_name_on_ssl(dtio->ssl, dtio->tls_server_name, - dtio->tls_use_sni)) { - return 0; - } - return 1; -} - -/** open the output file descriptor */ -static void dtio_open_output(struct dt_io_thread* dtio) -{ - struct ub_event* ev; - if(dtio->upstream_is_unix) { - if(!dtio_open_output_local(dtio)) { - dtio_reconnect_enable(dtio); - return; - } - } else if(dtio->upstream_is_tcp || dtio->upstream_is_tls) { - if(!dtio_open_output_tcp(dtio)) { - dtio_reconnect_enable(dtio); - return; - } - if(dtio->upstream_is_tls) { - if(!dtio_setup_ssl(dtio)) { - dtio_close_fd(dtio); - dtio_reconnect_enable(dtio); - return; - } - } - } - dtio->check_nb_connect = 1; - - /* the EV_READ is to read ACCEPT control messages, and catch channel - * close. EV_WRITE is to write packets */ - ev = ub_event_new(dtio->event_base, dtio->fd, - UB_EV_READ | UB_EV_WRITE | UB_EV_PERSIST, &dtio_output_cb, - dtio); - if(!ev) { - log_err("dnstap io: out of memory"); - if(dtio->ssl) { -#ifdef HAVE_SSL - SSL_free(dtio->ssl); - dtio->ssl = NULL; -#endif - } - dtio_close_fd(dtio); - dtio_reconnect_enable(dtio); - return; - } - dtio->event = ev; - - /* setup protocol control message to start */ - if((!dtio->is_bidirectional && !dtio_control_start_send(dtio)) || - (dtio->is_bidirectional && !dtio_control_ready_send(dtio)) ) { - log_err("dnstap io: out of memory"); - ub_event_free(dtio->event); - dtio->event = NULL; - if(dtio->ssl) { -#ifdef HAVE_SSL - SSL_free(dtio->ssl); - dtio->ssl = NULL; -#endif - } - dtio_close_fd(dtio); - dtio_reconnect_enable(dtio); - return; - } -} - -/** perform the setup of the writer thread on the established event_base */ -static void dtio_setup_on_base(struct dt_io_thread* dtio) -{ - dtio_setup_cmd(dtio); - dtio_setup_reconnect(dtio); - dtio_open_output(dtio); - if(!dtio_add_output_event_write(dtio)) - return; -} - -#ifndef THREADS_DISABLED -/** the IO thread function for the DNSTAP IO */ -static void* dnstap_io(void* arg) -{ - struct dt_io_thread* dtio = (struct dt_io_thread*)arg; - time_t secs = 0; - struct timeval now; - log_thread_set(&dtio->threadnum); - - /* setup */ - verbose(VERB_ALGO, "start dnstap io thread"); - dtio_setup_base(dtio, &secs, &now); - dtio_setup_on_base(dtio); - - /* run */ - if(ub_event_base_dispatch(dtio->event_base) < 0) { - log_err("dnstap io: dispatch failed, errno is %s", - strerror(errno)); - } - - /* cleanup */ - verbose(VERB_ALGO, "stop dnstap io thread"); - dtio_desetup(dtio); - return NULL; -} -#endif /* THREADS_DISABLED */ - -int dt_io_thread_start(struct dt_io_thread* dtio, void* event_base_nothr, - int numworkers) -{ - /* set up the thread, can fail */ -#ifndef USE_WINSOCK - if(pipe(dtio->commandpipe) == -1) { - log_err("failed to create pipe: %s", strerror(errno)); - return 0; - } -#else - if(_pipe(dtio->commandpipe, 4096, _O_BINARY) == -1) { - log_err("failed to create _pipe: %s", - wsa_strerror(WSAGetLastError())); - return 0; - } -#endif - - /* start the thread */ - dtio->threadnum = numworkers+1; - dtio->started = 1; -#ifndef THREADS_DISABLED - ub_thread_create(&dtio->tid, dnstap_io, dtio); - (void)event_base_nothr; -#else - dtio->event_base = event_base_nothr; - dtio_setup_on_base(dtio); -#endif - return 1; -} - -void dt_io_thread_stop(struct dt_io_thread* dtio) -{ -#ifndef THREADS_DISABLED - uint8_t cmd = DTIO_COMMAND_STOP; -#endif - if(!dtio) return; - if(!dtio->started) return; - verbose(VERB_ALGO, "dnstap io: send stop cmd"); - -#ifndef THREADS_DISABLED - while(1) { - ssize_t r = write(dtio->commandpipe[1], &cmd, sizeof(cmd)); - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - continue; -#else - if(WSAGetLastError() == WSAEINPROGRESS) - continue; - if(WSAGetLastError() == WSAEWOULDBLOCK) - continue; -#endif - log_err("dnstap io stop: write: %s", - sock_strerror(errno)); - break; - } - break; - } - dtio->started = 0; -#endif /* THREADS_DISABLED */ - -#ifndef USE_WINSOCK - close(dtio->commandpipe[1]); -#else - _close(dtio->commandpipe[1]); -#endif - dtio->commandpipe[1] = -1; -#ifndef THREADS_DISABLED - ub_thread_join(dtio->tid); -#else - dtio->want_to_exit = 1; - dtio_desetup(dtio); -#endif -} diff --git a/crates/libunbound-sys/unbound/dnstap/dtstream.h b/crates/libunbound-sys/unbound/dnstap/dtstream.h deleted file mode 100644 index f87d6dc8..00000000 --- a/crates/libunbound-sys/unbound/dnstap/dtstream.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * dnstap/dtstream.h - Frame Streams thread for unbound DNSTAP - * - * Copyright (c) 2020, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * - * An implementation of the Frame Streams data transport protocol for - * the Unbound DNSTAP message logging facility. - */ - -#ifndef DTSTREAM_H -#define DTSTREAM_H - -#include "util/locks.h" -struct dt_msg_entry; -struct dt_io_list_item; -struct dt_io_thread; -struct config_file; -struct comm_base; - -/** - * A message buffer with dnstap messages queued up. It is per-worker. - * It has locks to synchronize. If the buffer is full, a new message - * cannot be added and is discarded. A thread reads the messages and sends - * them. - */ -struct dt_msg_queue { - /** lock of the buffer structure. Hold this lock to add or remove - * entries to the buffer. Release it so that other threads can also - * put messages to log, or a message can be taken out to send away - * by the writer thread. - */ - lock_basic_type lock; - /** the maximum size of the buffer, in bytes */ - size_t maxsize; - /** current size of the buffer, in bytes. data bytes of messages. - * If a new message make it more than maxsize, the buffer is full */ - size_t cursize; - /** number of messages in the queue */ - int msgcount; - /** list of messages. The messages are added to the back and taken - * out from the front. */ - struct dt_msg_entry* first, *last; - /** reference to the io thread to wakeup */ - struct dt_io_thread* dtio; - /** the wakeup timer for dtio, on worker event base */ - struct comm_timer* wakeup_timer; -}; - -/** - * An entry in the dt_msg_queue. contains one DNSTAP message. - * It is malloced. - */ -struct dt_msg_entry { - /** next in the list. */ - struct dt_msg_entry* next; - /** the buffer with the data to send, an encoded DNSTAP message */ - void* buf; - /** the length to send. */ - size_t len; -}; - -/** - * Containing buffer and counter for reading DNSTAP frames. - */ -struct dt_frame_read_buf { - /** Buffer containing frame, except length counter(s). */ - void* buf; - /** Number of bytes written to buffer. */ - size_t buf_count; - /** Capacity of the buffer. */ - size_t buf_cap; - - /** Frame length field. Will contain the 2nd length field for control - * frames. */ - uint32_t frame_len; - /** Number of bytes that have been written to the frame_length field. */ - size_t frame_len_done; - - /** Set to 1 if this is a control frame, 0 otherwise (ie data frame). */ - int control_frame; -}; - -/** - * IO thread that reads from the queues and writes them. - */ -struct dt_io_thread { - /** the thread number for the dtio thread, - * must be first to cast thread arg to int* in checklock code. */ - int threadnum; - /** event base, for event handling */ - void* event_base; - /** list of queues that is registered to get written */ - struct dt_io_list_item* io_list; - /** iterator point in the io_list, to pick from them in a - * round-robin fashion, instead of only from the first when busy. - * if NULL it means start at the start of the list. */ - struct dt_io_list_item* io_list_iter; - /** thread id, of the io thread */ - ub_thread_type tid; - /** if the io processing has started */ - int started; - /** ssl context for the io thread, for tls connections. type SSL_CTX* */ - void* ssl_ctx; - /** if SNI will be used for TLS connections. */ - int tls_use_sni; - - /** file descriptor that the thread writes to */ - int fd; - /** event structure that the thread uses */ - void* event; - /** the event is added */ - int event_added; - /** event added is a write event */ - int event_added_is_write; - /** check for nonblocking connect errors on fd */ - int check_nb_connect; - /** ssl for current connection, type SSL* */ - void* ssl; - /** true if the handshake for SSL is done, 0 if not */ - int ssl_handshake_done; - /** true if briefly the SSL wants a read event, 0 if not. - * This happens during negotiation, we then do not want to write, - * but wait for a read event. */ - int ssl_brief_read; - /** true if SSL_read is waiting for a write event. Set back to 0 after - * single write event is handled. */ - int ssl_brief_write; - - /** the buffer that currently getting written, or NULL if no - * (partial) message written now */ - void* cur_msg; - /** length of the current message */ - size_t cur_msg_len; - /** number of bytes written for the current message */ - size_t cur_msg_done; - /** number of bytes of the length that have been written, - * for the current message length that precedes the frame */ - size_t cur_msg_len_done; - - /** lock on wakeup_timer_enabled */ - lock_basic_type wakeup_timer_lock; - /** if wakeup timer is enabled in some thread */ - int wakeup_timer_enabled; - /** command pipe that stops the pipe if closed. Used to quit - * the program. [0] is read, [1] is written to. */ - int commandpipe[2]; - /** the event to listen to the commandpipe */ - void* command_event; - /** the io thread wants to exit */ - int want_to_exit; - - /** in stop flush, this is nonNULL and references the stop_ev */ - void* stop_flush_event; - - /** the timer event for connection retries */ - void* reconnect_timer; - /** if the reconnect timer is added to the event base */ - int reconnect_is_added; - /** the current reconnection timeout, it is increased with - * exponential backoff, in msec */ - int reconnect_timeout; - - /** If the log server is connected to over unix domain sockets, - * eg. a file is named that is created to log onto. */ - int upstream_is_unix; - /** if the log server is connected to over TCP. The ip address and - * port are used */ - int upstream_is_tcp; - /** if the log server is connected to over TLS. ip address, port, - * and client certificates can be used for authentication. */ - int upstream_is_tls; - - /** Perform bidirectional Frame Streams handshake before sending - * messages. */ - int is_bidirectional; - /** Set if the READY control frame has been sent. */ - int ready_frame_sent; - /** Set if valid ACCEPT frame is received. */ - int accept_frame_received; - /** (partially) read frame */ - struct dt_frame_read_buf read_frame; - - /** the file path for unix socket (or NULL) */ - char* socket_path; - /** the ip address and port number (or NULL) */ - char* ip_str; - /** is the TLS upstream authenticated by name, if nonNULL, - * we use the same cert bundle as used by other TLS streams. */ - char* tls_server_name; - /** are client certificates in use */ - int use_client_certs; - /** client cert files: the .key file */ - char* client_key_file; - /** client cert files: the .pem file */ - char* client_cert_file; -}; - -/** - * IO thread list of queues list item - * lists a worker queue that should be looked at and sent to the log server. - */ -struct dt_io_list_item { - /** next in the list of buffers to inspect */ - struct dt_io_list_item* next; - /** buffer of this worker */ - struct dt_msg_queue* queue; -}; - -/** - * Create new (empty) worker message queue. Limit set to default on max. - * @param base: event base for wakeup timer. - * @return NULL on malloc failure or a new queue (not locked). - */ -struct dt_msg_queue* dt_msg_queue_create(struct comm_base* base); - -/** - * Delete a worker message queue. It has to be unlinked from access, - * so it can be deleted without lock worries. The queue is emptied (deleted). - * @param mq: message queue. - */ -void dt_msg_queue_delete(struct dt_msg_queue* mq); - -/** - * Submit a message to the queue. The queue is locked by the routine, - * the message is inserted, and then the queue is unlocked so the - * message can be picked up by the writer thread. - * @param mq: message queue. - * @param buf: buffer with message (dnstap contents). - * The buffer must have been malloced by caller. It is linked in - * the queue, and is free()d after use. If the routine fails - * the buffer is freed as well (and nothing happens, the item - * could not be logged). - * @param len: length of buffer. - */ -void dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len); - -/** timer callback to wakeup dtio thread to process messages */ -void mq_wakeup_cb(void* arg); - -/** - * Create IO thread. - * @return new io thread object. not yet started. or NULL malloc failure. - */ -struct dt_io_thread* dt_io_thread_create(void); - -/** - * Delete the IO thread structure. - * @param dtio: the io thread that is deleted. It must not be running. - */ -void dt_io_thread_delete(struct dt_io_thread* dtio); - -/** - * Apply config to the dtio thread - * @param dtio: io thread, not yet started. - * @param cfg: config file struct. - * @return false on malloc failure. - */ -int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, - struct config_file *cfg); - -/** - * Register a msg queue to the io thread. It will be polled to see if - * there are messages and those then get removed and sent, when the thread - * is running. - * @param dtio: the io thread. - * @param mq: message queue to register. - * @return false on failure (malloc failure). - */ -int dt_io_thread_register_queue(struct dt_io_thread* dtio, - struct dt_msg_queue* mq); - -/** - * Unregister queue from io thread. - * @param dtio: the io thread. - * @param mq: message queue. - */ -void dt_io_thread_unregister_queue(struct dt_io_thread* dtio, - struct dt_msg_queue* mq); - -/** - * Start the io thread - * @param dtio: the io thread. - * @param event_base_nothr: the event base to attach the events to, in case - * we are running without threads. With threads, this is ignored - * and a thread is started to process the dnstap log messages. - * @param numworkers: number of worker threads. The dnstap io thread is - * that number +1 as the threadnumber (in logs). - * @return false on failure. - */ -int dt_io_thread_start(struct dt_io_thread* dtio, void* event_base_nothr, - int numworkers); - -/** - * Stop the io thread - * @param dtio: the io thread. - */ -void dt_io_thread_stop(struct dt_io_thread* dtio); - -/** callback for the dnstap reconnect, to start reconnecting to output */ -void dtio_reconnect_timeout_cb(int fd, short bits, void* arg); - -/** callback for the dnstap events, to write to the output */ -void dtio_output_cb(int fd, short bits, void* arg); - -/** callback for the dnstap commandpipe, to stop the dnstap IO */ -void dtio_cmd_cb(int fd, short bits, void* arg); - -/** callback for the timer when the thread stops and wants to finish up */ -void dtio_stop_timer_cb(int fd, short bits, void* arg); - -/** callback for the output when the thread stops and wants to finish up */ -void dtio_stop_ev_cb(int fd, short bits, void* arg); - -/** callback for unbound-dnstap-socket */ -void dtio_tap_callback(int fd, short bits, void* arg); - -/** callback for unbound-dnstap-socket */ -void dtio_mainfdcallback(int fd, short bits, void* arg); - -#endif /* DTSTREAM_H */ diff --git a/crates/libunbound-sys/unbound/dnstap/unbound-dnstap-socket.c b/crates/libunbound-sys/unbound/dnstap/unbound-dnstap-socket.c deleted file mode 100644 index d172a674..00000000 --- a/crates/libunbound-sys/unbound/dnstap/unbound-dnstap-socket.c +++ /dev/null @@ -1,1572 +0,0 @@ -/* - * dnstap/unbound-dnstap-socket.c - debug program that listens for DNSTAP logs. - * - * Copyright (c) 2020, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This program listens on a DNSTAP socket for logged messages. - */ -#include "config.h" -#ifdef HAVE_GETOPT_H -#include -#endif -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_UN_H -#include -#endif -#include -#include -#include -#include "dnstap/dtstream.h" -#include "dnstap/dnstap_fstrm.h" -#include "util/log.h" -#include "util/ub_event.h" -#include "util/net_help.h" -#include "services/listen_dnsport.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "sldns/pkthdr.h" -#ifdef USE_DNSTAP -#include -#include "dnstap/dnstap.pb-c.h" -#endif /* USE_DNSTAP */ -#include "util/config_file.h" - -/** listen backlog on TCP connections for dnstap logs */ -#define LISTEN_BACKLOG 16 - -/** usage information for streamtcp */ -static void usage(char* argv[]) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Listen to dnstap messages\n"); - printf("stdout has dnstap log, stderr has verbose server log\n"); - printf("-u listen to unix socket with this file name\n"); - printf("-s listen for TCP on the IP and port\n"); - printf("-t listen for TLS on IP and port\n"); - printf("-x server key file for TLS service\n"); - printf("-y server cert file for TLS service\n"); - printf("-z cert file to verify client connections\n"); - printf("-l long format for DNS printout\n"); - printf("-v more verbose log output\n"); - printf("-h this help text\n"); - exit(1); -} - -/** long format option, for multiline printout per message */ -static int longformat = 0; - -struct tap_socket_list; -struct tap_socket; -/** main tap callback data */ -struct main_tap_data { - /** the event base (to loopexit) */ - struct ub_event_base* base; - /** the list of accept sockets */ - struct tap_socket_list* acceptlist; -}; - -/** tap callback variables */ -struct tap_data { - /** the fd */ - int fd; - /** the ub event */ - struct ub_event* ev; - /** the SSL for TLS streams */ - SSL* ssl; - /** is the ssl handshake done */ - int ssl_handshake_done; - /** we are briefly waiting to write (in the struct event) */ - int ssl_brief_write; - /** string that identifies the socket (or NULL), like IP address */ - char* id; - /** have we read the length, and how many bytes of it */ - int len_done; - /** have we read the data, and how many bytes of it */ - size_t data_done; - /** are we reading a control frame */ - int control_frame; - /** are we bi-directional (if false, uni-directional) */ - int is_bidirectional; - /** data of the frame */ - uint8_t* frame; - /** length of this frame */ - size_t len; -}; - -/** list of sockets */ -struct tap_socket_list { - /** next in list */ - struct tap_socket_list* next; - /** the socket */ - struct tap_socket* s; -}; - -/** tap socket */ -struct tap_socket { - /** fd of socket */ - int fd; - /** the event for it */ - struct ub_event *ev; - /** has the event been added */ - int ev_added; - /** the callback, for the event, ev_cb(fd, bits, arg) */ - void (*ev_cb)(int, short, void*); - /** data element, (arg for the tap_socket struct) */ - void* data; - /** socketpath, if this is an AF_LOCAL socket */ - char* socketpath; - /** IP, if this is a TCP socket */ - char* ip; - /** for a TLS socket, the tls context */ - SSL_CTX* sslctx; -}; - -/** del the tap event */ -static void tap_socket_delev(struct tap_socket* s) -{ - if(!s) return; - if(!s->ev) return; - if(!s->ev_added) return; - ub_event_del(s->ev); - s->ev_added = 0; -} - -/** close the tap socket */ -static void tap_socket_close(struct tap_socket* s) -{ - if(!s) return; - if(s->fd == -1) return; - close(s->fd); - s->fd = -1; -} - -/** delete tap socket */ -static void tap_socket_delete(struct tap_socket* s) -{ - if(!s) return; -#ifdef HAVE_SSL - SSL_CTX_free(s->sslctx); -#endif - ub_event_free(s->ev); - free(s->socketpath); - free(s->ip); - free(s); -} - -/** create new socket (unconnected, not base-added), or NULL malloc fail */ -static struct tap_socket* tap_socket_new_local(char* socketpath, - void (*ev_cb)(int, short, void*), void* data) -{ - struct tap_socket* s = calloc(1, sizeof(*s)); - if(!s) { - log_err("malloc failure"); - return NULL; - } - s->socketpath = strdup(socketpath); - if(!s->socketpath) { - free(s); - log_err("malloc failure"); - return NULL; - } - s->fd = -1; - s->ev_cb = ev_cb; - s->data = data; - return s; -} - -/** create new socket (unconnected, not base-added), or NULL malloc fail */ -static struct tap_socket* tap_socket_new_tcpaccept(char* ip, - void (*ev_cb)(int, short, void*), void* data) -{ - struct tap_socket* s = calloc(1, sizeof(*s)); - if(!s) { - log_err("malloc failure"); - return NULL; - } - s->ip = strdup(ip); - if(!s->ip) { - free(s); - log_err("malloc failure"); - return NULL; - } - s->fd = -1; - s->ev_cb = ev_cb; - s->data = data; - return s; -} - -/** create new socket (unconnected, not base-added), or NULL malloc fail */ -static struct tap_socket* tap_socket_new_tlsaccept(char* ip, - void (*ev_cb)(int, short, void*), void* data, char* server_key, - char* server_cert, char* verifypem) -{ - struct tap_socket* s = calloc(1, sizeof(*s)); - if(!s) { - log_err("malloc failure"); - return NULL; - } - s->ip = strdup(ip); - if(!s->ip) { - free(s); - log_err("malloc failure"); - return NULL; - } - s->fd = -1; - s->ev_cb = ev_cb; - s->data = data; - s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem); - if(!s->sslctx) { - log_err("could not create ssl context"); - free(s->ip); - free(s); - return NULL; - } - return s; -} - -/** setup tcp accept socket on IP string */ -static int make_tcp_accept(char* ip) -{ -#ifdef SO_REUSEADDR - int on = 1; -#endif - struct sockaddr_storage addr; - socklen_t len; - int s; - - memset(&addr, 0, sizeof(addr)); - len = (socklen_t)sizeof(addr); - if(!extstrtoaddr(ip, &addr, &len, UNBOUND_DNS_PORT)) { - log_err("could not parse IP '%s'", ip); - return -1; - } - - if((s = socket(addr.ss_family, SOCK_STREAM, 0)) == -1) { - log_err("can't create socket: %s", sock_strerror(errno)); - return -1; - } -#ifdef SO_REUSEADDR - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", - sock_strerror(errno)); - sock_close(s); - return -1; - } -#endif /* SO_REUSEADDR */ - if(bind(s, (struct sockaddr*)&addr, len) != 0) { - log_err_addr("can't bind socket", sock_strerror(errno), - &addr, len); - sock_close(s); - return -1; - } - if(!fd_set_nonblock(s)) { - sock_close(s); - return -1; - } - if(listen(s, LISTEN_BACKLOG) == -1) { - log_err("can't listen: %s", sock_strerror(errno)); - sock_close(s); - return -1; - } - return s; -} - -/** setup socket on event base */ -static int tap_socket_setup(struct tap_socket* s, struct ub_event_base* base) -{ - if(s->socketpath) { - /* AF_LOCAL accept socket */ - s->fd = create_local_accept_sock(s->socketpath, NULL, 0); - if(s->fd == -1) { - log_err("could not create local socket"); - return 0; - } - } else if(s->ip || s->sslctx) { - /* TCP accept socket */ - s->fd = make_tcp_accept(s->ip); - if(s->fd == -1) { - log_err("could not create tcp socket"); - return 0; - } - } - s->ev = ub_event_new(base, s->fd, UB_EV_READ | UB_EV_PERSIST, - s->ev_cb, s); - if(!s->ev) { - log_err("could not ub_event_new"); - return 0; - } - if(ub_event_add(s->ev, NULL) != 0) { - log_err("could not ub_event_add"); - return 0; - } - s->ev_added = 1; - return 1; -} - -/** add tap socket to list */ -static int tap_socket_list_insert(struct tap_socket_list** liststart, - struct tap_socket* s) -{ - struct tap_socket_list* entry = (struct tap_socket_list*) - malloc(sizeof(*entry)); - if(!entry) - return 0; - entry->next = *liststart; - entry->s = s; - *liststart = entry; - return 1; -} - -/** delete the list */ -static void tap_socket_list_delete(struct tap_socket_list* list) -{ - struct tap_socket_list* e = list, *next; - while(e) { - next = e->next; - tap_socket_delev(e->s); - tap_socket_close(e->s); - tap_socket_delete(e->s); - free(e); - e = next; - } -} - -/** setup accept events */ -static int tap_socket_list_addevs(struct tap_socket_list* list, - struct ub_event_base* base) -{ - struct tap_socket_list* entry; - for(entry = list; entry; entry = entry->next) { - if(!tap_socket_setup(entry->s, base)) { - log_err("could not setup socket"); - return 0; - } - } - return 1; -} - -#ifdef USE_DNSTAP -/** log control frame contents */ -static void log_control_frame(uint8_t* pkt, size_t len) -{ - char* desc; - if(verbosity == 0) return; - desc = fstrm_describe_control(pkt, len); - if(!desc) { - log_err("out of memory"); - return; - } - log_info("control frame %s", desc); - free(desc); -} - -/** convert mtype to string */ -static const char* mtype_to_str(enum _Dnstap__Message__Type mtype) -{ - switch(mtype) { - case DNSTAP__MESSAGE__TYPE__AUTH_QUERY: - return "AUTH_QUERY"; - case DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE: - return "AUTH_RESPONSE"; - case DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY: - return "RESOLVER_QUERY"; - case DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE: - return "RESOLVER_RESPONSE"; - case DNSTAP__MESSAGE__TYPE__CLIENT_QUERY: - return "CLIENT_QUERY"; - case DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE: - return "CLIENT_RESPONSE"; - case DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY: - return "FORWARDER_QUERY"; - case DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE: - return "FORWARDER_RESPONSE"; - case DNSTAP__MESSAGE__TYPE__STUB_QUERY: - return "STUB_QUERY"; - case DNSTAP__MESSAGE__TYPE__STUB_RESPONSE: - return "STUB_RESPONSE"; - default: break; - } - return "unknown_message_type"; -} - -/** convert type address to a string ip4 or ip6, malloced or NULL on fail */ -static char* str_of_addr(ProtobufCBinaryData address) -{ - char buf[64]; - socklen_t len = sizeof(buf); - if(address.len == 4) { - if(inet_ntop(AF_INET, address.data, buf, len)!=0) - return strdup(buf); - } else if(address.len == 16) { - if(inet_ntop(AF_INET6, address.data, buf, len)!=0) - return strdup(buf); - } - return NULL; -} - -/** convert message buffer (of dns bytes) to the first qname, type, class, - * malloced or NULL on fail */ -static char* q_of_msg(ProtobufCBinaryData message) -{ - char buf[300]; - /* header, name, type, class minimum to get the query tuple */ - if(message.len < 12 + 1 + 4 + 4) return NULL; - if(LDNS_QDCOUNT(message.data) < 1) return NULL; - if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12, - buf, sizeof(buf)) != 0) { - /* remove trailing newline, tabs to spaces */ - /* remove the newline: */ - if(buf[0] != 0) buf[strlen(buf)-1]=0; - /* remove first tab (before type) */ - if(strrchr(buf, '\t')) *strrchr(buf, '\t')=' '; - /* remove second tab (before class) */ - if(strrchr(buf, '\t')) *strrchr(buf, '\t')=' '; - return strdup(buf); - } - return NULL; -} - -/** convert possible string or hex data to string. malloced or NULL */ -static char* possible_str(ProtobufCBinaryData str) -{ - int is_str = 1; - size_t i; - for(i=0; i>4]; - res[i*2+1] = hex[str.data[i]&0x0f]; - } - res[str.len*2] = 0; - return res; - } - } - return NULL; -} - -/** convert timeval to string, malloced or NULL */ -static char* tv_to_str(protobuf_c_boolean has_time_sec, uint64_t time_sec, - protobuf_c_boolean has_time_nsec, uint32_t time_nsec) -{ - char buf[64], buf2[256]; - struct timeval tv; - time_t time_t_sec; - memset(&tv, 0, sizeof(tv)); - if(has_time_sec) tv.tv_sec = time_sec; - if(has_time_nsec) tv.tv_usec = time_nsec/1000; - - buf[0]=0; - time_t_sec = tv.tv_sec; - (void)ctime_r(&time_t_sec, buf); - snprintf(buf2, sizeof(buf2), "%u.%9.9u %s", - (unsigned)time_sec, (unsigned)time_nsec, buf); - return strdup(buf2); -} - -/** log data frame contents */ -static void log_data_frame(uint8_t* pkt, size_t len) -{ - Dnstap__Dnstap* d = dnstap__dnstap__unpack(NULL, len, pkt); - const char* mtype = NULL; - char* maddr=NULL, *qinf=NULL; - if(!d) { - log_err("could not unpack"); - return; - } - if(d->base.descriptor != &dnstap__dnstap__descriptor) { - log_err("wrong base descriptor"); - dnstap__dnstap__free_unpacked(d, NULL); - return; - } - if(d->type != DNSTAP__DNSTAP__TYPE__MESSAGE) { - log_err("dnstap type not type_message"); - dnstap__dnstap__free_unpacked(d, NULL); - return; - } - if(d->message) { - mtype = mtype_to_str(d->message->type); - if(d->message->has_query_address) - maddr = str_of_addr(d->message->query_address); - else if(d->message->has_response_address) - maddr = str_of_addr(d->message->response_address); - if(d->message->has_query_message) - qinf = q_of_msg(d->message->query_message); - else if(d->message->has_response_message) - qinf = q_of_msg(d->message->response_message); - - } else { - mtype = "nomessage"; - } - - printf("%s%s%s%s%s\n", mtype, (maddr?" ":""), (maddr?maddr:""), - (qinf?" ":""), (qinf?qinf:"")); - free(maddr); - free(qinf); - - if(longformat) { - char* id=NULL, *vs=NULL; - if(d->has_identity) { - id=possible_str(d->identity); - } - if(d->has_version) { - vs=possible_str(d->version); - } - if(id || vs) - printf("identity: %s%s%s\n", (id?id:""), - (id&&vs?" ":""), (vs?vs:"")); - free(id); - free(vs); - - if(d->message && d->message->has_query_message && - d->message->query_message.data) { - char* qmsg = sldns_wire2str_pkt( - d->message->query_message.data, - d->message->query_message.len); - if(qmsg) { - printf("query_message:\n%s", qmsg); - free(qmsg); - } - } - if(d->message && d->message->has_query_time_sec) { - char* qtv = tv_to_str(d->message->has_query_time_sec, - d->message->query_time_sec, - d->message->has_query_time_nsec, - d->message->query_time_nsec); - if(qtv) { - printf("query_time: %s\n", qtv); - free(qtv); - } - } - if(d->message && d->message->has_response_message && - d->message->response_message.data) { - char* rmsg = sldns_wire2str_pkt( - d->message->response_message.data, - d->message->response_message.len); - if(rmsg) { - printf("response_message:\n%s", rmsg); - free(rmsg); - } - } - if(d->message && d->message->has_response_time_sec) { - char* rtv = tv_to_str(d->message->has_response_time_sec, - d->message->response_time_sec, - d->message->has_response_time_nsec, - d->message->response_time_nsec); - if(rtv) { - printf("response_time: %s\n", rtv); - free(rtv); - } - } - } - fflush(stdout); - dnstap__dnstap__free_unpacked(d, NULL); -} -#endif /* USE_DNSTAP */ - -/** receive bytes from fd, prints errors if bad, - * returns 0: closed/error, -1: continue, >0 number of bytes */ -static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf, - size_t len) -{ - ssize_t ret = recv(fd, buf, len, MSG_DONTWAIT); - if(ret == 0) { - /* closed */ - if(verbosity) log_info("dnstap client stream closed from %s", - (data->id?data->id:"")); - return 0; - } else if(ret == -1) { - /* error */ -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return -1; -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAEINPROGRESS) - return -1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(data->ev, UB_EV_READ); - return -1; - } -#endif - log_err("could not recv: %s", sock_strerror(errno)); - if(verbosity) log_info("dnstap client stream closed from %s", - (data->id?data->id:"")); - return 0; - } - return ret; -} - -/* define routine for have_ssl only to avoid unused function warning */ -#ifdef HAVE_SSL -/** set to wait briefly for a write event, for one event call */ -static void tap_enable_brief_write(struct tap_data* data) -{ - ub_event_del(data->ev); - ub_event_del_bits(data->ev, UB_EV_READ); - ub_event_add_bits(data->ev, UB_EV_WRITE); - if(ub_event_add(data->ev, NULL) != 0) - log_err("could not ub_event_add in tap_enable_brief_write"); - data->ssl_brief_write = 1; -} -#endif /* HAVE_SSL */ - -/* define routine for have_ssl only to avoid unused function warning */ -#ifdef HAVE_SSL -/** stop the brief wait for a write event. back to reading. */ -static void tap_disable_brief_write(struct tap_data* data) -{ - ub_event_del(data->ev); - ub_event_del_bits(data->ev, UB_EV_WRITE); - ub_event_add_bits(data->ev, UB_EV_READ); - if(ub_event_add(data->ev, NULL) != 0) - log_err("could not ub_event_add in tap_disable_brief_write"); - data->ssl_brief_write = 0; -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** receive bytes over ssl stream, prints errors if bad, - * returns 0: closed/error, -1: continue, >0 number of bytes */ -static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len) -{ - int r; - ERR_clear_error(); - r = SSL_read(data->ssl, buf, len); - if(r <= 0) { - int want = SSL_get_error(data->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - /* closed */ - if(verbosity) log_info("dnstap client stream closed from %s", - (data->id?data->id:"")); - return 0; - } else if(want == SSL_ERROR_WANT_READ) { - /* continue later */ - return -1; - } else if(want == SSL_ERROR_WANT_WRITE) { - /* set to briefly write */ - tap_enable_brief_write(data); - return -1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - if(verbosity) log_info("dnstap client stream closed from %s", - (data->id?data->id:"")); - return 0; - } - log_crypto_err("could not SSL_read"); - if(verbosity) log_info("dnstap client stream closed from %s", - (data->id?data->id:"")); - return 0; - } - return r; -} -#endif /* HAVE_SSL */ - -/** receive bytes on the tap connection, prints errors if bad, - * returns 0: closed/error, -1: continue, >0 number of bytes */ -static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len) -{ -#ifdef HAVE_SSL - if(data->ssl) - return ssl_read_bytes(data, buf, len); -#endif - return receive_bytes(data, data->fd, buf, len); -} - -/** delete the tap structure */ -static void tap_data_free(struct tap_data* data) -{ - ub_event_del(data->ev); - ub_event_free(data->ev); -#ifdef HAVE_SSL - SSL_free(data->ssl); -#endif - close(data->fd); - free(data->id); - free(data->frame); - free(data); -} - -/** reply with ACCEPT control frame to bidirectional client, - * returns 0 on error */ -static int reply_with_accept(struct tap_data* data) -{ -#ifdef USE_DNSTAP - /* len includes the escape and framelength */ - int r; - size_t len = 0; - void* acceptframe = fstrm_create_control_frame_accept( - DNSTAP_CONTENT_TYPE, &len); - if(!acceptframe) { - log_err("out of memory"); - return 0; - } - - fd_set_block(data->fd); - if(data->ssl) { - if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) { - if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN) - log_err("SSL_write, peer closed connection"); - else - log_err("could not SSL_write"); - fd_set_nonblock(data->fd); - free(acceptframe); - return 0; - } - } else { - if(send(data->fd, acceptframe, len, 0) == -1) { - log_err("send failed: %s", sock_strerror(errno)); - fd_set_nonblock(data->fd); - free(acceptframe); - return 0; - } - } - if(verbosity) log_info("sent control frame(accept) content-type:(%s)", - DNSTAP_CONTENT_TYPE); - - fd_set_nonblock(data->fd); - free(acceptframe); - return 1; -#else - log_err("no dnstap compiled, no reply"); - (void)data; - return 0; -#endif -} - -/** reply with FINISH control frame to bidirectional client, - * returns 0 on error */ -static int reply_with_finish(struct tap_data* data) -{ -#ifdef USE_DNSTAP - size_t len = 0; - void* finishframe = fstrm_create_control_frame_finish(&len); - if(!finishframe) { - log_err("out of memory"); - return 0; - } - - fd_set_block(data->fd); - if(data->ssl) { - int r; - if((r=SSL_write(data->ssl, finishframe, len)) <= 0) { - if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN) - log_err("SSL_write, peer closed connection"); - else - log_err("could not SSL_write"); - fd_set_nonblock(data->fd); - free(finishframe); - return 0; - } - } else { - if(send(data->fd, finishframe, len, 0) == -1) { - log_err("send failed: %s", sock_strerror(errno)); - fd_set_nonblock(data->fd); - free(finishframe); - return 0; - } - } - if(verbosity) log_info("sent control frame(finish)"); - - fd_set_nonblock(data->fd); - free(finishframe); - return 1; -#else - log_err("no dnstap compiled, no reply"); - (void)data; - return 0; -#endif -} - -#ifdef HAVE_SSL -/** check SSL peer certificate, return 0 on fail */ -static int tap_check_peer(struct tap_data* data) -{ - if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) { - /* verification */ - if(SSL_get_verify_result(data->ssl) == X509_V_OK) { - X509* x = SSL_get_peer_certificate(data->ssl); - if(!x) { - if(verbosity) log_info("SSL connection %s" - " failed no certificate", data->id); - return 0; - } - if(verbosity) - log_cert(VERB_ALGO, "peer certificate", x); -#ifdef HAVE_SSL_GET0_PEERNAME - if(SSL_get0_peername(data->ssl)) { - if(verbosity) log_info("SSL connection %s " - "to %s authenticated", data->id, - SSL_get0_peername(data->ssl)); - } else { -#endif - if(verbosity) log_info("SSL connection %s " - "authenticated", data->id); -#ifdef HAVE_SSL_GET0_PEERNAME - } -#endif - X509_free(x); - } else { - X509* x = SSL_get_peer_certificate(data->ssl); - if(x) { - if(verbosity) - log_cert(VERB_ALGO, "peer certificate", x); - X509_free(x); - } - if(verbosity) log_info("SSL connection %s failed: " - "failed to authenticate", data->id); - return 0; - } - } else { - /* unauthenticated, the verify peer flag was not set - * in ssl when the ssl object was created from ssl_ctx */ - if(verbosity) log_info("SSL connection %s", data->id); - } - return 1; -} -#endif /* HAVE_SSL */ - -#ifdef HAVE_SSL -/** perform SSL handshake, return 0 to wait for events, 1 if done */ -static int tap_handshake(struct tap_data* data) -{ - int r; - if(data->ssl_brief_write) { - /* write condition has been satisfied, back to reading */ - tap_disable_brief_write(data); - } - if(data->ssl_handshake_done) - return 1; - - ERR_clear_error(); - r = SSL_do_handshake(data->ssl); - if(r != 1) { - int want = SSL_get_error(data->ssl, r); - if(want == SSL_ERROR_WANT_READ) { - return 0; - } else if(want == SSL_ERROR_WANT_WRITE) { - tap_enable_brief_write(data); - return 0; - } else if(r == 0) { - /* closed */ - tap_data_free(data); - return 0; - } else if(want == SSL_ERROR_SYSCALL) { - /* SYSCALL and errno==0 means closed uncleanly */ - int silent = 0; -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - silent = 1; /* silence 'broken pipe' */ -#endif -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - silent = 1; /* silence reset by peer */ -#endif - if(errno == 0) - silent = 1; - if(!silent) - log_err("SSL_handshake syscall: %s", - strerror(errno)); - tap_data_free(data); - return 0; - } else { - unsigned long err = ERR_get_error(); - if(!squelch_err_ssl_handshake(err)) { - log_crypto_err_code("ssl handshake failed", - err); - verbose(VERB_OPS, "ssl handshake failed " - "from %s", data->id); - } - tap_data_free(data); - return 0; - } - } - /* check peer verification */ - data->ssl_handshake_done = 1; - if(!tap_check_peer(data)) { - /* closed */ - tap_data_free(data); - return 0; - } - return 1; -} -#endif /* HAVE_SSL */ - -/** callback for dnstap listener */ -void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg) -{ - struct tap_data* data = (struct tap_data*)arg; - if(verbosity>=3) log_info("tap callback"); -#ifdef HAVE_SSL - if(data->ssl && (!data->ssl_handshake_done || - data->ssl_brief_write)) { - if(!tap_handshake(data)) - return; - } -#endif - while(data->len_done < 4) { - uint32_t l = (uint32_t)data->len; - ssize_t ret = tap_receive(data, - ((uint8_t*)&l)+data->len_done, 4-data->len_done); - if(verbosity>=4) log_info("s recv %d", (int)ret); - if(ret == 0) { - /* closed or error */ - tap_data_free(data); - return; - } else if(ret == -1) { - /* continue later */ - return; - } - data->len_done += ret; - data->len = (size_t)l; - if(data->len_done < 4) - return; /* continue later */ - data->len = (size_t)(ntohl(l)); - if(verbosity>=3) log_info("length is %d", (int)data->len); - if(data->len == 0) { - /* it is a control frame */ - data->control_frame = 1; - /* read controlframelen */ - data->len_done = 0; - } else { - /* allocate frame size */ - data->frame = calloc(1, data->len); - if(!data->frame) { - log_err("out of memory"); - tap_data_free(data); - return; - } - } - } - - /* we want to read the full length now */ - if(data->data_done < data->len) { - ssize_t r = tap_receive(data, data->frame + data->data_done, - data->len - data->data_done); - if(verbosity>=4) log_info("f recv %d", (int)r); - if(r == 0) { - /* closed or error */ - tap_data_free(data); - return; - } else if(r == -1) { - /* continue later */ - return; - } - data->data_done += r; - if(data->data_done < data->len) - return; /* continue later */ - } - - /* we are done with a frame */ - if(verbosity>=3) log_info("received %sframe len %d", - (data->control_frame?"control ":""), (int)data->len); -#ifdef USE_DNSTAP - if(data->control_frame) - log_control_frame(data->frame, data->len); - else log_data_frame(data->frame, data->len); -#endif - - if(data->len >= 4 && sldns_read_uint32(data->frame) == - FSTRM_CONTROL_FRAME_READY) { - data->is_bidirectional = 1; - if(verbosity) log_info("bidirectional stream"); - if(!reply_with_accept(data)) { - tap_data_free(data); - return; - } - } else if(data->len >= 4 && sldns_read_uint32(data->frame) == - FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) { - if(!reply_with_finish(data)) { - tap_data_free(data); - return; - } - } - - /* prepare for next frame */ - free(data->frame); - data->frame = NULL; - data->control_frame = 0; - data->len = 0; - data->len_done = 0; - data->data_done = 0; - -} - -/** callback for main listening file descriptor */ -void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg) -{ - struct tap_socket* tap_sock = (struct tap_socket*)arg; - struct main_tap_data* maindata = (struct main_tap_data*) - tap_sock->data; - struct tap_data* data; - char* id = NULL; - struct sockaddr_storage addr; - socklen_t addrlen = (socklen_t)sizeof(addr); - int s = accept(fd, (struct sockaddr*)&addr, &addrlen); - if(s == -1) { -#ifndef USE_WINSOCK - /* EINTR is signal interrupt. others are closed connection. */ - if( errno == EINTR || errno == EAGAIN -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif -#ifdef ECONNABORTED - || errno == ECONNABORTED -#endif -#ifdef EPROTO - || errno == EPROTO -#endif /* EPROTO */ - ) - return; -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAECONNRESET) - return; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(maindata->ev, UB_EV_READ); - return; - } -#endif - log_err_addr("accept failed", sock_strerror(errno), &addr, - addrlen); - return; - } - fd_set_nonblock(s); - if(verbosity) { - if(addr.ss_family == AF_LOCAL) { -#ifdef HAVE_SYS_UN_H - struct sockaddr_un* usock = calloc(1, sizeof(struct sockaddr_un) + 1); - if(usock) { - socklen_t ulen = sizeof(struct sockaddr_un); - if(getsockname(fd, (struct sockaddr*)usock, &ulen) != -1) { - log_info("accepted new dnstap client from %s", usock->sun_path); - id = strdup(usock->sun_path); - } else { - log_info("accepted new dnstap client"); - } - free(usock); - } else { - log_info("accepted new dnstap client"); - } -#endif /* HAVE_SYS_UN_H */ - } else if(addr.ss_family == AF_INET || - addr.ss_family == AF_INET6) { - char ip[256]; - addr_to_str(&addr, addrlen, ip, sizeof(ip)); - log_info("accepted new dnstap client from %s", ip); - id = strdup(ip); - } else { - log_info("accepted new dnstap client"); - } - } - - data = calloc(1, sizeof(*data)); - if(!data) fatal_exit("out of memory"); - data->fd = s; - data->id = id; - if(tap_sock->sslctx) { - data->ssl = incoming_ssl_fd(tap_sock->sslctx, data->fd); - if(!data->ssl) fatal_exit("could not SSL_new"); - } - data->ev = ub_event_new(maindata->base, s, UB_EV_READ | UB_EV_PERSIST, - &dtio_tap_callback, data); - if(!data->ev) fatal_exit("could not ub_event_new"); - if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add"); -} - -/** setup local accept sockets */ -static void setup_local_list(struct main_tap_data* maindata, - struct config_strlist_head* local_list) -{ - struct config_strlist* item; - for(item = local_list->first; item; item = item->next) { - struct tap_socket* s; - s = tap_socket_new_local(item->str, &dtio_mainfdcallback, - maindata); - if(!s) fatal_exit("out of memory"); - if(!tap_socket_list_insert(&maindata->acceptlist, s)) - fatal_exit("out of memory"); - } -} - -/** setup tcp accept sockets */ -static void setup_tcp_list(struct main_tap_data* maindata, - struct config_strlist_head* tcp_list) -{ - struct config_strlist* item; - for(item = tcp_list->first; item; item = item->next) { - struct tap_socket* s; - s = tap_socket_new_tcpaccept(item->str, &dtio_mainfdcallback, - maindata); - if(!s) fatal_exit("out of memory"); - if(!tap_socket_list_insert(&maindata->acceptlist, s)) - fatal_exit("out of memory"); - } -} - -/** setup tls accept sockets */ -static void setup_tls_list(struct main_tap_data* maindata, - struct config_strlist_head* tls_list, char* server_key, - char* server_cert, char* verifypem) -{ - struct config_strlist* item; - for(item = tls_list->first; item; item = item->next) { - struct tap_socket* s; - s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback, - maindata, server_key, server_cert, verifypem); - if(!s) fatal_exit("out of memory"); - if(!tap_socket_list_insert(&maindata->acceptlist, s)) - fatal_exit("out of memory"); - } -} - -/** signal variable */ -static struct ub_event_base* sig_base = NULL; -/** do we have to quit */ -int sig_quit = 0; -/** signal handler for user quit */ -static RETSIGTYPE main_sigh(int sig) -{ - if(!sig_quit) { - char str[] = "exit on signal \n"; - str[15] = '0' + (sig/10)%10; - str[16] = '0' + sig%10; - /* simple cast to void will not silence Wunused-result */ - (void)!write(STDERR_FILENO, str, strlen(str)); - } - if(sig_base) { - ub_event_base_loopexit(sig_base); - sig_base = NULL; - } - sig_quit = 1; -} - -/** setup and run the server to listen to DNSTAP messages */ -static void -setup_and_run(struct config_strlist_head* local_list, - struct config_strlist_head* tcp_list, - struct config_strlist_head* tls_list, char* server_key, - char* server_cert, char* verifypem) -{ - time_t secs = 0; - struct timeval now; - struct main_tap_data* maindata; - struct ub_event_base* base; - const char *evnm="event", *evsys="", *evmethod=""; - - maindata = calloc(1, sizeof(*maindata)); - if(!maindata) fatal_exit("out of memory"); - memset(&now, 0, sizeof(now)); - base = ub_default_event_base(1, &secs, &now); - if(!base) fatal_exit("could not create ub_event base"); - maindata->base = base; - sig_base = base; - if(sig_quit) { - ub_event_base_free(base); - free(maindata); - return; - } - ub_get_event_sys(base, &evnm, &evsys, &evmethod); - if(verbosity) log_info("%s %s uses %s method", evnm, evsys, evmethod); - - setup_local_list(maindata, local_list); - setup_tcp_list(maindata, tcp_list); - setup_tls_list(maindata, tls_list, server_key, server_cert, - verifypem); - if(!tap_socket_list_addevs(maindata->acceptlist, base)) - fatal_exit("could not setup accept events"); - if(verbosity) log_info("start of service"); - - ub_event_base_dispatch(base); - sig_base = NULL; - - if(verbosity) log_info("end of service"); - tap_socket_list_delete(maindata->acceptlist); - ub_event_base_free(base); - free(maindata); -} - -/** getopt global, in case header files fail to declare it. */ -extern int optind; -/** getopt global, in case header files fail to declare it. */ -extern char* optarg; - -/** main program for streamtcp */ -int main(int argc, char** argv) -{ - int c; - int usessl = 0; - struct config_strlist_head local_list; - struct config_strlist_head tcp_list; - struct config_strlist_head tls_list; - char* server_key = NULL, *server_cert = NULL, *verifypem = NULL; -#ifdef USE_WINSOCK - WSADATA wsa_data; - if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) { - printf("WSAStartup failed\n"); - return 1; - } -#endif - if(signal(SIGINT, main_sigh) == SIG_ERR || -#ifdef SIGQUIT - signal(SIGQUIT, main_sigh) == SIG_ERR || -#endif -#ifdef SIGHUP - signal(SIGHUP, main_sigh) == SIG_ERR || -#endif -#ifdef SIGBREAK - signal(SIGBREAK, main_sigh) == SIG_ERR || -#endif - signal(SIGTERM, main_sigh) == SIG_ERR) - fatal_exit("could not bind to signal"); - memset(&local_list, 0, sizeof(local_list)); - memset(&tcp_list, 0, sizeof(tcp_list)); - memset(&tls_list, 0, sizeof(tls_list)); - - /* lock debug start (if any) */ - checklock_start(); - log_ident_set("unbound-dnstap-socket"); - log_init(0, 0, 0); - -#ifdef SIGPIPE - if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) { - perror("could not install signal handler for SIGPIPE"); - return 1; - } -#endif - - /* command line options */ - while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) { - switch(c) { - case 'u': - if(!cfg_strlist_append(&local_list, - strdup(optarg))) - fatal_exit("out of memory"); - break; - case 's': - if(!cfg_strlist_append(&tcp_list, - strdup(optarg))) - fatal_exit("out of memory"); - break; - case 't': - if(!cfg_strlist_append(&tls_list, - strdup(optarg))) - fatal_exit("out of memory"); - usessl = 1; - break; - case 'x': - server_key = optarg; - usessl = 1; - break; - case 'y': - server_cert = optarg; - usessl = 1; - break; - case 'z': - verifypem = optarg; - usessl = 1; - break; - case 'l': - longformat = 1; - break; - case 'v': - verbosity++; - break; - case 'h': - case '?': - default: - usage(argv); - } - } - argc -= optind; - argv += optind; - - if(usessl) { -#ifdef HAVE_SSL -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) - ERR_load_SSL_strings(); -#endif -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) -# ifndef S_SPLINT_S - OpenSSL_add_all_algorithms(); -# endif -#else - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS - | OPENSSL_INIT_ADD_ALL_DIGESTS - | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); -#endif -#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) - (void)SSL_library_init(); -#else - (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); -#endif -#endif /* HAVE_SSL */ - } - setup_and_run(&local_list, &tcp_list, &tls_list, server_key, - server_cert, verifypem); - config_delstrlist(local_list.first); - config_delstrlist(tcp_list.first); - config_delstrlist(tls_list.first); - - checklock_stop(); -#ifdef USE_WINSOCK - WSACleanup(); -#endif - return 0; -} - -/***--- definitions to make fptr_wlist work. ---***/ -/* These are callbacks, similar to smallapp callbacks, except the debug - * tool callbacks are not in it */ -struct tube; -struct query_info; -#include "util/data/packed_rrset.h" -#include "daemon/worker.h" -#include "daemon/remote.h" -#include "util/fptr_wlist.h" -#include "libunbound/context.h" - -void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), - uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), - int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -int worker_handle_request(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -int remote_control_callback(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -struct outbound_entry* worker_send_query( - struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags), - int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit), - struct sockaddr_storage* ATTR_UNUSED(addr), - socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), - int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), - struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); - return 0; -} - -#ifdef UB_ON_WINDOWS -void -worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* - ATTR_UNUSED(arg)) { - log_assert(0); -} - -void -wsvc_cron_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif /* UB_ON_WINDOWS */ - -void -worker_alloc_cleanup(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -struct outbound_entry* libworker_send_query( - struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags), - int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit), - struct sockaddr_storage* ATTR_UNUSED(addr), - socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), - int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), - struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); - return 0; -} - -int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), - uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), - int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), - struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); -} - -int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_start_accept(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_stop_accept(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -/** keep track of lock id in lock-verify application */ -struct order_id { - /** the thread id that created it */ - int thr; - /** the instance number of creation */ - int instance; -}; - -int order_lock_cmp(const void* e1, const void* e2) -{ - const struct order_id* o1 = e1; - const struct order_id* o2 = e2; - if(o1->thr < o2->thr) return -1; - if(o1->thr > o2->thr) return 1; - if(o1->instance < o2->instance) return -1; - if(o1->instance > o2->instance) return 1; - return 0; -} - -int -codeline_cmp(const void* a, const void* b) -{ - return strcmp(a, b); -} - -int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} diff --git a/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.c b/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.c deleted file mode 100644 index ffac7ff3..00000000 --- a/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.c +++ /dev/null @@ -1,306 +0,0 @@ -/** - * \file - * This file contains the dynamic library module for Unbound. - * This loads a dynamic library (.dll, .so) and calls that for the - * module actions. - */ -#include "config.h" -#include "dynlibmod/dynlibmod.h" -#include "util/module.h" -#include "util/config_file.h" - -#if HAVE_WINDOWS_H -#include -#define __DYNMOD HMODULE -#define __DYNSYM FARPROC -#define __LOADSYM GetProcAddress -static void log_dlerror() { - DWORD dwLastError = GetLastError(); - LPSTR MessageBuffer; - DWORD dwBufferLength; - DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM ; - if((dwBufferLength = FormatMessageA( - dwFormatFlags, - NULL, // module to get message from (NULL == system) - dwLastError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language - (LPSTR) &MessageBuffer, - 0, - NULL - ))) - { - log_err("dynlibmod: %s (%ld)", MessageBuffer, dwLastError); - LocalFree(MessageBuffer); - } - -} - -static HMODULE open_library(const char* fname) { - return LoadLibrary(fname); -} - -static void close_library(const char* fname, __DYNMOD handle) { - (void)fname; - (void)handle; -} -#else -#include -#define __DYNMOD void* -#define __DYNSYM void* -#define __LOADSYM dlsym -static void log_dlerror() { - log_err("dynlibmod: %s", dlerror()); -} - -static void* open_library(const char* fname) { - return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL); -} - -static void close_library(const char* fname, __DYNMOD handle) { - if(!handle) return; - if(dlclose(handle) != 0) { - log_err("dlclose %s: %s", fname, strerror(errno)); - } -} -#endif - -/** module counter for multiple dynlib modules */ -static int dynlib_mod_count = 0; - -/** dynlib module init */ -int dynlibmod_init(struct module_env* env, int id) { - int dynlib_mod_idx = dynlib_mod_count++; - struct config_strlist* cfg_item = env->cfg->dynlib_file; - struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env)); - __DYNMOD dynamic_library; - if (!de) - { - log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx); - return 0; - } - - env->modinfo[id] = (void*) de; - - de->fname = NULL; - for(int i = dynlib_mod_idx; - i != 0 && cfg_item != NULL; - i--, cfg_item = cfg_item->next) {} - - if (cfg_item == NULL || cfg_item->str == NULL || cfg_item->str[0] == 0) { - log_err("dynlibmod[%d]: no dynamic library given.", dynlib_mod_idx); - return 0; - } else { - de->fname = cfg_item->str; - } - verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname); - dynamic_library = open_library(de->fname); - de->dynamic_library = (void*)dynamic_library; - if (dynamic_library == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - __DYNSYM initializer; - __DYNSYM deinitializer; - __DYNSYM operate; - __DYNSYM inform; - __DYNSYM clear; - __DYNSYM get_mem; - initializer = __LOADSYM(dynamic_library,"init"); - if (initializer == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load init procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_init = (func_init_t)(void*)initializer; - } - deinitializer = __LOADSYM(dynamic_library,"deinit"); - if (deinitializer == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load deinit procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_deinit = (func_deinit_t)(void*)deinitializer; - } - operate = __LOADSYM(dynamic_library,"operate"); - if (operate == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load operate procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_operate = (func_operate_t)(void*)operate; - } - inform = __LOADSYM(dynamic_library,"inform_super"); - if (inform == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load inform_super procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_inform = (func_inform_t)(void*)inform; - } - clear = __LOADSYM(dynamic_library,"clear"); - if (clear == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load clear procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_clear = (func_clear_t)(void*)clear; - } - get_mem = __LOADSYM(dynamic_library,"get_mem"); - if (get_mem == NULL) { - log_dlerror(); - log_err("dynlibmod[%d]: unable to load get_mem procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname); - return 0; - } else { - de->func_get_mem = (func_get_mem_t)(void*)get_mem; - } - } - de->inplace_cb_delete_wrapped = &inplace_cb_delete_wrapped; - de->inplace_cb_register_wrapped = &inplace_cb_register_wrapped; - return de->func_init(env, id); -} - -/** dynlib module deinit */ -void dynlibmod_deinit(struct module_env* env, int id) { - struct dynlibmod_env* de = env->modinfo[id]; - if(de == NULL) - return; - de->func_deinit(env, id); - close_library(de->fname, (__DYNMOD)de->dynamic_library); - dynlib_mod_count--; - de->fname = NULL; - free(de); -} - -/** dynlib module operate on a query */ -void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound) { - struct dynlibmod_env* de = qstate->env->modinfo[id]; - - de->func_operate(qstate, event, id, outbound); -} - -/** dynlib module */ -void dynlibmod_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) { - struct dynlibmod_env* de = qstate->env->modinfo[id]; - - de->func_inform(qstate, id, super); -} - -/** dynlib module cleanup query state */ -void dynlibmod_clear(struct module_qstate* qstate, int id) { - struct dynlibmod_env* de = qstate->env->modinfo[id]; - - de->func_clear(qstate, id); -} - -/** dynlib module alloc size routine */ -size_t dynlibmod_get_mem(struct module_env* env, int id) { - struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id]; - size_t size; - verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de); - if(!de) - return 0; - - size = de->func_get_mem(env, id); - return size + sizeof(*de); -} - -int dynlib_inplace_cb_reply_generic(struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct edns_option** opt_list_out, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time, int id, void* callback) { - struct cb_pair* cb_pair = (struct cb_pair*) callback; - return ((inplace_cb_reply_func_type*) cb_pair->cb)(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, region, start_time, id, cb_pair->cb_arg); -} - -int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags, - struct module_qstate* qstate, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region, - int id, void* callback) { - struct cb_pair* cb_pair = (struct cb_pair*) callback; - return ((inplace_cb_query_func_type*) cb_pair->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, id, cb_pair->cb_arg); -} - -int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate, - int id, void* cb_args) { - struct cb_pair* cb_pair = (struct cb_pair*) cb_args; - return ((inplace_cb_edns_back_parsed_func_type*) cb_pair->cb)(qstate, id, cb_pair->cb_arg); -} - -int dynlib_inplace_cb_query_response(struct module_qstate* qstate, - struct dns_msg* response, int id, void* cb_args) { - struct cb_pair* cb_pair = (struct cb_pair*) cb_args; - return ((inplace_cb_query_response_func_type*) cb_pair->cb)(qstate, response, id, cb_pair->cb_arg); -} - -int -inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg, - struct module_env* env, int id) { - struct cb_pair* cb_pair = malloc(sizeof(struct cb_pair)); - if(cb_pair == NULL) { - log_err("dynlibmod[%d]: malloc failure", id); - return 0; - } - cb_pair->cb = cb; - cb_pair->cb_arg = cbarg; - if(type >= inplace_cb_reply && type <= inplace_cb_reply_servfail) { - return inplace_cb_register(&dynlib_inplace_cb_reply_generic, type, (void*) cb_pair, env, id); - } else if(type == inplace_cb_query) { - return inplace_cb_register(&dynlib_inplace_cb_query_generic, type, (void*) cb_pair, env, id); - } else if(type == inplace_cb_query_response) { - return inplace_cb_register(&dynlib_inplace_cb_query_response, type, (void*) cb_pair, env, id); - } else if(type == inplace_cb_edns_back_parsed) { - return inplace_cb_register(&dynlib_inplace_cb_edns_back_parsed, type, (void*) cb_pair, env, id); - } else { - free(cb_pair); - return 0; - } -} - -void -inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type, - int id) { - struct inplace_cb* temp = env->inplace_cb_lists[type]; - struct inplace_cb* prev = NULL; - - while(temp) { - if(temp->id == id) { - if(!prev) { - env->inplace_cb_lists[type] = temp->next; - free(temp->cb_arg); - free(temp); - temp = env->inplace_cb_lists[type]; - } - else { - prev->next = temp->next; - free(temp->cb_arg); - free(temp); - temp = prev->next; - } - } - else { - prev = temp; - temp = temp->next; - } - } -} - - -/** - * The module function block - */ -static struct module_func_block dynlibmod_block = { - "dynlib", - &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super, - &dynlibmod_clear, &dynlibmod_get_mem -}; - -struct module_func_block* dynlibmod_get_funcblock(void) -{ - return &dynlibmod_block; -} diff --git a/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.h b/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.h deleted file mode 100644 index 321f4f69..00000000 --- a/crates/libunbound-sys/unbound/dynlibmod/dynlibmod.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * dynlibmod.h: module header file - * - * Copyright (c) 2019, Peter Munch-Ellingsen (peterme AT peterme.net) - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Dynamic loading module for unbound. Loads dynamic library. - */ -#ifndef DYNLIBMOD_H -#define DYNLIBMOD_H -#include "util/module.h" -#include "services/outbound_list.h" - -/** - * Get the module function block. - * @return: function block with function pointers to module methods. - */ -struct module_func_block* dynlibmod_get_funcblock(void); - -/** dynlib module init */ -int dynlibmod_init(struct module_env* env, int id); - -/** dynlib module deinit */ -void dynlibmod_deinit(struct module_env* env, int id); - -/** dynlib module operate on a query */ -void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); - -/** dynlib module */ -void dynlibmod_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** dynlib module cleanup query state */ -void dynlibmod_clear(struct module_qstate* qstate, int id); - -/** dynlib module alloc size routine */ -size_t dynlibmod_get_mem(struct module_env* env, int id); - -int dynlib_inplace_cb_reply_generic(struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct edns_option** opt_list_out, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time, int id, void* callback); - -int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags, - struct module_qstate* qstate, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region, - int id, void* callback); - -int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate, - int id, void* cb_args); - -int dynlib_inplace_cb_query_response(struct module_qstate* qstate, - struct dns_msg* response, int id, void* cb_args); - -int -inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg, - struct module_env* env, int id); - -void -inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type, - int id); - -struct cb_pair { - void *cb; - void *cb_arg; -}; - -/** - * Global state for the module. - */ - -typedef int (*func_init_t)(struct module_env*, int); -typedef void (*func_deinit_t)(struct module_env*, int); -typedef void (*func_operate_t)(struct module_qstate*, enum module_ev, int, struct outbound_entry*); -typedef void (*func_inform_t)(struct module_qstate*, int, struct module_qstate*); -typedef void (*func_clear_t)(struct module_qstate*, int); -typedef size_t (*func_get_mem_t)(struct module_env*, int); -typedef void (*inplace_cb_delete_wrapped_t)(struct module_env*, enum inplace_cb_list_type, int); -typedef int (*inplace_cb_register_wrapped_t)(void*, enum inplace_cb_list_type, void*, struct module_env*, int); - - -struct dynlibmod_env { - /** Dynamic library filename. */ - const char* fname; - /** dynamic library handle */ - void* dynamic_library; - /** Module init function */ - func_init_t func_init; - /** Module deinit function */ - func_deinit_t func_deinit; - /** Module operate function */ - func_operate_t func_operate; - /** Module super_inform function */ - func_inform_t func_inform; - /** Module clear function */ - func_clear_t func_clear; - /** Module get_mem function */ - func_get_mem_t func_get_mem; - /** Wrapped inplace callback functions to circumvent callback whitelisting */ - inplace_cb_delete_wrapped_t inplace_cb_delete_wrapped; - inplace_cb_register_wrapped_t inplace_cb_register_wrapped; - /** Pointer to any data the dynamic library might want to keep */ - void *dyn_env; -}; - - -#endif /* DYNLIBMOD_H */ diff --git a/crates/libunbound-sys/unbound/dynlibmod/examples/helloworld.c b/crates/libunbound-sys/unbound/dynlibmod/examples/helloworld.c deleted file mode 100644 index be211684..00000000 --- a/crates/libunbound-sys/unbound/dynlibmod/examples/helloworld.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * \file - * - * This is an example to show how dynamic libraries can be made to work with - * unbound. To build a .so file simply run: - * gcc -I../.. -shared -Wall -Werror -fpic -o helloworld.so helloworld.c - * And to build for windows, first make unbound with the --with-dynlibmod - * switch, then use this command: - * x86_64-w64-mingw32-gcc -m64 -I../.. -shared -Wall -Werror -fpic - * -o helloworld.dll helloworld.c -L../.. -l:libunbound.dll.a - * to cross-compile a 64-bit Windows DLL. The libunbound.dll.a is produced - * by the compile step that makes unbound.exe and allows the dynlib dll to - * access definitions in unbound.exe. - */ - -#include "../../config.h" -#include "../../util/module.h" -#include "../../sldns/parseutil.h" -#include "../dynlibmod.h" - -/* Declare the EXPORT macro that expands to exporting the symbol for DLLs when - * compiling for Windows. All procedures marked with EXPORT in this example are - * called directly by the dynlib module and must be present for the module to - * load correctly. */ -#ifdef HAVE_WINDOWS_H -#define EXPORT __declspec(dllexport) -#else -#define EXPORT -#endif - -/* Forward declare a callback, implemented at the bottom of this file */ -int reply_callback(struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct edns_option** opt_list_out, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time, int id, void* callback); - -/* Init is called when the module is first loaded. It should be used to set up - * the environment for this module and do any other initialisation required. */ -EXPORT int init(struct module_env* env, int id) { - log_info("dynlib: hello world from init"); - struct dynlibmod_env* de = (struct dynlibmod_env*) env->modinfo[id]; - de->inplace_cb_register_wrapped(&reply_callback, - inplace_cb_reply, - NULL, env, id); - struct dynlibmod_env* local_env = env->modinfo[id]; - local_env->dyn_env = NULL; - return 1; -} - -/* Deinit is run as the program is shutting down. It should be used to clean up - * the environment and any left over data. */ -EXPORT void deinit(struct module_env* env, int id) { - log_info("dynlib: hello world from deinit"); - struct dynlibmod_env* de = (struct dynlibmod_env*) env->modinfo[id]; - de->inplace_cb_delete_wrapped(env, inplace_cb_reply, id); - if (de->dyn_env != NULL) free(de->dyn_env); -} - -/* Operate is called every time a query passes by this module. The event can be - * used to determine which direction in the module chain it came from. */ -EXPORT void operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* entry) { - log_info("dynlib: hello world from operate"); - log_info("dynlib: incoming query: %s %s(%d) %s(%d)", - qstate->qinfo.qname, - sldns_lookup_by_id(sldns_rr_classes, qstate->qinfo.qclass)->name, - qstate->qinfo.qclass, - sldns_rr_descript(qstate->qinfo.qtype)->_name, - qstate->qinfo.qtype); - if (event == module_event_new || event == module_event_pass) { - qstate->ext_state[id] = module_wait_module; - struct dynlibmod_env* env = qstate->env->modinfo[id]; - if (env->dyn_env == NULL) { - env->dyn_env = calloc(3, sizeof(int)); - ((int *)env->dyn_env)[0] = 42; - ((int *)env->dyn_env)[1] = 102; - ((int *)env->dyn_env)[2] = 192; - } else { - log_err("dynlib: already has data!"); - qstate->ext_state[id] = module_error; - } - } else if (event == module_event_moddone) { - qstate->ext_state[id] = module_finished; - } else { - qstate->ext_state[id] = module_error; - } -} - -/* Inform super is called when a query is completed or errors out, but only if - * a sub-query has been registered to it by this module. Look at - * mesh_attach_sub in services/mesh.h to see how this is done. */ -EXPORT void inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) { - log_info("dynlib: hello world from inform_super"); -} - -/* Clear is called once a query is complete and the response has been sent - * back. It is used to clear up any per-query allocations. */ -EXPORT void clear(struct module_qstate* qstate, int id) { - log_info("dynlib: hello world from clear"); - struct dynlibmod_env* env = qstate->env->modinfo[id]; - if (env->dyn_env != NULL) { - free(env->dyn_env); - env->dyn_env = NULL; - } -} - -/* Get mem is called when Unbound is printing performance information. This - * only happens explicitly and is only used to show memory usage to the user. */ -EXPORT size_t get_mem(struct module_env* env, int id) { - log_info("dynlib: hello world from get_mem"); - return 0; -} - -/* The callback that was forward declared earlier. It is registered in the init - * procedure to run when a query is being replied to. */ -int reply_callback(struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct edns_option** opt_list_out, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time, int id, void* callback) { - log_info("dynlib: hello world from callback"); - struct dynlibmod_env* env = qstate->env->modinfo[id]; - if (env->dyn_env != NULL) { - log_info("dynlib: numbers gotten from query: %d, %d, and %d", - ((int *)env->dyn_env)[0], - ((int *)env->dyn_env)[1], - ((int *)env->dyn_env)[2]); - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/edns-subnet/addrtree.c b/crates/libunbound-sys/unbound/edns-subnet/addrtree.c deleted file mode 100644 index ebe71b97..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/addrtree.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * edns-subnet/addrtree.c -- radix tree for edns subnet cache. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** \file - * addrtree -- radix tree for edns subnet cache. - */ - -#include "config.h" -#include "util/log.h" -#include "util/data/msgreply.h" -#include "util/module.h" -#include "addrtree.h" - -/** - * Create a new edge - * @param node: Child node this edge will connect to. - * @param addr: full key to this edge. - * @param addrlen: length of relevant part of key for this node - * @param parent_node: Parent node for node - * @param parent_index: Index of child node at parent node - * @return new addredge or NULL on failure - */ -static struct addredge * -edge_create(struct addrnode *node, const addrkey_t *addr, - addrlen_t addrlen, struct addrnode *parent_node, int parent_index) -{ - size_t n; - struct addredge *edge = (struct addredge *)malloc( sizeof (*edge) ); - if (!edge) - return NULL; - edge->node = node; - edge->len = addrlen; - edge->parent_index = parent_index; - edge->parent_node = parent_node; - /* ceil() */ - n = (size_t)((addrlen / KEYWIDTH) + ((addrlen % KEYWIDTH != 0)?1:0)); - edge->str = (addrkey_t *)calloc(n, sizeof (addrkey_t)); - if (!edge->str) { - free(edge); - return NULL; - } - memcpy(edge->str, addr, n * sizeof (addrkey_t)); - /* Only manipulate other objects after successful alloc */ - node->parent_edge = edge; - log_assert(parent_node->edge[parent_index] == NULL); - parent_node->edge[parent_index] = edge; - return edge; -} - -/** - * Create a new node - * @param tree: Tree the node lives in. - * @param elem: Element to store at this node - * @param scope: Scopemask from server reply - * @param ttl: Element is valid up to this time. Absolute, seconds - * @return new addrnode or NULL on failure - */ -static struct addrnode * -node_create(struct addrtree *tree, void *elem, addrlen_t scope, - time_t ttl) -{ - struct addrnode* node = (struct addrnode *)malloc( sizeof (*node) ); - if (!node) - return NULL; - node->elem = elem; - tree->node_count++; - node->scope = scope; - node->ttl = ttl; - node->only_match_scope_zero = 0; - node->edge[0] = NULL; - node->edge[1] = NULL; - node->parent_edge = NULL; - node->next = NULL; - node->prev = NULL; - return node; -} - -/** Size in bytes of node and parent edge - * @param tree: tree the node lives in - * @param n: node which size must be calculated - * @return size in bytes. - **/ -static inline size_t -node_size(const struct addrtree *tree, const struct addrnode *n) -{ - return sizeof *n + sizeof *n->parent_edge + n->parent_edge->len + - (n->elem?tree->sizefunc(n->elem):0); -} - -struct addrtree * -addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *), - size_t (*sizefunc)(void *), void *env, uint32_t max_node_count) -{ - struct addrtree *tree; - log_assert(delfunc != NULL); - log_assert(sizefunc != NULL); - tree = (struct addrtree *)calloc(1, sizeof(*tree)); - if (!tree) - return NULL; - tree->root = node_create(tree, NULL, 0, 0); - if (!tree->root) { - free(tree); - return NULL; - } - tree->size_bytes = sizeof *tree + sizeof *tree->root; - tree->first = NULL; - tree->last = NULL; - tree->max_depth = max_depth; - tree->delfunc = delfunc; - tree->sizefunc = sizefunc; - tree->env = env; - tree->node_count = 0; - tree->max_node_count = max_node_count; - return tree; -} - -/** - * Scrub a node clean of elem - * @param tree: tree the node lives in. - * @param node: node to be cleaned. - */ -static void -clean_node(struct addrtree *tree, struct addrnode *node) -{ - if (!node->elem) return; - tree->size_bytes -= tree->sizefunc(node->elem); - tree->delfunc(tree->env, node->elem); - node->only_match_scope_zero = 0; - node->elem = NULL; -} - -/** Remove specified node from LRU list */ -static void -lru_pop(struct addrtree *tree, struct addrnode *node) -{ - if (node == tree->first) { - if (!node->next) { /* it is the last as well */ - tree->first = NULL; - tree->last = NULL; - } else { - tree->first = node->next; - tree->first->prev = NULL; - } - } else if (node == tree->last) { /* but not the first */ - tree->last = node->prev; - tree->last->next = NULL; - } else { - node->prev->next = node->next; - node->next->prev = node->prev; - } -} - -/** Add node to LRU list as most recently used. */ -static void -lru_push(struct addrtree *tree, struct addrnode *node) -{ - if (!tree->first) { - tree->first = node; - node->prev = NULL; - } else { - tree->last->next = node; - node->prev = tree->last; - } - tree->last = node; - node->next = NULL; -} - -/** Move node to the end of LRU list */ -static void -lru_update(struct addrtree *tree, struct addrnode *node) -{ - if (tree->root == node) return; - lru_pop(tree, node); - lru_push(tree, node); -} - -/** - * Purge a node from the tree. Node and parentedge are cleaned and - * free'd. - * @param tree: Tree the node lives in. - * @param node: Node to be freed - */ -static void -purge_node(struct addrtree *tree, struct addrnode *node) -{ - struct addredge *parent_edge, *child_edge = NULL; - int index; - int keep = node->edge[0] && node->edge[1]; - - clean_node(tree, node); - parent_edge = node->parent_edge; - if (keep || !parent_edge) return; - tree->node_count--; - index = parent_edge->parent_index; - child_edge = node->edge[!node->edge[0]]; - if (child_edge) { - child_edge->parent_node = parent_edge->parent_node; - child_edge->parent_index = index; - } - parent_edge->parent_node->edge[index] = child_edge; - tree->size_bytes -= node_size(tree, node); - free(parent_edge->str); - free(parent_edge); - lru_pop(tree, node); - free(node); -} - -/** - * If a limit is set remove old nodes while above that limit. - * @param tree: Tree to be cleaned up. - */ -static void -lru_cleanup(struct addrtree *tree) -{ - struct addrnode *n, *p; - int children; - if (tree->max_node_count == 0) return; - while (tree->node_count > tree->max_node_count) { - n = tree->first; - if (!n) break; - children = (n->edge[0] != NULL) + (n->edge[1] != NULL); - /** Don't remove this node, it is either the root or we can't - * do without it because it has 2 children */ - if (children == 2 || !n->parent_edge) { - lru_update(tree, n); - continue; - } - p = n->parent_edge->parent_node; - purge_node(tree, n); - /** Since we removed n, n's parent p is eligible for deletion - * if it is not the root node, caries no data and has only 1 - * child */ - children = (p->edge[0] != NULL) + (p->edge[1] != NULL); - if (!p->elem && children == 1 && p->parent_edge) { - purge_node(tree, p); - } - } -} - -inline size_t -addrtree_size(const struct addrtree *tree) -{ - return tree?tree->size_bytes:0; -} - -void addrtree_delete(struct addrtree *tree) -{ - struct addrnode *n; - if (!tree) return; - clean_node(tree, tree->root); - free(tree->root); - tree->size_bytes -= sizeof(struct addrnode); - while ((n = tree->first)) { - tree->first = n->next; - clean_node(tree, n); - tree->size_bytes -= node_size(tree, n); - free(n->parent_edge->str); - free(n->parent_edge); - free(n); - } - log_assert(sizeof *tree == addrtree_size(tree)); - free(tree); -} - -/** - * Get N'th bit from address - * @param addr: address to inspect - * @param addrlen: length of addr in bits - * @param n: index of bit to test. Must be in range [0, addrlen) - * @return 0 or 1 - */ -static int -getbit(const addrkey_t *addr, addrlen_t addrlen, addrlen_t n) -{ - log_assert(addrlen > n); - (void)addrlen; - return (int)(addr[n/KEYWIDTH]>>((KEYWIDTH-1)-(n%KEYWIDTH))) & 1; -} - -/** - * Test for equality on N'th bit. - * @return 0 for equal, 1 otherwise - */ -static inline int -cmpbit(const addrkey_t *key1, const addrkey_t *key2, addrlen_t n) -{ - addrkey_t c = key1[n/KEYWIDTH] ^ key2[n/KEYWIDTH]; - return (int)(c >> ((KEYWIDTH-1)-(n%KEYWIDTH))) & 1; -} - -/** - * Common number of bits in prefix. - * @param s1: first prefix. - * @param l1: length of s1 in bits. - * @param s2: second prefix. - * @param l2: length of s2 in bits. - * @param skip: nr of bits already checked. - * @return common number of bits. - */ -static addrlen_t -bits_common(const addrkey_t *s1, addrlen_t l1, - const addrkey_t *s2, addrlen_t l2, addrlen_t skip) -{ - addrlen_t len, i; - len = (l1 > l2) ? l2 : l1; - log_assert(skip < len); - for (i = skip; i < len; i++) { - if (cmpbit(s1, s2, i)) return i; - } - return len; -} - -/** - * Tests if s1 is a substring of s2 - * @param s1: first prefix. - * @param l1: length of s1 in bits. - * @param s2: second prefix. - * @param l2: length of s2 in bits. - * @param skip: nr of bits already checked. - * @return 1 for substring, 0 otherwise - */ -static int -issub(const addrkey_t *s1, addrlen_t l1, - const addrkey_t *s2, addrlen_t l2, addrlen_t skip) -{ - return bits_common(s1, l1, s2, l2, skip) == l1; -} - -void -addrtree_insert(struct addrtree *tree, const addrkey_t *addr, - addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, - time_t now, int only_match_scope_zero) -{ - struct addrnode *newnode, *node; - struct addredge *edge; - int index; - addrlen_t common, depth; - - node = tree->root; - log_assert(node != NULL); - - /* Protect our cache against too much fine-grained data */ - if (tree->max_depth < scope) scope = tree->max_depth; - /* Server answer was less specific than question */ - if (scope < sourcemask) sourcemask = scope; - - depth = 0; - while (1) { - log_assert(depth <= sourcemask); - /* Case 1: update existing node */ - if (depth == sourcemask) { - /* update this node's scope and data */ - clean_node(tree, node); - node->ttl = ttl; - node->only_match_scope_zero = only_match_scope_zero; - node->elem = elem; - node->scope = scope; - tree->size_bytes += tree->sizefunc(elem); - return; - } - index = getbit(addr, sourcemask, depth); - /* Get an edge to an unexpired node */ - edge = node->edge[index]; - while (edge) { - /* Purge all expired nodes on path */ - if (!edge->node->elem || edge->node->ttl >= now) - break; - purge_node(tree, edge->node); - edge = node->edge[index]; - } - /* Case 2: New leafnode */ - if (!edge) { - newnode = node_create(tree, elem, scope, ttl); - if (!newnode) return; - if (!edge_create(newnode, addr, sourcemask, node, - index)) { - clean_node(tree, newnode); - tree->node_count--; - free(newnode); - return; - } - tree->size_bytes += node_size(tree, newnode); - lru_push(tree, newnode); - lru_cleanup(tree); - return; - } - /* Case 3: Traverse edge */ - common = bits_common(edge->str, edge->len, addr, sourcemask, - depth); - if (common == edge->len) { - /* We update the scope of intermediate nodes. Apparently - * the * authority changed its mind. If we would not do - * this we might not be able to reach our new node. */ - node->scope = scope; - depth = edge->len; - node = edge->node; - continue; - } - /* Case 4: split. */ - if (!(newnode = node_create(tree, NULL, 0, 0))) - return; - node->edge[index] = NULL; - if (!edge_create(newnode, addr, common, node, index)) { - node->edge[index] = edge; - clean_node(tree, newnode); - tree->node_count--; - free(newnode); - return; - } - lru_push(tree, newnode); - /* connect existing child to our new node */ - index = getbit(edge->str, edge->len, common); - newnode->edge[index] = edge; - edge->parent_node = newnode; - edge->parent_index = (int)index; - - if (common == sourcemask) { - /* Data is stored in the node */ - newnode->elem = elem; - newnode->scope = scope; - newnode->ttl = ttl; - newnode->only_match_scope_zero = only_match_scope_zero; - } - - tree->size_bytes += node_size(tree, newnode); - - if (common != sourcemask) { - /* Data is stored in other leafnode */ - node = newnode; - newnode = node_create(tree, elem, scope, ttl); - if (!edge_create(newnode, addr, sourcemask, node, - index^1)) { - clean_node(tree, newnode); - tree->node_count--; - free(newnode); - return; - } - tree->size_bytes += node_size(tree, newnode); - lru_push(tree, newnode); - } - lru_cleanup(tree); - return; - } -} - -struct addrnode * -addrtree_find(struct addrtree *tree, const addrkey_t *addr, - addrlen_t sourcemask, time_t now) -{ - struct addrnode *node = tree->root; - struct addredge *edge = NULL; - addrlen_t depth = 0; - - log_assert(node != NULL); - while (1) { - /* Current node more specific then question. */ - log_assert(depth <= sourcemask); - /* does this node have data? if yes, see if we have a match */ - if (node->elem && node->ttl >= now && - !(sourcemask != 0 && node->only_match_scope_zero)) { - /* saved at wrong depth */; - log_assert(node->scope >= depth); - if (depth == node->scope || - (node->scope > sourcemask && - depth == sourcemask)) { - /* Authority indicates it does not have a more - * precise answer or we cannot ask a more - * specific question. */ - lru_update(tree, node); - return node; - } - } - /* This is our final depth, but we haven't found an answer. */ - if (depth == sourcemask) - return NULL; - /* Find an edge to traverse */ - edge = node->edge[getbit(addr, sourcemask, depth)]; - if (!edge || !edge->node) - return NULL; - if (edge->len > sourcemask ) - return NULL; - if (!issub(edge->str, edge->len, addr, sourcemask, depth)) - return NULL; - log_assert(depth < edge->len); - depth = edge->len; - node = edge->node; - } -} - -/** Wrappers for static functions to unit test */ -int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1, - const addrkey_t *key2, addrlen_t n) { - return cmpbit(key1, key2, n); -} -addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1, - addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip) { - return bits_common(s1, l1, s2, l2, skip); -} -int unittest_wrapper_addrtree_getbit(const addrkey_t *addr, - addrlen_t addrlen, addrlen_t n) { - return getbit(addr, addrlen, n); -} -int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1, - const addrkey_t *s2, addrlen_t l2, addrlen_t skip) { - return issub(s1, l1, s2, l2, skip); -} diff --git a/crates/libunbound-sys/unbound/edns-subnet/addrtree.h b/crates/libunbound-sys/unbound/edns-subnet/addrtree.h deleted file mode 100644 index 0bc1837c..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/addrtree.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * edns-subnet/addrtree.h -- radix tree for edns subnet cache. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * The addrtree is a radix tree designed for edns subnet. Most notable - * is the addition of 'scope' to a node. Scope is only relevant for - * nodes with elem set, it indicates the number of bits the authority - * desires. - * - * For retrieving data one needs an address and address length - * (sourcemask). While traversing the tree the first matching node is - * returned. A node matches when - * node.scope<=sourcemask && node.elem!=NULL - * (This is the most specific answer the authority has.) - * or - * node.sourcemask==sourcemask && node.elem!=NULL - * (This is the most specific question the client can ask.) - * - * Insertion needs an address, sourcemask and scope. The length of the - * address is capped by min(sourcemask, scope). While traversing the - * tree the scope of all visited nodes is updated. This ensures we are - * always able to find the most specific answer available. - */ - -#ifndef ADDRTREE_H -#define ADDRTREE_H - -typedef uint8_t addrlen_t; -typedef uint8_t addrkey_t; -#define KEYWIDTH 8 - -struct addrtree { - struct addrnode *root; - /** Number of elements in the tree (not always equal to number of - * nodes) */ - uint32_t node_count; - /** Maximum number of allowed nodes, will be enforced by LRU list. - * Excluding the root node, 0 for unlimited */ - uint32_t max_node_count; - /** Size of tree in bytes */ - size_t size_bytes; - /** Maximum prefix length we are willing to cache. */ - addrlen_t max_depth; - /** External function to delete elem. Called as - * delfunc(addrnode->elem, addrtree->env) */ - void (*delfunc)(void *, void *); - /** Environment for delfunc */ - void *env; - /** External function returning size of elem. Called as - * sizefunc(addrnode->elem) */ - size_t (*sizefunc)(void *); - /** first node in LRU list, first candidate to go */ - struct addrnode* first; - /** last node in LRU list, last candidate to go */ - struct addrnode *last; -}; - -struct addrnode { - /** Payload of node, may be NULL */ - void *elem; - /** Abs time in seconds in which elem is meaningful */ - time_t ttl; - /** Number of significant bits in address. */ - addrlen_t scope; - /** Only use the element for queries for subnet/0. Set if the query - * for /0 was answered with scope 0. For query /x answer scope 0, - * they can match anything and this is false. */ - int only_match_scope_zero; - /** A node can have 0-2 edges, set to NULL for unused */ - struct addredge *edge[2]; - /** edge between this node and parent */ - struct addredge *parent_edge; - /** previous node in LRU list */ - struct addrnode *prev; - /** next node in LRU list */ - struct addrnode *next; -}; - -struct addredge { - /** address of connected node */ - addrkey_t *str; - /** length in bits of str */ - addrlen_t len; - /** child node this edge is connected to */ - struct addrnode *node; - /** Parent node this ege is connected to */ - struct addrnode *parent_node; - /** Index of this edge in parent_node */ - int parent_index; -}; - -/** - * Size of tree in bytes. - * @param tree: Tree. - * @return size of tree in bytes. - */ -size_t addrtree_size(const struct addrtree *tree); - -/** - * Create a new tree. - * @param max_depth: Tree will cap keys to this length. - * @param delfunc: f(element, env) delete element. - * @param sizefunc: f(element) returning the size of element. - * @param env: Module environment for alloc information. - * @param max_node_count: Maximum size of this data structure in nodes. - * 0 for unlimited. - * @return new addrtree or NULL on failure. - */ -struct addrtree * -addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *), - size_t (*sizefunc)(void *), void *env, uint32_t max_node_count); - -/** - * Free tree and all nodes below. - * @param tree: Tree to be freed. - */ -void addrtree_delete(struct addrtree *tree); - -/** - * Insert an element in the tree. Failures are silent. Sourcemask and - * scope might be changed according to local policy. Caller should no - * longer access elem, it could be free'd now or later during future - * inserts. - * - * @param tree: Tree insert elem in. - * @param addr: key for element lookup. - * @param sourcemask: Length of addr in bits. - * @param scope: Number of significant bits in addr. - * @param elem: data to store in the tree. - * @param ttl: elem is valid up to this time, seconds. - * @param only_match_scope_zero: set for when query /0 has scope /0 answer. - * @param now: Current time in seconds. - */ -void addrtree_insert(struct addrtree *tree, const addrkey_t *addr, - addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, - time_t now, int only_match_scope_zero); - -/** - * Find a node containing an element in the tree. - * - * @param tree: Tree to search. - * @param addr: key for element lookup. - * @param sourcemask: Length of addr in bits. - * @param now: Current time in seconds. - * @return addrnode or NULL on miss. - */ -struct addrnode * addrtree_find(struct addrtree *tree, - const addrkey_t *addr, addrlen_t sourcemask, time_t now); - -/** Wrappers for static functions to unit test */ -int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1, - const addrkey_t *key2, addrlen_t n); -addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1, - addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip); -int unittest_wrapper_addrtree_getbit(const addrkey_t *addr, - addrlen_t addrlen, addrlen_t n); -int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1, - const addrkey_t *s2, addrlen_t l2, addrlen_t skip); -#endif /* ADDRTREE_H */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.c b/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.c deleted file mode 100644 index 4c93192f..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * edns-subnet/edns-subnet.c - Subnet option related constants - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Subnet option related constants. - */ - -#include "config.h" - -#ifdef CLIENT_SUBNET /* keeps splint happy */ -#include "edns-subnet/edns-subnet.h" -#include - -int -copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n) -{ - size_t intpart = n / 8; /* bytes */ - size_t fracpart = n % 8; /* bits */ - size_t written = intpart; - if (intpart > dstlen || intpart > srclen) - return 1; - if (fracpart && (intpart+1 > dstlen || intpart+1 > srclen)) - return 1; - memcpy(dst, src, intpart); - if (fracpart) { - dst[intpart] = src[intpart] & ~(0xFF >> fracpart); - written++; - } - memset(dst + written, 0, dstlen - written); - return 0; -} - -#endif /* CLIENT_SUBNET */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.h b/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.h deleted file mode 100644 index 6ab541de..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/edns-subnet.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * edns-subnet/edns-subnet.h - Subnet option related constants - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Subnet option related constants. - */ - -#include "util/net_help.h" - -#ifndef EDNSSUBNET_EDNSSUBNET_H -#define EDNSSUBNET_EDNSSUBNET_H - -/** In use by the edns subnet option code, as assigned by IANA */ -#define EDNSSUBNET_ADDRFAM_IP4 1 -#define EDNSSUBNET_ADDRFAM_IP6 2 - -/** - * ECS option - */ -struct ecs_data { - uint16_t subnet_addr_fam; - uint8_t subnet_source_mask; - uint8_t subnet_scope_mask; - uint8_t subnet_addr[INET6_SIZE]; - int subnet_validdata; -}; - -/** - * copy the first n BITS from src to dst iff both src and dst - * are large enough, return 0 on success - */ -int -copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n); - -#endif /* EDNSSUBNET_EDNSSUBNET_H */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.c b/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.c deleted file mode 100644 index 1ea7fb1b..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * edns-subnet/subnet-whitelist.c - Hosts we actively try to send subnet option - * to. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * - * Keep track of the white listed servers for subnet option. Based - * on acl_list.c|h - */ - -#include "config.h" - -#ifdef CLIENT_SUBNET /* keeps splint happy */ -#include "edns-subnet/edns-subnet.h" -#include "edns-subnet/subnet-whitelist.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/storage/dnstree.h" -#include "sldns/str2wire.h" -#include "util/data/dname.h" - -struct ecs_whitelist* -ecs_whitelist_create(void) -{ - struct ecs_whitelist* whitelist = - (struct ecs_whitelist*)calloc(1, - sizeof(struct ecs_whitelist)); - if(!whitelist) - return NULL; - whitelist->region = regional_create(); - if(!whitelist->region) { - ecs_whitelist_delete(whitelist); - return NULL; - } - return whitelist; -} - -void -ecs_whitelist_delete(struct ecs_whitelist* whitelist) -{ - if(!whitelist) - return; - regional_destroy(whitelist->region); - free(whitelist); -} - -/** insert new address into whitelist structure */ -static int -upstream_insert(struct ecs_whitelist* whitelist, - struct sockaddr_storage* addr, socklen_t addrlen, int net) -{ - struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc( - whitelist->region, sizeof(*node)); - if(!node) - return 0; - if(!addr_tree_insert(&whitelist->upstream, node, addr, addrlen, net)) { - verbose(VERB_QUERY, - "duplicate send-client-subnet address ignored."); - } - return 1; -} - -/** apply edns-subnet string */ -static int -upstream_str_cfg(struct ecs_whitelist* whitelist, const char* str) -{ - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - verbose(VERB_ALGO, "send-client-subnet: %s", str); - if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { - log_err("cannot parse send-client-subnet netblock: %s", str); - return 0; - } - if(!upstream_insert(whitelist, &addr, addrlen, net)) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** read client_subnet config */ -static int -read_upstream(struct ecs_whitelist* whitelist, struct config_file* cfg) -{ - struct config_strlist* p; - for(p = cfg->client_subnet; p; p = p->next) { - log_assert(p->str); - if(!upstream_str_cfg(whitelist, p->str)) - return 0; - } - return 1; -} - -/** read client_subnet_zone config */ -static int -read_names(struct ecs_whitelist* whitelist, struct config_file* cfg) -{ - /* parse names, report errors, insert into tree */ - struct config_strlist* p; - struct name_tree_node* n; - uint8_t* nm, *nmr; - size_t nm_len; - int nm_labs; - - for(p = cfg->client_subnet_zone; p; p = p->next) { - log_assert(p->str); - nm = sldns_str2wire_dname(p->str, &nm_len); - if(!nm) { - log_err("cannot parse client-subnet-zone: %s", p->str); - return 0; - } - nm_labs = dname_count_size_labels(nm, &nm_len); - nmr = (uint8_t*)regional_alloc_init(whitelist->region, nm, - nm_len); - free(nm); - if(!nmr) { - log_err("out of memory"); - return 0; - } - n = (struct name_tree_node*)regional_alloc(whitelist->region, - sizeof(*n)); - if(!n) { - log_err("out of memory"); - return 0; - } - if(!name_tree_insert(&whitelist->dname, n, nmr, nm_len, nm_labs, - LDNS_RR_CLASS_IN)) { - verbose(VERB_QUERY, "ignoring duplicate " - "client-subnet-zone: %s", p->str); - } - } - return 1; -} - -int -ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist, - struct config_file* cfg) -{ - regional_free_all(whitelist->region); - addr_tree_init(&whitelist->upstream); - name_tree_init(&whitelist->dname); - if(!read_upstream(whitelist, cfg)) - return 0; - if(!read_names(whitelist, cfg)) - return 0; - addr_tree_init_parents(&whitelist->upstream); - name_tree_init_parents(&whitelist->dname); - return 1; -} - -int -ecs_is_whitelisted(struct ecs_whitelist* whitelist, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname, - size_t qname_len, uint16_t qclass) -{ - int labs; - if(addr_tree_lookup(&whitelist->upstream, addr, addrlen)) - return 1; - /* Not in upstream whitelist, check dname whitelist. */ - labs = dname_count_labels(qname); - return name_tree_lookup(&whitelist->dname, qname, qname_len, labs, - qclass) != NULL; -} - -size_t -ecs_whitelist_get_mem(struct ecs_whitelist* whitelist) -{ - if(!whitelist) return 0; - return sizeof(*whitelist) + regional_get_mem(whitelist->region); -} - -#endif /* CLIENT_SUBNET */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.h b/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.h deleted file mode 100644 index 8cd03aba..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/subnet-whitelist.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * edns-subnet/subnet-whitelist.h - Hosts we actively try to send subnet option - * to. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * - * Keep track of the white listed servers and domain names for subnet option. - * Based on acl_list.c|h - */ - -#ifndef EDNSSUBNET_WHITELIST_H -#define EDNSSUBNET_WHITELIST_H -#include "util/storage/dnstree.h" - -struct config_file; -struct regional; - -/** - * ecs_whitelist structure - */ -struct ecs_whitelist { - /** regional for allocation */ - struct regional* region; - /** - * Tree of the address spans that are whitelisted. - * contents of type addr_tree_node. Each node is an address span - * Unbound will append subnet option for. - */ - rbtree_type upstream; - /** - * Tree of domain names for which Unbound will append an ECS option. - * rbtree of struct name_tree_node. - */ - rbtree_type dname; -}; - -/** - * Create ecs_whitelist structure - * @return new structure or NULL on error. - */ -struct ecs_whitelist* ecs_whitelist_create(void); - -/** - * Delete ecs_whitelist structure. - * @param whitelist: to delete. - */ -void ecs_whitelist_delete(struct ecs_whitelist* whitelist); - -/** - * Process ecs_whitelist config. - * @param whitelist: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist, - struct config_file* cfg); - -/** - * See if an address or domain is whitelisted. - * @param whitelist: structure for address storage. - * @param addr: address to check - * @param addrlen: length of addr. - * @param qname: dname in query - * @param qname_len: length of dname - * @param qclass: class in query - * @return: true if the address is whitelisted for subnet option. - */ -int ecs_is_whitelisted(struct ecs_whitelist* whitelist, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname, - size_t qname_len, uint16_t qclass); - -/** - * Get memory used by ecs_whitelist structure. - * @param whitelist: structure for address storage. - * @return bytes in use. - */ -size_t ecs_whitelist_get_mem(struct ecs_whitelist* whitelist); - -#endif /* EDNSSUBNET_WHITELIST_H */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/subnetmod.c b/crates/libunbound-sys/unbound/edns-subnet/subnetmod.c deleted file mode 100644 index 13fd669b..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/subnetmod.c +++ /dev/null @@ -1,957 +0,0 @@ -/* - * edns-subnet/subnetmod.c - edns subnet module. Must be called before validator - * and iterator. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - /** - * \file - * subnet module for unbound. - */ - -#include "config.h" - -#ifdef CLIENT_SUBNET /* keeps splint happy */ - -#include "edns-subnet/subnetmod.h" -#include "edns-subnet/edns-subnet.h" -#include "edns-subnet/addrtree.h" -#include "edns-subnet/subnet-whitelist.h" - -#include "services/mesh.h" -#include "services/cache/dns.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/storage/slabhash.h" -#include "util/config_file.h" -#include "util/data/msgreply.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "iterator/iter_utils.h" - -/** externally called */ -void -subnet_data_delete(void *d, void *ATTR_UNUSED(arg)) -{ - struct subnet_msg_cache_data *r; - r = (struct subnet_msg_cache_data*)d; - addrtree_delete(r->tree4); - addrtree_delete(r->tree6); - free(r); -} - -/** externally called */ -size_t -msg_cache_sizefunc(void *k, void *d) -{ - struct msgreply_entry *q = (struct msgreply_entry*)k; - struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d; - size_t s = sizeof(struct msgreply_entry) - + sizeof(struct subnet_msg_cache_data) - + q->key.qname_len + lock_get_mem(&q->entry.lock); - s += addrtree_size(r->tree4); - s += addrtree_size(r->tree6); - return s; -} - -/** new query for ecs module */ -static int -subnet_new_qstate(struct module_qstate *qstate, int id) -{ - struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc( - qstate->region, sizeof(struct subnet_qstate)); - if(!sq) - return 0; - qstate->minfo[id] = sq; - memset(sq, 0, sizeof(*sq)); - sq->started_no_cache_store = qstate->no_cache_store; - sq->started_no_cache_lookup = qstate->no_cache_lookup; - return 1; -} - -/** Add ecs struct to edns list, after parsing it to wire format. */ -void -subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list, - struct module_qstate *qstate, struct regional *region) -{ - size_t sn_octs, sn_octs_remainder; - sldns_buffer* buf = qstate->env->scratch_buffer; - - if(ecs->subnet_validdata) { - log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 || - ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6); - log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 || - ecs->subnet_source_mask <= INET_SIZE*8); - log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 || - ecs->subnet_source_mask <= INET6_SIZE*8); - - sn_octs = ecs->subnet_source_mask / 8; - sn_octs_remainder = - (size_t)((ecs->subnet_source_mask % 8)>0?1:0); - - log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE); - - sldns_buffer_clear(buf); - sldns_buffer_write_u16(buf, ecs->subnet_addr_fam); - sldns_buffer_write_u8(buf, ecs->subnet_source_mask); - sldns_buffer_write_u8(buf, ecs->subnet_scope_mask); - sldns_buffer_write(buf, ecs->subnet_addr, sn_octs); - if(sn_octs_remainder) - sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] & - ~(0xFF >> (ecs->subnet_source_mask % 8))); - sldns_buffer_flip(buf); - - edns_opt_list_append(list, - qstate->env->cfg->client_subnet_opcode, - sn_octs + sn_octs_remainder + 4, - sldns_buffer_begin(buf), region); - } -} - -int ecs_whitelist_check(struct query_info* qinfo, - uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), - struct regional *region, int id, void* ATTR_UNUSED(cbargs)) -{ - struct subnet_qstate *sq; - struct subnet_env *sn_env; - - if(!(sq=(struct subnet_qstate*)qstate->minfo[id])) - return 1; - sn_env = (struct subnet_env*)qstate->env->modinfo[id]; - - /* Cache by default, might be disabled after parsing EDNS option - * received from nameserver. */ - if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) { - qstate->no_cache_store = 0; - } - - if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream && - qstate->env->cfg->client_subnet_always_forward) || - ecs_is_whitelisted(sn_env->whitelist, - addr, addrlen, qinfo->qname, qinfo->qname_len, - qinfo->qclass))) { - /* Address on whitelist or client query contains ECS option, we - * want to sent out ECS. Only add option if it is not already - * set. */ - if(!edns_opt_list_find(qstate->edns_opts_back_out, - qstate->env->cfg->client_subnet_opcode)) { - subnet_ecs_opt_list_append(&sq->ecs_server_out, - &qstate->edns_opts_back_out, qstate, region); - } - sq->subnet_sent = 1; - } - else { - /* Outgoing ECS option is set, but we don't want to sent it to - * this address, remove option. */ - if(edns_opt_list_find(qstate->edns_opts_back_out, - qstate->env->cfg->client_subnet_opcode)) { - edns_opt_list_remove(&qstate->edns_opts_back_out, - qstate->env->cfg->client_subnet_opcode); - } - sq->subnet_sent = 0; - } - return 1; -} - - -void -subnet_markdel(void* key) -{ - struct msgreply_entry *e = (struct msgreply_entry*)key; - e->key.qtype = 0; - e->key.qclass = 0; -} - -int -subnetmod_init(struct module_env *env, int id) -{ - struct subnet_env *sn_env = (struct subnet_env*)calloc(1, - sizeof(struct subnet_env)); - if(!sn_env) { - log_err("malloc failure"); - return 0; - } - alloc_init(&sn_env->alloc, NULL, 0); - env->modinfo[id] = (void*)sn_env; - - /* Warn that serve-expired and prefetch do not work with the subnet - * module cache. */ - if(env->cfg->serve_expired) - log_warn( - "subnetcache: serve-expired is set but not working " - "for data originating from the subnet module cache."); - if(env->cfg->prefetch) - log_warn( - "subnetcache: prefetch is set but not working " - "for data originating from the subnet module cache."); - /* Copy msg_cache settings */ - sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs, - HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size, - msg_cache_sizefunc, query_info_compare, query_entry_delete, - subnet_data_delete, NULL); - slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel); - if(!sn_env->subnet_msg_cache) { - log_err("subnetcache: could not create cache"); - free(sn_env); - env->modinfo[id] = NULL; - return 0; - } - /* whitelist for edns subnet capable servers */ - sn_env->whitelist = ecs_whitelist_create(); - if(!sn_env->whitelist || - !ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) { - log_err("subnetcache: could not create ECS whitelist"); - slabhash_delete(sn_env->subnet_msg_cache); - free(sn_env); - env->modinfo[id] = NULL; - return 0; - } - - verbose(VERB_QUERY, "subnetcache: option registered (%d)", - env->cfg->client_subnet_opcode); - /* Create new mesh state for all queries. */ - env->unique_mesh = 1; - if(!edns_register_option(env->cfg->client_subnet_opcode, - env->cfg->client_subnet_always_forward /* bypass cache */, - 1 /* no aggregation */, env)) { - log_err("subnetcache: could not register opcode"); - ecs_whitelist_delete(sn_env->whitelist); - slabhash_delete(sn_env->subnet_msg_cache); - free(sn_env); - env->modinfo[id] = NULL; - return 0; - } - inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL, - env, id); - inplace_cb_register((void*)ecs_edns_back_parsed, - inplace_cb_edns_back_parsed, NULL, env, id); - inplace_cb_register((void*)ecs_query_response, - inplace_cb_query_response, NULL, env, id); - lock_rw_init(&sn_env->biglock); - return 1; -} - -void -subnetmod_deinit(struct module_env *env, int id) -{ - struct subnet_env *sn_env; - if(!env || !env->modinfo[id]) - return; - sn_env = (struct subnet_env*)env->modinfo[id]; - lock_rw_destroy(&sn_env->biglock); - inplace_cb_delete(env, inplace_cb_edns_back_parsed, id); - inplace_cb_delete(env, inplace_cb_query, id); - inplace_cb_delete(env, inplace_cb_query_response, id); - ecs_whitelist_delete(sn_env->whitelist); - slabhash_delete(sn_env->subnet_msg_cache); - alloc_clear(&sn_env->alloc); - free(sn_env); - env->modinfo[id] = NULL; -} - -/** Tells client that upstream has no/improper support */ -static void -cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source) -{ - target->subnet_scope_mask = 0; - target->subnet_source_mask = source->subnet_source_mask; - target->subnet_addr_fam = source->subnet_addr_fam; - memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE); - target->subnet_validdata = 1; -} - -static void -delfunc(void *envptr, void *elemptr) { - struct reply_info *elem = (struct reply_info *)elemptr; - struct subnet_env *env = (struct subnet_env *)envptr; - reply_info_parsedelete(elem, &env->alloc); -} - -static size_t -sizefunc(void *elemptr) { - struct reply_info *elem = (struct reply_info *)elemptr; - return sizeof (struct reply_info) - sizeof (struct rrset_ref) - + elem->rrset_count * sizeof (struct rrset_ref) - + elem->rrset_count * sizeof (struct ub_packed_rrset_key *); -} - -/** - * Select tree from cache entry based on edns data. - * If for address family not present it will create a new one. - * NULL on failure to create. */ -static struct addrtree* -get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns, - struct subnet_env *env, struct config_file* cfg) -{ - struct addrtree *tree; - if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { - if (!data->tree4) - data->tree4 = addrtree_create( - cfg->max_client_subnet_ipv4, &delfunc, - &sizefunc, env, cfg->max_ecs_tree_size_ipv4); - tree = data->tree4; - } else { - if (!data->tree6) - data->tree6 = addrtree_create( - cfg->max_client_subnet_ipv6, &delfunc, - &sizefunc, env, cfg->max_ecs_tree_size_ipv6); - tree = data->tree6; - } - return tree; -} - -static void -update_cache(struct module_qstate *qstate, int id) -{ - struct msgreply_entry *mrep_entry; - struct addrtree *tree; - struct reply_info *rep; - struct query_info qinf; - struct subnet_env *sne = qstate->env->modinfo[id]; - struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id]; - struct slabhash *subnet_msg_cache = sne->subnet_msg_cache; - struct ecs_data *edns = &sq->ecs_client_in; - size_t i; - int only_match_scope_zero; - - /* We already calculated hash upon lookup (lookup_and_reply) if we were - * allowed to look in the ECS cache */ - hashvalue_type h = qstate->minfo[id] && - ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated? - ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash : - query_info_hash(&qstate->qinfo, qstate->query_flags); - /* Step 1, general qinfo lookup */ - struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h, - &qstate->qinfo, 1); - int need_to_insert = (lru_entry == NULL); - if (!lru_entry) { - void* data = calloc(1, - sizeof(struct subnet_msg_cache_data)); - if(!data) { - log_err("malloc failed"); - return; - } - qinf = qstate->qinfo; - qinf.qname = memdup(qstate->qinfo.qname, - qstate->qinfo.qname_len); - if(!qinf.qname) { - free(data); - log_err("memdup failed"); - return; - } - mrep_entry = query_info_entrysetup(&qinf, data, h); - free(qinf.qname); /* if qname 'consumed', it is set to NULL */ - if (!mrep_entry) { - free(data); - log_err("query_info_entrysetup failed"); - return; - } - lru_entry = &mrep_entry->entry; - lock_rw_wrlock(&lru_entry->lock); - } - /* lru_entry->lock is locked regardless of how we got here, - * either from the slabhash_lookup, or above in the new allocated */ - /* Step 2, find the correct tree */ - if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) { - lock_rw_unlock(&lru_entry->lock); - log_err("subnetcache: cache insertion failed"); - return; - } - lock_quick_lock(&sne->alloc.lock); - rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL); - lock_quick_unlock(&sne->alloc.lock); - if (!rep) { - lock_rw_unlock(&lru_entry->lock); - log_err("subnetcache: cache insertion failed"); - return; - } - - /* store RRsets */ - for(i=0; irrset_count; i++) { - rep->ref[i].key = rep->rrsets[i]; - rep->ref[i].id = rep->rrsets[i]->id; - } - reply_info_set_ttls(rep, *qstate->env->now); - rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */ - rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */ - if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0) - only_match_scope_zero = 1; - else only_match_scope_zero = 0; - addrtree_insert(tree, (addrkey_t*)edns->subnet_addr, - edns->subnet_source_mask, sq->max_scope, rep, - rep->ttl, *qstate->env->now, only_match_scope_zero); - - lock_rw_unlock(&lru_entry->lock); - if (need_to_insert) { - slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data, - NULL); - } -} - -/** Lookup in cache and reply true iff reply is sent. */ -static int -lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch) -{ - struct lruhash_entry *e; - struct module_env *env = qstate->env; - struct subnet_env *sne = (struct subnet_env*)env->modinfo[id]; - hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags); - struct subnet_msg_cache_data *data; - struct ecs_data *ecs = &sq->ecs_client_in; - struct addrtree *tree; - struct addrnode *node; - uint8_t scope; - - memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out)); - - if (sq) { - sq->qinfo_hash = h; /* Might be useful on cache miss */ - sq->qinfo_hash_calculated = 1; - } - e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1); - if (!e) return 0; /* qinfo not in cache */ - data = e->data; - tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)? - data->tree4 : data->tree6; - if (!tree) { /* qinfo in cache but not for this family */ - lock_rw_unlock(&e->lock); - return 0; - } - node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr, - ecs->subnet_source_mask, *env->now); - if (!node) { /* plain old cache miss */ - lock_rw_unlock(&e->lock); - return 0; - } - - qstate->return_msg = tomsg(NULL, &qstate->qinfo, - (struct reply_info *)node->elem, qstate->region, *env->now, 0, - env->scratch); - scope = (uint8_t)node->scope; - lock_rw_unlock(&e->lock); - - if (!qstate->return_msg) { /* Failed allocation or expired TTL */ - return 0; - } - - if (sq->subnet_downstream) { /* relay to interested client */ - sq->ecs_client_out.subnet_scope_mask = scope; - sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam; - sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask; - memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr, - INET6_SIZE); - sq->ecs_client_out.subnet_validdata = 1; - } - - if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) { - qstate->need_refetch = 1; - } - return 1; -} - -/** - * Test first bits of addresses for equality. Caller is responsible - * for making sure that both a and b are at least net/8 octets long. - * @param a: first address. - * @param a: seconds address. - * @param net: Number of bits to test. - * @return: 1 if equal, 0 otherwise. - */ -static int -common_prefix(uint8_t *a, uint8_t *b, uint8_t net) -{ - size_t n = (size_t)net / 8; - return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]); -} - -static enum module_ext_state -eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) -{ - struct subnet_env *sne = qstate->env->modinfo[id]; - - struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */ - struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */ - struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */ - struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */ - - memset(c_out, 0, sizeof(*c_out)); - - if (!qstate->return_msg) { - /* already an answer and its not a message, but retain - * the actual rcode, instead of module_error, so send - * module_finished */ - return module_finished; - } - - /* We have not asked for subnet data */ - if (!sq->subnet_sent) { - if (s_in->subnet_validdata) - verbose(VERB_QUERY, "subnetcache: received spurious data"); - if (sq->subnet_downstream) /* Copy back to client */ - cp_edns_bad_response(c_out, c_in); - return module_finished; - } - - /* subnet sent but nothing came back */ - if (!s_in->subnet_validdata) { - /* The authority indicated no support for edns subnet. As a - * consequence the answer ended up in the regular cache. It - * is still useful to put it in the edns subnet cache for - * when a client explicitly asks for subnet specific answer. */ - verbose(VERB_QUERY, "subnetcache: Authority indicates no support"); - if(!sq->started_no_cache_store) { - lock_rw_wrlock(&sne->biglock); - update_cache(qstate, id); - lock_rw_unlock(&sne->biglock); - } - if (sq->subnet_downstream) - cp_edns_bad_response(c_out, c_in); - return module_finished; - } - - /* Being here means we have asked for and got a subnet specific - * answer. Also, the answer from the authority is not yet cached - * anywhere. */ - - /* can we accept response? */ - if(s_out->subnet_addr_fam != s_in->subnet_addr_fam || - s_out->subnet_source_mask != s_in->subnet_source_mask || - !common_prefix(s_out->subnet_addr, s_in->subnet_addr, - s_out->subnet_source_mask)) - { - /* we can not accept, restart query without option */ - verbose(VERB_QUERY, "subnetcache: forged data"); - s_out->subnet_validdata = 0; - (void)edns_opt_list_remove(&qstate->edns_opts_back_out, - qstate->env->cfg->client_subnet_opcode); - sq->subnet_sent = 0; - return module_restart_next; - } - - lock_rw_wrlock(&sne->biglock); - if(!sq->started_no_cache_store) { - update_cache(qstate, id); - } - sne->num_msg_nocache++; - lock_rw_unlock(&sne->biglock); - - if (sq->subnet_downstream) { - /* Client wants to see the answer, echo option back - * and adjust the scope. */ - c_out->subnet_addr_fam = c_in->subnet_addr_fam; - c_out->subnet_source_mask = c_in->subnet_source_mask; - memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE); - c_out->subnet_scope_mask = sq->max_scope; - /* Limit scope returned to client to scope used for caching. */ - if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { - if(c_out->subnet_scope_mask > - qstate->env->cfg->max_client_subnet_ipv4) { - c_out->subnet_scope_mask = - qstate->env->cfg->max_client_subnet_ipv4; - } - } - else if(c_out->subnet_scope_mask > - qstate->env->cfg->max_client_subnet_ipv6) { - c_out->subnet_scope_mask = - qstate->env->cfg->max_client_subnet_ipv6; - } - c_out->subnet_validdata = 1; - } - return module_finished; -} - -/** Parse EDNS opt data containing ECS */ -static int -parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs) -{ - memset(ecs, 0, sizeof(*ecs)); - if (ecs_option->opt_len < 4) - return 0; - - ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data); - ecs->subnet_source_mask = ecs_option->opt_data[2]; - ecs->subnet_scope_mask = ecs_option->opt_data[3]; - /* remaining bytes indicate address */ - - /* validate input*/ - /* option length matches calculated length? */ - if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4)) - return 0; - if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0) - return 0; - if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { - if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32) - return 0; - } else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) { - if (ecs->subnet_source_mask > 128 || - ecs->subnet_scope_mask > 128) - return 0; - } else - return 0; - - /* valid ECS data, write to ecs_data */ - if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4, - ecs_option->opt_len - 4, ecs->subnet_source_mask)) - return 0; - ecs->subnet_validdata = 1; - return 1; -} - -void -subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, - struct config_file* cfg) -{ - void* sinaddr; - - /* Construct subnet option from original query */ - if(((struct sockaddr_in*)ss)->sin_family == AF_INET) { - ecs->subnet_source_mask = cfg->max_client_subnet_ipv4; - ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4; - sinaddr = &((struct sockaddr_in*)ss)->sin_addr; - if (!copy_clear( ecs->subnet_addr, INET6_SIZE, - (uint8_t *)sinaddr, INET_SIZE, - ecs->subnet_source_mask)) { - ecs->subnet_validdata = 1; - } - } -#ifdef INET6 - else { - ecs->subnet_source_mask = cfg->max_client_subnet_ipv6; - ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6; - sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr; - if (!copy_clear( ecs->subnet_addr, INET6_SIZE, - (uint8_t *)sinaddr, INET6_SIZE, - ecs->subnet_source_mask)) { - ecs->subnet_validdata = 1; - } - } -#else - /* We don't know how to handle ip6, just pass */ -#endif /* INET6 */ -} - -int -ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, - int id, void* ATTR_UNUSED(cbargs)) -{ - struct subnet_qstate *sq; - - if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id])) - return 1; - - if(sq->subnet_sent && - FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) { - /* REFUSED response to ECS query, remove ECS option. */ - edns_opt_list_remove(&qstate->edns_opts_back_out, - qstate->env->cfg->client_subnet_opcode); - sq->subnet_sent = 0; - memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out)); - } else if (!sq->track_max_scope && - FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR && - response->rep->an_numrrsets > 0 - ) { - struct ub_packed_rrset_key* s = response->rep->rrsets[0]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(qstate->qinfo.qname, - s->rk.dname) == 0) { - /* CNAME response for QNAME. From now on keep track of - * longest received ECS prefix for all queries on this - * qstate. */ - sq->track_max_scope = 1; - } - } - return 1; -} - -/** verbose print edns subnet option in pretty print */ -static void -subnet_log_print(const char* s, struct edns_option* ecs_opt) -{ - if(verbosity >= VERB_ALGO) { - char buf[256]; - char* str = buf; - size_t str_len = sizeof(buf); - if(!ecs_opt) { - verbose(VERB_ALGO, "%s (null)", s); - return; - } - (void)sldns_wire2str_edns_subnet_print(&str, &str_len, - ecs_opt->opt_data, ecs_opt->opt_len); - verbose(VERB_ALGO, "%s %s", s, buf); - } -} - -int -ecs_edns_back_parsed(struct module_qstate* qstate, int id, - void* ATTR_UNUSED(cbargs)) -{ - struct subnet_qstate *sq; - struct edns_option* ecs_opt; - - if(!(sq=(struct subnet_qstate*)qstate->minfo[id])) - return 1; - if((ecs_opt = edns_opt_list_find( - qstate->edns_opts_back_in, - qstate->env->cfg->client_subnet_opcode)) && - parse_subnet_option(ecs_opt, &sq->ecs_server_in) && - sq->subnet_sent && sq->ecs_server_in.subnet_validdata) { - subnet_log_print("answer has edns subnet", ecs_opt); - /* Only skip global cache store if we sent an ECS option - * and received one back. Answers from non-whitelisted - * servers will end up in global cache. Answers for - * queries with 0 source will not (unless nameserver - * does not support ECS). */ - qstate->no_cache_store = 1; - if(!sq->track_max_scope || (sq->track_max_scope && - sq->ecs_server_in.subnet_scope_mask > - sq->max_scope)) - sq->max_scope = sq->ecs_server_in.subnet_scope_mask; - } - - return 1; -} - -void -subnetmod_operate(struct module_qstate *qstate, enum module_ev event, - int id, struct outbound_entry* outbound) -{ - struct subnet_env *sne = qstate->env->modinfo[id]; - struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id]; - - verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s " - "event:%s", id, strextstate(qstate->ext_state[id]), - strmodulevent(event)); - log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo); - - if((event == module_event_new || event == module_event_pass) && - sq == NULL) { - struct edns_option* ecs_opt; - if(!subnet_new_qstate(qstate, id)) { - qstate->return_msg = NULL; - qstate->ext_state[id] = module_finished; - return; - } - - sq = (struct subnet_qstate*)qstate->minfo[id]; - - if((ecs_opt = edns_opt_list_find( - qstate->edns_opts_front_in, - qstate->env->cfg->client_subnet_opcode))) { - if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) { - /* Wrongly formatted ECS option. RFC mandates to - * return FORMERROR. */ - qstate->return_rcode = LDNS_RCODE_FORMERR; - qstate->ext_state[id] = module_finished; - return; - } - subnet_log_print("query has edns subnet", ecs_opt); - sq->subnet_downstream = 1; - } - else if(qstate->mesh_info->reply_list) { - subnet_option_from_ss( - &qstate->mesh_info->reply_list->query_reply.client_addr, - &sq->ecs_client_in, qstate->env->cfg); - } - else if(qstate->client_addr.ss_family != AF_UNSPEC) { - subnet_option_from_ss( - &qstate->client_addr, - &sq->ecs_client_in, qstate->env->cfg); - } - - if(sq->ecs_client_in.subnet_validdata == 0) { - /* No clients are interested in result or we could not - * parse it, we don't do client subnet */ - sq->ecs_server_out.subnet_validdata = 0; - verbose(VERB_ALGO, "subnetcache: pass to next module"); - qstate->ext_state[id] = module_wait_module; - return; - } - - /* Limit to minimum allowed source mask */ - if(sq->ecs_client_in.subnet_source_mask != 0 && ( - (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 && - sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) || - (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 && - sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) { - qstate->return_rcode = LDNS_RCODE_REFUSED; - qstate->ext_state[id] = module_finished; - return; - } - - if(!sq->started_no_cache_lookup && !qstate->blacklist) { - lock_rw_wrlock(&sne->biglock); - if(qstate->mesh_info->reply_list && - lookup_and_reply(qstate, id, sq, - qstate->env->cfg->prefetch)) { - sne->num_msg_cache++; - lock_rw_unlock(&sne->biglock); - verbose(VERB_QUERY, "subnetcache: answered from cache"); - qstate->ext_state[id] = module_finished; - - subnet_ecs_opt_list_append(&sq->ecs_client_out, - &qstate->edns_opts_front_out, qstate, - qstate->region); - if(verbosity >= VERB_ALGO) { - subnet_log_print("reply has edns subnet", - edns_opt_list_find( - qstate->edns_opts_front_out, - qstate->env->cfg-> - client_subnet_opcode)); - } - return; - } - lock_rw_unlock(&sne->biglock); - } - - sq->ecs_server_out.subnet_addr_fam = - sq->ecs_client_in.subnet_addr_fam; - sq->ecs_server_out.subnet_source_mask = - sq->ecs_client_in.subnet_source_mask; - /* Limit source prefix to configured maximum */ - if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 - && sq->ecs_server_out.subnet_source_mask > - qstate->env->cfg->max_client_subnet_ipv4) - sq->ecs_server_out.subnet_source_mask = - qstate->env->cfg->max_client_subnet_ipv4; - else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 - && sq->ecs_server_out.subnet_source_mask > - qstate->env->cfg->max_client_subnet_ipv6) - sq->ecs_server_out.subnet_source_mask = - qstate->env->cfg->max_client_subnet_ipv6; - /* Safe to copy completely, even if the source is limited by the - * configuration. subnet_ecs_opt_list_append() will limit the address. - * */ - memcpy(&sq->ecs_server_out.subnet_addr, - sq->ecs_client_in.subnet_addr, INET6_SIZE); - sq->ecs_server_out.subnet_scope_mask = 0; - sq->ecs_server_out.subnet_validdata = 1; - if(sq->ecs_server_out.subnet_source_mask != 0 && - qstate->env->cfg->client_subnet_always_forward && - sq->subnet_downstream) - /* ECS specific data required, do not look at the global - * cache in other modules. */ - qstate->no_cache_lookup = 1; - - /* pass request to next module */ - verbose(VERB_ALGO, - "subnetcache: not found in cache. pass to next module"); - qstate->ext_state[id] = module_wait_module; - return; - } - /* Query handed back by next module, we have a 'final' answer */ - if(sq && event == module_event_moddone) { - qstate->ext_state[id] = eval_response(qstate, id, sq); - if(qstate->ext_state[id] == module_finished && - qstate->return_msg) { - subnet_ecs_opt_list_append(&sq->ecs_client_out, - &qstate->edns_opts_front_out, qstate, - qstate->region); - if(verbosity >= VERB_ALGO) { - subnet_log_print("reply has edns subnet", - edns_opt_list_find( - qstate->edns_opts_front_out, - qstate->env->cfg-> - client_subnet_opcode)); - } - } - qstate->no_cache_store = sq->started_no_cache_store; - qstate->no_cache_lookup = sq->started_no_cache_lookup; - return; - } - if(sq && outbound) { - return; - } - /* We are being revisited */ - if(event == module_event_pass || event == module_event_new) { - /* Just pass it on, we already did the work */ - verbose(VERB_ALGO, "subnetcache: pass to next module"); - qstate->ext_state[id] = module_wait_module; - return; - } - if(!sq && (event == module_event_moddone)) { - /* during priming, module done but we never started */ - qstate->ext_state[id] = module_finished; - return; - } - log_err("subnetcache: bad event %s", strmodulevent(event)); - qstate->ext_state[id] = module_error; - return; -} - -void -subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate), - int ATTR_UNUSED(id)) -{ - /* qstate has no data outside region */ -} - -void -subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate), - int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) -{ - /* Not used */ -} - -size_t -subnetmod_get_mem(struct module_env *env, int id) -{ - struct subnet_env *sn_env = env->modinfo[id]; - if (!sn_env) return 0; - return sizeof(*sn_env) + - slabhash_get_mem(sn_env->subnet_msg_cache) + - ecs_whitelist_get_mem(sn_env->whitelist); -} - -/** - * The module function block - */ -static struct module_func_block subnetmod_block = { - "subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate, - &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem -}; - -struct module_func_block* -subnetmod_get_funcblock(void) -{ - return &subnetmod_block; -} - -/** Wrappers for static functions to unit test */ -size_t -unittest_wrapper_subnetmod_sizefunc(void *elemptr) -{ - return sizefunc(elemptr); -} - -#endif /* CLIENT_SUBNET */ diff --git a/crates/libunbound-sys/unbound/edns-subnet/subnetmod.h b/crates/libunbound-sys/unbound/edns-subnet/subnetmod.h deleted file mode 100644 index f0bcaad3..00000000 --- a/crates/libunbound-sys/unbound/edns-subnet/subnetmod.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * edns-subnet/subnetmod.h - edns subnet module. Must be called before validator - * and iterator. - * - * Copyright (c) 2013, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * subnet module for unbound. - */ - -#ifndef SUBNETMOD_H -#define SUBNETMOD_H -#include "util/module.h" -#include "services/outbound_list.h" -#include "util/alloc.h" -#include "util/net_help.h" -#include "util/storage/slabhash.h" -#include "util/data/dname.h" -#include "edns-subnet/addrtree.h" -#include "edns-subnet/edns-subnet.h" - -/** - * Global state for the subnet module. - */ -struct subnet_env { - /** shared message cache - * key: struct query_info* - * data: struct subnet_msg_cache_data* */ - struct slabhash* subnet_msg_cache; - /** access control, which upstream servers we send client address */ - struct ecs_whitelist* whitelist; - /** allocation service */ - struct alloc_cache alloc; - lock_rw_type biglock; - /** number of messages from cache */ - size_t num_msg_cache; - /** number of messages not from cache */ - size_t num_msg_nocache; -}; - -struct subnet_msg_cache_data { - struct addrtree* tree4; - struct addrtree* tree6; -}; - -struct subnet_qstate { - /** We need the hash for both cache lookup and insert */ - hashvalue_type qinfo_hash; - int qinfo_hash_calculated; - /** ecs_data for client communication */ - struct ecs_data ecs_client_in; - struct ecs_data ecs_client_out; - /** ecss data for server communication */ - struct ecs_data ecs_server_in; - struct ecs_data ecs_server_out; - int subnet_downstream; - int subnet_sent; - /** keep track of longest received scope, set after receiving CNAME for - * incoming QNAME. */ - int track_max_scope; - /** longest received scope mask since track_max_scope is set. This value - * is used for caching and answereing to client. */ - uint8_t max_scope; - /** has the subnet module been started with no_cache_store? */ - int started_no_cache_store; - /** has the subnet module been started with no_cache_lookup? */ - int started_no_cache_lookup; -}; - -void subnet_data_delete(void* d, void* ATTR_UNUSED(arg)); -size_t msg_cache_sizefunc(void* k, void* d); - -/** - * Get the module function block. - * @return: function block with function pointers to module methods. - */ -struct module_func_block* subnetmod_get_funcblock(void); - -/** subnet module init */ -int subnetmod_init(struct module_env* env, int id); - -/** subnet module deinit */ -void subnetmod_deinit(struct module_env* env, int id); - -/** subnet module operate on a query */ -void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); - -/** subnet module */ -void subnetmod_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** subnet module cleanup query state */ -void subnetmod_clear(struct module_qstate* qstate, int id); - -/** subnet module alloc size routine */ -size_t subnetmod_get_mem(struct module_env* env, int id); - -/** Wrappers for static functions to unit test */ -size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr); - -/** Whitelist check, called just before query is sent upstream. */ -int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags, - struct module_qstate* qstate, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - struct regional* region, int id, void* cbargs); - -/** Check whether response from server contains ECS record, if so, skip cache - * store. Called just after parsing EDNS data from server. */ -int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs); - -/** Remove ECS record from back_out when query resulted in REFUSED response. */ -int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, - int id, void* cbargs); - -/** mark subnet msg to be deleted */ -void subnet_markdel(void* key); - -/** Add ecs struct to edns list, after parsing it to wire format. */ -void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list, - struct module_qstate *qstate, struct regional *region); - -/** Create ecs_data from the sockaddr_storage information. */ -void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, - struct config_file* cfg); -#endif /* SUBNETMOD_H */ diff --git a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.c b/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.c deleted file mode 100644 index c2b1f5d4..00000000 --- a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to - * operate on. - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * - * Keep track of the white listed domains for ipsecmod. - */ - -#include "config.h" - -#ifdef USE_IPSECMOD -#include "ipsecmod/ipsecmod.h" -#include "ipsecmod/ipsecmod-whitelist.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/rbtree.h" -#include "util/data/dname.h" -#include "util/storage/dnstree.h" -#include "sldns/str2wire.h" - -/** Apply ipsecmod-whitelist string. */ -static int -whitelist_str_cfg(rbtree_type* whitelist, const char* name) -{ - struct name_tree_node* n; - size_t len; - uint8_t* nm = sldns_str2wire_dname(name, &len); - if(!nm) { - log_err("ipsecmod: could not parse %s for whitelist.", name); - return 0; - } - n = (struct name_tree_node*)calloc(1, sizeof(*n)); - if(!n) { - log_err("ipsecmod: out of memory while creating whitelist."); - free(nm); - return 0; - } - n->node.key = n; - n->name = nm; - n->len = len; - n->labs = dname_count_labels(nm); - n->dclass = LDNS_RR_CLASS_IN; - if(!name_tree_insert(whitelist, n, nm, len, n->labs, n->dclass)) { - /* duplicate element ignored, idempotent */ - free(n->name); - free(n); - } - return 1; -} - -/** Read ipsecmod-whitelist config. */ -static int -read_whitelist(rbtree_type* whitelist, struct config_file* cfg) -{ - struct config_strlist* p; - for(p = cfg->ipsecmod_whitelist; p; p = p->next) { - log_assert(p->str); - if(!whitelist_str_cfg(whitelist, p->str)) - return 0; - } - return 1; -} - -int -ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie, - struct config_file* cfg) -{ - ie->whitelist = rbtree_create(name_tree_compare); - if(!read_whitelist(ie->whitelist, cfg)) - return 0; - name_tree_init_parents(ie->whitelist); - return 1; -} - -/** Delete ipsecmod_env->whitelist element. */ -static void -whitelist_free(struct rbnode_type* n, void* ATTR_UNUSED(d)) -{ - if(n) { - free(((struct name_tree_node*)n)->name); - free(n); - } -} - -/** Get memory usage of ipsecmod_env->whitelist element. */ -static void -whitelist_get_mem(struct rbnode_type* n, void* arg) -{ - struct name_tree_node* node = (struct name_tree_node*)n; - size_t* size = (size_t*) arg; - if(node) { - *size += sizeof(node) + node->len; - } -} - -void -ipsecmod_whitelist_delete(rbtree_type* whitelist) -{ - if(whitelist) { - traverse_postorder(whitelist, whitelist_free, NULL); - free(whitelist); - } -} - -int -ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname, - size_t dname_len, uint16_t qclass) -{ - if(!ie->whitelist) return 1; /* No whitelist, treat as whitelisted. */ - return name_tree_lookup(ie->whitelist, dname, dname_len, - dname_count_labels(dname), qclass) != NULL; -} - -size_t -ipsecmod_whitelist_get_mem(rbtree_type* whitelist) -{ - size_t size = 0; - if(whitelist) { - traverse_postorder(whitelist, whitelist_get_mem, &size); - } - return size; -} - -#endif /* USE_IPSECMOD */ diff --git a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.h b/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.h deleted file mode 100644 index d9886881..00000000 --- a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod-whitelist.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to - * operate on. - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * - * Keep track of the white listed domains for ipsecmod. - */ - -#ifndef IPSECMOD_WHITELIST_H -#define IPSECMOD_WHITELIST_H -#include "util/storage/dnstree.h" - -struct config_file; -struct regional; - -/** - * Process ipsecmod_whitelist config. - * @param ie: ipsecmod environment. - * @param cfg: config options. - * @return 0 on error. - */ -int ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie, - struct config_file* cfg); - -/** - * Delete the ipsecmod whitelist. - * @param whitelist: ipsecmod whitelist. - */ -void ipsecmod_whitelist_delete(rbtree_type* whitelist); - -/** - * See if a domain is whitelisted. - * @param ie: ipsecmod environment. - * @param dname: domain name to check. - * @param dname_len: length of domain name. - * @param qclass: query CLASS. - * @return: true if the domain is whitelisted for the ipsecmod. - */ -int ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname, - size_t dname_len, uint16_t qclass); - -/** - * Get memory used by ipsecmod whitelist. - * @param whitelist: structure for domain storage. - * @return bytes in use. - */ -size_t ipsecmod_whitelist_get_mem(rbtree_type* whitelist); - -#endif /* IPSECMOD_WHITELIST_H */ diff --git a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.c b/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.c deleted file mode 100644 index 19549d4e..00000000 --- a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * ipsecmod/ipsecmod.c - facilitate opportunistic IPsec module - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that facilitates opportunistic IPsec. It does so - * by also querying for the IPSECKEY for A/AAAA queries and calling a - * configurable hook (eg. signaling an IKE daemon) before replying. - */ - -#include "config.h" -#ifdef USE_IPSECMOD -#include "ipsecmod/ipsecmod.h" -#include "ipsecmod/ipsecmod-whitelist.h" -#include "util/fptr_wlist.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "services/cache/dns.h" -#include "sldns/wire2str.h" - -/** Apply configuration to ipsecmod module 'global' state. */ -static int -ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg) -{ - if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) { - log_err("ipsecmod: missing ipsecmod-hook."); - return 0; - } - if(cfg->ipsecmod_whitelist && - !ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg)) - return 0; - return 1; -} - -int -ipsecmod_init(struct module_env* env, int id) -{ - struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1, - sizeof(struct ipsecmod_env)); - if(!ipsecmod_env) { - log_err("malloc failure"); - return 0; - } - env->modinfo[id] = (void*)ipsecmod_env; - ipsecmod_env->whitelist = NULL; - if(!ipsecmod_apply_cfg(ipsecmod_env, env->cfg)) { - log_err("ipsecmod: could not apply configuration settings."); - return 0; - } - return 1; -} - -void -ipsecmod_deinit(struct module_env* env, int id) -{ - struct ipsecmod_env* ipsecmod_env; - if(!env || !env->modinfo[id]) - return; - ipsecmod_env = (struct ipsecmod_env*)env->modinfo[id]; - /* Free contents. */ - ipsecmod_whitelist_delete(ipsecmod_env->whitelist); - free(ipsecmod_env); - env->modinfo[id] = NULL; -} - -/** New query for ipsecmod. */ -static int -ipsecmod_new(struct module_qstate* qstate, int id) -{ - struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc( - qstate->region, sizeof(struct ipsecmod_qstate)); - qstate->minfo[id] = iq; - if(!iq) - return 0; - /* Initialise it. */ - memset(iq, 0, sizeof(*iq)); - iq->enabled = qstate->env->cfg->ipsecmod_enabled; - iq->is_whitelisted = ipsecmod_domain_is_whitelisted( - (struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname, - qstate->qinfo.qname_len, qstate->qinfo.qclass); - return 1; -} - -/** - * Exit module with an error status. - * @param qstate: query state - * @param id: module id. - */ -static void -ipsecmod_error(struct module_qstate* qstate, int id) -{ - qstate->ext_state[id] = module_error; - qstate->return_rcode = LDNS_RCODE_SERVFAIL; -} - -/** - * Generate a request for the IPSECKEY. - * - * @param qstate: query state that is the parent. - * @param id: module id. - * @param name: what name to query for. - * @param namelen: length of name. - * @param qtype: query type. - * @param qclass: query class. - * @param flags: additional flags, such as the CD bit (BIT_CD), or 0. - * @return false on alloc failure. - */ -static int -generate_request(struct module_qstate* qstate, int id, uint8_t* name, - size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags) -{ - struct module_qstate* newq; - struct query_info ask; - ask.qname = name; - ask.qname_len = namelen; - ask.qtype = qtype; - ask.qclass = qclass; - ask.local_alias = NULL; - log_query_info(VERB_ALGO, "ipsecmod: generate request", &ask); - - /* Explicitly check for cycle before trying to attach. Will result in - * cleaner error message. The attach_sub code also checks for cycle but the - * message will be out of memory in both cases then. */ - fptr_ok(fptr_whitelist_modenv_detect_cycle(qstate->env->detect_cycle)); - if((*qstate->env->detect_cycle)(qstate, &ask, - (uint16_t)(BIT_RD|flags), 0, 0)) { - verbose(VERB_ALGO, "Could not generate request: cycle detected"); - return 0; - } - - fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &ask, - (uint16_t)(BIT_RD|flags), 0, 0, &newq)){ - log_err("Could not generate request: out of memory"); - return 0; - } - qstate->ext_state[id] = module_wait_subquery; - return 1; -} - -/** - * Check if the string passed is a valid domain name with safe characters to - * pass to a shell. - * This will only allow: - * - digits - * - alphas - * - hyphen (not at the start) - * - dot (not at the start, or the only character) - * - underscore - * @param s: pointer to the string. - * @param slen: string's length. - * @return true if s only contains safe characters; false otherwise. - */ -static int -domainname_has_safe_characters(char* s, size_t slen) { - size_t i; - for(i = 0; i < slen; i++) { - if(s[i] == '\0') return 1; - if((s[i] == '-' && i != 0) - || (s[i] == '.' && (i != 0 || s[1] == '\0')) - || (s[i] == '_') || (s[i] >= '0' && s[i] <= '9') - || (s[i] >= 'A' && s[i] <= 'Z') - || (s[i] >= 'a' && s[i] <= 'z')) { - continue; - } - return 0; - } - return 1; -} - -/** - * Check if the stringified IPSECKEY RDATA contains safe characters to pass to - * a shell. - * This is only relevant for checking the gateway when the gateway type is 3 - * (domainname). - * @param s: pointer to the string. - * @param slen: string's length. - * @return true if s contains only safe characters; false otherwise. - */ -static int -ipseckey_has_safe_characters(char* s, size_t slen) { - int precedence, gateway_type, algorithm; - char* gateway; - gateway = (char*)calloc(slen, sizeof(char)); - if(!gateway) { - log_err("ipsecmod: out of memory when calling the hook"); - return 0; - } - if(sscanf(s, "%d %d %d %s ", - &precedence, &gateway_type, &algorithm, gateway) != 4) { - free(gateway); - return 0; - } - if(gateway_type != 3) { - free(gateway); - return 1; - } - if(domainname_has_safe_characters(gateway, slen)) { - free(gateway); - return 1; - } - free(gateway); - return 0; -} - -/** - * Prepare the data and call the hook. - * - * @param qstate: query state. - * @param iq: ipsecmod qstate. - * @param ie: ipsecmod environment. - * @return true on success, false otherwise. - */ -static int -call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq, - struct ipsecmod_env* ATTR_UNUSED(ie)) -{ - size_t slen, tempdata_len, tempstring_len, i; - char str[65535], *s, *tempstring; - int w = 0, w_temp, qtype; - struct ub_packed_rrset_key* rrset_key; - struct packed_rrset_data* rrset_data; - uint8_t *tempdata; - - /* Check if a shell is available */ - if(system(NULL) == 0) { - log_err("ipsecmod: no shell available for ipsecmod-hook"); - return 0; - } - - /* Zero the buffer. */ - s = str; - slen = sizeof(str); - memset(s, 0, slen); - - /* Copy the hook into the buffer. */ - w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook); - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - /* Copy the qname into the buffer. */ - tempstring = sldns_wire2str_dname(qstate->qinfo.qname, - qstate->qinfo.qname_len); - if(!tempstring) { - log_err("ipsecmod: out of memory when calling the hook"); - return 0; - } - if(!domainname_has_safe_characters(tempstring, strlen(tempstring))) { - log_err("ipsecmod: qname has unsafe characters"); - free(tempstring); - return 0; - } - w += sldns_str_print(&s, &slen, "\"%s\"", tempstring); - free(tempstring); - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - /* Copy the IPSECKEY TTL into the buffer. */ - rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; - w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl); - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo, - qstate->return_msg->rep); - /* Double check that the records are indeed A/AAAA. - * This should never happen as this function is only executed for A/AAAA - * queries but make sure we don't pass anything other than A/AAAA to the - * shell. */ - qtype = ntohs(rrset_key->rk.type); - if(qtype != LDNS_RR_TYPE_AAAA && qtype != LDNS_RR_TYPE_A) { - log_err("ipsecmod: Answer is not of A or AAAA type"); - return 0; - } - rrset_data = (struct packed_rrset_data*)rrset_key->entry.data; - /* Copy the A/AAAA record(s) into the buffer. Start and end this section - * with a double quote. */ - w += sldns_str_print(&s, &slen, "\""); - for(i=0; icount; i++) { - if(i > 0) { - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - } - /* Ignore the first two bytes, they are the rr_data len. */ - w_temp = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2, - rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype); - if(w_temp < 0) { - /* Error in printout. */ - log_err("ipsecmod: Error in printing IP address"); - return 0; - } else if((size_t)w_temp >= slen) { - s = NULL; /* We do not want str to point outside of buffer. */ - slen = 0; - log_err("ipsecmod: shell command too long"); - return 0; - } else { - s += w_temp; - slen -= w_temp; - w += w_temp; - } - } - w += sldns_str_print(&s, &slen, "\""); - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - /* Copy the IPSECKEY record(s) into the buffer. Start and end this section - * with a double quote. */ - w += sldns_str_print(&s, &slen, "\""); - rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; - for(i=0; icount; i++) { - if(i > 0) { - /* Put space into the buffer. */ - w += sldns_str_print(&s, &slen, " "); - } - /* Ignore the first two bytes, they are the rr_data len. */ - tempdata = rrset_data->rr_data[i] + 2; - tempdata_len = rrset_data->rr_len[i] - 2; - /* Save the buffer pointers. */ - tempstring = s; tempstring_len = slen; - w_temp = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, - &slen, NULL, 0, NULL); - /* There was an error when parsing the IPSECKEY; reset the buffer - * pointers to their previous values. */ - if(w_temp == -1) { - s = tempstring; slen = tempstring_len; - } else if(w_temp > 0) { - if(!ipseckey_has_safe_characters( - tempstring, tempstring_len - slen)) { - log_err("ipsecmod: ipseckey has unsafe characters"); - return 0; - } - w += w_temp; - } - } - w += sldns_str_print(&s, &slen, "\""); - if(w >= (int)sizeof(str)) { - log_err("ipsecmod: shell command too long"); - return 0; - } - verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str); - /* ipsecmod-hook should return 0 on success. */ - if(system(str) != 0) - return 0; - return 1; -} - -/** - * Handle an ipsecmod module event with a query - * @param qstate: query state (from the mesh), passed between modules. - * contains qstate->env module environment with global caches and so on. - * @param iq: query state specific for this module. per-query. - * @param ie: environment specific for this module. global. - * @param id: module id. - */ -static void -ipsecmod_handle_query(struct module_qstate* qstate, - struct ipsecmod_qstate* iq, struct ipsecmod_env* ie, int id) -{ - struct ub_packed_rrset_key* rrset_key; - struct packed_rrset_data* rrset_data; - size_t i; - /* Pass to next module if we are not enabled and whitelisted. */ - if(!(iq->enabled && iq->is_whitelisted)) { - qstate->ext_state[id] = module_wait_module; - return; - } - /* New query, check if the query is for an A/AAAA record and disable - * caching for other modules. */ - if(!iq->ipseckey_done) { - if(qstate->qinfo.qtype == LDNS_RR_TYPE_A || - qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { - char type[16]; - sldns_wire2str_type_buf(qstate->qinfo.qtype, type, - sizeof(type)); - verbose(VERB_ALGO, "ipsecmod: query for %s; engaging", - type); - qstate->no_cache_store = 1; - } - /* Pass request to next module. */ - qstate->ext_state[id] = module_wait_module; - return; - } - /* IPSECKEY subquery is finished. */ - /* We have an IPSECKEY answer. */ - if(iq->ipseckey_rrset) { - rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; - if(rrset_data) { - /* If bogus return SERVFAIL. */ - if(!qstate->env->cfg->ipsecmod_ignore_bogus && - rrset_data->security == sec_status_bogus) { - log_err("ipsecmod: bogus IPSECKEY"); - errinf(qstate, "ipsecmod: bogus IPSECKEY"); - ipsecmod_error(qstate, id); - return; - } - /* We have a valid IPSECKEY reply, call hook. */ - if(!call_hook(qstate, iq, ie) && - qstate->env->cfg->ipsecmod_strict) { - log_err("ipsecmod: ipsecmod-hook failed"); - errinf(qstate, "ipsecmod: ipsecmod-hook failed"); - ipsecmod_error(qstate, id); - return; - } - /* Make sure the A/AAAA's TTL is equal/less than the - * ipsecmod_max_ttl. */ - rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo, - qstate->return_msg->rep); - rrset_data = (struct packed_rrset_data*)rrset_key->entry.data; - if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) { - /* Update TTL for rrset to fixed value. */ - rrset_data->ttl = qstate->env->cfg->ipsecmod_max_ttl; - for(i=0; icount+rrset_data->rrsig_count; i++) - rrset_data->rr_ttl[i] = qstate->env->cfg->ipsecmod_max_ttl; - /* Also update reply_info's TTL */ - if(qstate->return_msg->rep->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) { - qstate->return_msg->rep->ttl = - qstate->env->cfg->ipsecmod_max_ttl; - qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC( - qstate->return_msg->rep->ttl); - qstate->return_msg->rep->serve_expired_ttl = qstate->return_msg->rep->ttl + - qstate->env->cfg->serve_expired_ttl; - } - } - } - } - /* Store A/AAAA in cache. */ - if(!dns_cache_store(qstate->env, &qstate->qinfo, - qstate->return_msg->rep, 0, qstate->prefetch_leeway, - 0, qstate->region, qstate->query_flags, qstate->qstarttime)) { - log_err("ipsecmod: out of memory caching record"); - } - qstate->ext_state[id] = module_finished; -} - -/** - * Handle an ipsecmod module event with a response from the iterator. - * @param qstate: query state (from the mesh), passed between modules. - * contains qstate->env module environment with global caches and so on. - * @param iq: query state specific for this module. per-query. - * @param ie: environment specific for this module. global. - * @param id: module id. - */ -static void -ipsecmod_handle_response(struct module_qstate* qstate, - struct ipsecmod_qstate* ATTR_UNUSED(iq), - struct ipsecmod_env* ATTR_UNUSED(ie), int id) -{ - /* Pass to previous module if we are not enabled and whitelisted. */ - if(!(iq->enabled && iq->is_whitelisted)) { - qstate->ext_state[id] = module_finished; - return; - } - /* check if the response is for an A/AAAA query. */ - if((qstate->qinfo.qtype == LDNS_RR_TYPE_A || - qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) && - /* check that we had an answer for the A/AAAA query. */ - qstate->return_msg && - reply_find_answer_rrset(&qstate->return_msg->qinfo, - qstate->return_msg->rep) && - /* check that another module didn't SERVFAIL. */ - qstate->return_rcode == LDNS_RCODE_NOERROR) { - char type[16]; - sldns_wire2str_type_buf(qstate->qinfo.qtype, type, - sizeof(type)); - verbose(VERB_ALGO, "ipsecmod: response for %s; generating IPSECKEY " - "subquery", type); - /* generate an IPSECKEY query. */ - if(!generate_request(qstate, id, qstate->qinfo.qname, - qstate->qinfo.qname_len, LDNS_RR_TYPE_IPSECKEY, - qstate->qinfo.qclass, 0)) { - log_err("ipsecmod: could not generate subquery."); - errinf(qstate, "ipsecmod: could not generate subquery."); - ipsecmod_error(qstate, id); - } - return; - } - /* we are done with the query. */ - qstate->ext_state[id] = module_finished; -} - -void -ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct ipsecmod_env* ie = (struct ipsecmod_env*)qstate->env->modinfo[id]; - struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)qstate->minfo[id]; - verbose(VERB_QUERY, "ipsecmod[module %d] operate: extstate:%s event:%s", - id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if(iq) log_query_info(VERB_QUERY, "ipsecmod operate: query", - &qstate->qinfo); - - /* create ipsecmod_qstate. */ - if((event == module_event_new || event == module_event_pass) && - iq == NULL) { - if(!ipsecmod_new(qstate, id)) { - errinf(qstate, "ipsecmod: could not ipsecmod_new"); - ipsecmod_error(qstate, id); - return; - } - iq = (struct ipsecmod_qstate*)qstate->minfo[id]; - } - if(iq && (event == module_event_pass || event == module_event_new)) { - ipsecmod_handle_query(qstate, iq, ie, id); - return; - } - if(iq && (event == module_event_moddone)) { - ipsecmod_handle_response(qstate, iq, ie, id); - return; - } - if(iq && outbound) { - /* cachedb does not need to process responses at this time - * ignore it. - cachedb_process_response(qstate, iq, ie, id, outbound, event); - */ - return; - } - if(event == module_event_error) { - verbose(VERB_ALGO, "got called with event error, giving up"); - errinf(qstate, "ipsecmod: got called with event error"); - ipsecmod_error(qstate, id); - return; - } - if(!iq && (event == module_event_moddone)) { - /* during priming, module done but we never started. */ - qstate->ext_state[id] = module_finished; - return; - } - - log_err("ipsecmod: bad event %s", strmodulevent(event)); - errinf(qstate, "ipsecmod: operate got bad event"); - ipsecmod_error(qstate, id); - return; -} - -void -ipsecmod_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) -{ - struct ipsecmod_qstate* siq; - log_query_info(VERB_ALGO, "ipsecmod: inform_super, sub is", - &qstate->qinfo); - log_query_info(VERB_ALGO, "super is", &super->qinfo); - siq = (struct ipsecmod_qstate*)super->minfo[id]; - if(!siq) { - verbose(VERB_ALGO, "super has no ipsecmod state"); - return; - } - - if(qstate->return_msg) { - struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset( - &qstate->return_msg->qinfo, qstate->return_msg->rep); - if(rrset_key) { - /* We have an answer. */ - /* Copy to super's region. */ - rrset_key = packed_rrset_copy_region(rrset_key, super->region, 0); - siq->ipseckey_rrset = rrset_key; - if(!rrset_key) { - log_err("ipsecmod: out of memory."); - } - } - } - /* Notify super to proceed. */ - siq->ipseckey_done = 1; -} - -void -ipsecmod_clear(struct module_qstate* qstate, int id) -{ - if(!qstate) - return; - qstate->minfo[id] = NULL; -} - -size_t -ipsecmod_get_mem(struct module_env* env, int id) -{ - struct ipsecmod_env* ie = (struct ipsecmod_env*)env->modinfo[id]; - if(!ie) - return 0; - return sizeof(*ie) + ipsecmod_whitelist_get_mem(ie->whitelist); -} - -/** - * The ipsecmod function block - */ -static struct module_func_block ipsecmod_block = { - "ipsecmod", - &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate, - &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem -}; - -struct module_func_block* -ipsecmod_get_funcblock(void) -{ - return &ipsecmod_block; -} -#endif /* USE_IPSECMOD */ diff --git a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.h b/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.h deleted file mode 100644 index 272f473c..00000000 --- a/crates/libunbound-sys/unbound/ipsecmod/ipsecmod.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ipsecmod/ipsecmod.h - facilitate opportunistic IPsec module - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that facilitates opportunistic IPsec. It does so - * by also querying for the IPSECKEY for A/AAAA queries and calling a - * configurable hook (eg. signaling an IKE daemon) before replying. - */ - -#ifndef IPSECMOD_H -#define IPSECMOD_H -#include "util/module.h" -#include "util/rbtree.h" - -/** - * The global variable environment contents for the ipsecmod - * Shared between threads, this represents long term information. - */ -struct ipsecmod_env { - /** White listed domains for ipsecmod. */ - rbtree_type* whitelist; -}; - -/** - * Per query state for the ipsecmod module. - */ -struct ipsecmod_qstate { - /** State of the IPsec module. */ - /** NOTE: This value is copied here from the configuration so that a change - * with unbound-control would not complicate an already running mesh. */ - int enabled; - /** If the qname is whitelisted or not. */ - /** NOTE: No whitelist means all qnames are whitelisted. */ - int is_whitelisted; - /** Pointer to IPSECKEY rrset allocated in the qstate region. NULL if there - * was no IPSECKEY reply from the subquery. */ - struct ub_packed_rrset_key* ipseckey_rrset; - /** If the IPSECKEY subquery has finished. */ - int ipseckey_done; -}; - -/** Init the ipsecmod module */ -int ipsecmod_init(struct module_env* env, int id); -/** Deinit the ipsecmod module */ -void ipsecmod_deinit(struct module_env* env, int id); -/** Operate on an event on a query (in qstate). */ -void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); -/** Subordinate query done, inform this super request of its conclusion */ -void ipsecmod_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); -/** clear the ipsecmod query-specific contents out of qstate */ -void ipsecmod_clear(struct module_qstate* qstate, int id); -/** return memory estimate for the ipsecmod module */ -size_t ipsecmod_get_mem(struct module_env* env, int id); - -/** - * Get the function block with pointers to the ipsecmod functions - * @return the function block for "ipsecmod". - */ -struct module_func_block* ipsecmod_get_funcblock(void); - -#endif /* IPSECMOD_H */ diff --git a/crates/libunbound-sys/unbound/ipset/ipset.c b/crates/libunbound-sys/unbound/ipset/ipset.c deleted file mode 100644 index c61ebc20..00000000 --- a/crates/libunbound-sys/unbound/ipset/ipset.c +++ /dev/null @@ -1,386 +0,0 @@ -/** - * \file - * This file implements the ipset module. It can handle packets by putting - * the A and AAAA addresses that are configured in unbound.conf as type - * ipset (local-zone statements) into a firewall rule IPSet. For firewall - * blacklist and whitelist usage. - */ -#include "config.h" -#include "ipset/ipset.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "util/config_file.h" - -#include "services/cache/dns.h" - -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "sldns/parseutil.h" - -#include -#include -#include - -#define BUFF_LEN 256 - -/** - * Return an error - * @param qstate: our query state - * @param id: module id - * @param rcode: error code (DNS errcode). - * @return: 0 for use by caller, to make notation easy, like: - * return error_response(..). - */ -static int error_response(struct module_qstate* qstate, int id, int rcode) { - verbose(VERB_QUERY, "return error response %s", - sldns_lookup_by_id(sldns_rcodes, rcode)? - sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??"); - qstate->return_rcode = rcode; - qstate->return_msg = NULL; - qstate->ext_state[id] = module_finished; - return 0; -} - -static struct mnl_socket * open_mnl_socket() { - struct mnl_socket *mnl; - - mnl = mnl_socket_open(NETLINK_NETFILTER); - if (!mnl) { - log_err("ipset: could not open netfilter."); - return NULL; - } - - if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) { - mnl_socket_close(mnl); - log_err("ipset: could not bind netfilter."); - return NULL; - } - return mnl; -} - -static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) { - struct nlmsghdr *nlh; - struct nfgenmsg *nfg; - struct nlattr *nested[2]; - static char buffer[BUFF_LEN]; - - if (strlen(setname) >= IPSET_MAXNAMELEN) { - errno = ENAMETOOLONG; - return -1; - } - if (af != AF_INET && af != AF_INET6) { - errno = EAFNOSUPPORT; - return -1; - } - - nlh = mnl_nlmsg_put_header(buffer); - nlh->nlmsg_type = IPSET_CMD_ADD | (NFNL_SUBSYS_IPSET << 8); - nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL; - - nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); - nfg->nfgen_family = af; - nfg->version = NFNETLINK_V0; - nfg->res_id = htons(0); - - mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); - mnl_attr_put(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname); - nested[0] = mnl_attr_nest_start(nlh, IPSET_ATTR_DATA); - nested[1] = mnl_attr_nest_start(nlh, IPSET_ATTR_IP); - mnl_attr_put(nlh, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) - | NLA_F_NET_BYTEORDER, (af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)), ipaddr); - mnl_attr_nest_end(nlh, nested[1]); - mnl_attr_nest_end(nlh, nested[0]); - - if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) { - return -1; - } - return 0; -} - -static void -ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl, - struct packed_rrset_data *d, const char* setname, int af, - const char* dname) -{ - int ret; - size_t j, rr_len, rd_len; - uint8_t *rr_data; - - /* to d->count, not d->rrsig_count, because we do not want to add the RRSIGs, only the addresses */ - for (j = 0; j < d->count; j++) { - rr_len = d->rr_len[j]; - rr_data = d->rr_data[j]; - - rd_len = sldns_read_uint16(rr_data); - if(af == AF_INET && rd_len != INET_SIZE) - continue; - if(af == AF_INET6 && rd_len != INET6_SIZE) - continue; - if (rr_len - 2 >= rd_len) { - if(verbosity >= VERB_QUERY) { - char ip[128]; - if(inet_ntop(af, rr_data+2, ip, (socklen_t)sizeof(ip)) == 0) - snprintf(ip, sizeof(ip), "(inet_ntop_error)"); - verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname); - } - ret = add_to_ipset(mnl, setname, rr_data + 2, af); - if (ret < 0) { - log_err("ipset: could not add %s into %s", dname, setname); - - mnl_socket_close(mnl); - ie->mnl = NULL; - break; - } - } - } -} - -static int -ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, - struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset, - const char *qname, const int qlen, const char *setname, int af) -{ - static char dname[BUFF_LEN]; - const char *ds, *qs; - int dlen, plen; - - struct config_strlist *p; - struct packed_rrset_data *d; - - dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN); - if (dlen == 0) { - log_err("bad domain name"); - return -1; - } - - for (p = env->cfg->local_zones_ipset; p; p = p->next) { - ds = NULL; - qs = NULL; - plen = strlen(p->str); - - if (dlen >= plen) { - ds = dname + (dlen - plen); - } - if (qlen >= plen) { - qs = qname + (qlen - plen); - } - if ((ds && strncasecmp(p->str, ds, plen) == 0) - || (qs && strncasecmp(p->str, qs, plen) == 0)) { - d = (struct packed_rrset_data*)rrset->entry.data; - ipset_add_rrset_data(ie, mnl, d, setname, - af, dname); - break; - } - } - return 0; -} - -static int ipset_update(struct module_env *env, struct dns_msg *return_msg, - struct query_info qinfo, struct ipset_env *ie) -{ - struct mnl_socket *mnl; - size_t i; - const char *setname; - struct ub_packed_rrset_key *rrset; - int af; - static char qname[BUFF_LEN]; - int qlen; - - mnl = (struct mnl_socket *)ie->mnl; - if (!mnl) { - /* retry to create mnl socket */ - mnl = open_mnl_socket(); - if (!mnl) { - return -1; - } - ie->mnl = mnl; - } - - qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len, - qname, BUFF_LEN); - if(qlen == 0) { - log_err("bad domain name"); - return -1; - } - - for(i = 0; i < return_msg->rep->rrset_count; i++) { - setname = NULL; - rrset = return_msg->rep->rrsets[i]; - if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A && - ie->v4_enabled == 1) { - af = AF_INET; - setname = ie->name_v4; - } else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA && - ie->v6_enabled == 1) { - af = AF_INET6; - setname = ie->name_v6; - } - - if (setname) { - if(ipset_check_zones_for_rrset(env, ie, mnl, rrset, - qname, qlen, setname, af) == -1) - return -1; - } - } - - return 0; -} - -int ipset_init(struct module_env* env, int id) { - struct ipset_env *ipset_env; - - ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); - if (!ipset_env) { - log_err("malloc failure"); - return 0; - } - - env->modinfo[id] = (void *)ipset_env; - - ipset_env->mnl = NULL; - - ipset_env->name_v4 = env->cfg->ipset_name_v4; - ipset_env->name_v6 = env->cfg->ipset_name_v6; - - ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1; - ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1; - - if ((ipset_env->v4_enabled < 1) && (ipset_env->v6_enabled < 1)) { - log_err("ipset: set name no configuration?"); - return 0; - } - - return 1; -} - -void ipset_deinit(struct module_env *env, int id) { - struct mnl_socket *mnl; - struct ipset_env *ipset_env; - - if (!env || !env->modinfo[id]) { - return; - } - - ipset_env = (struct ipset_env *)env->modinfo[id]; - - mnl = (struct mnl_socket *)ipset_env->mnl; - if (mnl) { - mnl_socket_close(mnl); - ipset_env->mnl = NULL; - } - - free(ipset_env); - env->modinfo[id] = NULL; -} - -static int ipset_new(struct module_qstate* qstate, int id) { - struct ipset_qstate *iq = (struct ipset_qstate *)regional_alloc( - qstate->region, sizeof(struct ipset_qstate)); - qstate->minfo[id] = iq; - if (!iq) { - return 0; - } - - memset(iq, 0, sizeof(*iq)); - /* initialise it */ - /* TODO */ - - return 1; -} - -void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id, - struct outbound_entry *outbound) { - struct ipset_env *ie = (struct ipset_env *)qstate->env->modinfo[id]; - struct ipset_qstate *iq = (struct ipset_qstate *)qstate->minfo[id]; - verbose(VERB_QUERY, "ipset[module %d] operate: extstate:%s event:%s", - id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if (iq) { - log_query_info(VERB_QUERY, "ipset operate: query", &qstate->qinfo); - } - - /* perform ipset state machine */ - if ((event == module_event_new || event == module_event_pass) && !iq) { - if (!ipset_new(qstate, id)) { - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - iq = (struct ipset_qstate*)qstate->minfo[id]; - } - - if (iq && (event == module_event_pass || event == module_event_new)) { - qstate->ext_state[id] = module_wait_module; - return; - } - - if (iq && (event == module_event_moddone)) { - if (qstate->return_msg && qstate->return_msg->rep) { - ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie); - } - qstate->ext_state[id] = module_finished; - return; - } - - if (iq && outbound) { - /* ipset does not need to process responses at this time - * ignore it. - ipset_process_response(qstate, iq, ie, id, outbound, event); - */ - return; - } - - if (event == module_event_error) { - verbose(VERB_ALGO, "got called with event error, giving up"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - - if (!iq && (event == module_event_moddone)) { - /* during priming, module done but we never started */ - qstate->ext_state[id] = module_finished; - return; - } - - log_err("bad event for ipset"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); -} - -void ipset_inform_super(struct module_qstate *ATTR_UNUSED(qstate), - int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super)) { - /* ipset does not use subordinate requests at this time */ - verbose(VERB_ALGO, "ipset inform_super was called"); -} - -void ipset_clear(struct module_qstate *qstate, int id) { - struct cachedb_qstate *iq; - if (!qstate) { - return; - } - iq = (struct cachedb_qstate *)qstate->minfo[id]; - if (iq) { - /* free contents of iq */ - /* TODO */ - } - qstate->minfo[id] = NULL; -} - -size_t ipset_get_mem(struct module_env *env, int id) { - struct ipset_env *ie = (struct ipset_env *)env->modinfo[id]; - if (!ie) { - return 0; - } - return sizeof(*ie); -} - -/** - * The ipset function block - */ -static struct module_func_block ipset_block = { - "ipset", - &ipset_init, &ipset_deinit, &ipset_operate, - &ipset_inform_super, &ipset_clear, &ipset_get_mem -}; - -struct module_func_block * ipset_get_funcblock(void) { - return &ipset_block; -} - diff --git a/crates/libunbound-sys/unbound/ipset/ipset.h b/crates/libunbound-sys/unbound/ipset/ipset.h deleted file mode 100644 index f60a8be8..00000000 --- a/crates/libunbound-sys/unbound/ipset/ipset.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * ipset.h - * - * Author: Kevin Chou - * Email: k9982874@gmail.com - */ -#ifndef IPSET_H -#define IPSET_H -/** \file - * - * This file implements the ipset module. It can handle packets by putting - * the A and AAAA addresses that are configured in unbound.conf as type - * ipset (local-zone statements) into a firewall rule IPSet. For firewall - * blacklist and whitelist usage. - * - * To use the IPset module, install the libmnl-dev (or libmnl-devel) package - * and configure with --enable-ipset. And compile. Then enable the ipset - * module in unbound.conf with module-config: "ipset validator iterator" - * then create it with ipset -N blacklist iphash and then add - * local-zone: "example.com." ipset - * statements for the zones where you want the addresses of the names - * looked up added to the set. - * - * Set the name of the set with - * ipset: - * name-v4: "blacklist" - * name-v6: "blacklist6" - * in unbound.conf. The set can be used in this way: - * iptables -A INPUT -m set --set blacklist src -j DROP - * ip6tables -A INPUT -m set --set blacklist6 src -j DROP - */ - -#include "util/module.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ipset_env { - void* mnl; - - int v4_enabled; - int v6_enabled; - - const char *name_v4; - const char *name_v6; -}; - -struct ipset_qstate { - int dummy; -}; - -/** Init the ipset module */ -int ipset_init(struct module_env* env, int id); -/** Deinit the ipset module */ -void ipset_deinit(struct module_env* env, int id); -/** Operate on an event on a query (in qstate). */ -void ipset_operate(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); -/** Subordinate query done, inform this super request of its conclusion */ -void ipset_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); -/** clear the ipset query-specific contents out of qstate */ -void ipset_clear(struct module_qstate* qstate, int id); -/** return memory estimate for ipset module */ -size_t ipset_get_mem(struct module_env* env, int id); - -/** - * Get the function block with pointers to the ipset functions - * @return the function block for "ipset". - */ -struct module_func_block* ipset_get_funcblock(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IPSET_H */ - diff --git a/crates/libunbound-sys/unbound/iterator/iter_delegpt.c b/crates/libunbound-sys/unbound/iterator/iter_delegpt.c deleted file mode 100644 index c8b9a3ff..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_delegpt.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * iterator/iter_delegpt.c - delegation point with NS and address information. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file implements the Delegation Point. It contains a list of name servers - * and their addresses if known. - */ -#include "config.h" -#include "iterator/iter_delegpt.h" -#include "services/cache/dns.h" -#include "util/regional.h" -#include "util/data/dname.h" -#include "util/data/packed_rrset.h" -#include "util/data/msgreply.h" -#include "util/net_help.h" -#include "sldns/rrdef.h" -#include "sldns/sbuffer.h" - -struct delegpt* -delegpt_create(struct regional* region) -{ - struct delegpt* dp=(struct delegpt*)regional_alloc( - region, sizeof(*dp)); - if(!dp) - return NULL; - memset(dp, 0, sizeof(*dp)); - return dp; -} - -struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) -{ - struct delegpt* copy = delegpt_create(region); - struct delegpt_ns* ns; - struct delegpt_addr* a; - if(!copy) - return NULL; - if(!delegpt_set_name(copy, region, dp->name)) - return NULL; - copy->bogus = dp->bogus; - copy->has_parent_side_NS = dp->has_parent_side_NS; - copy->ssl_upstream = dp->ssl_upstream; - copy->tcp_upstream = dp->tcp_upstream; - for(ns = dp->nslist; ns; ns = ns->next) { - if(!delegpt_add_ns(copy, region, ns->name, ns->lame, - ns->tls_auth_name, ns->port)) - return NULL; - copy->nslist->cache_lookup_count = ns->cache_lookup_count; - copy->nslist->resolved = ns->resolved; - copy->nslist->got4 = ns->got4; - copy->nslist->got6 = ns->got6; - copy->nslist->done_pside4 = ns->done_pside4; - copy->nslist->done_pside6 = ns->done_pside6; - } - for(a = dp->target_list; a; a = a->next_target) { - if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, - a->bogus, a->lame, a->tls_auth_name, -1, NULL)) - return NULL; - } - return copy; -} - -int -delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) -{ - log_assert(!dp->dp_type_mlc); - dp->namelabs = dname_count_size_labels(name, &dp->namelen); - dp->name = regional_alloc_init(region, name, dp->namelen); - return dp->name != 0; -} - -int -delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, - uint8_t lame, char* tls_auth_name, int port) -{ - struct delegpt_ns* ns; - size_t len; - (void)dname_count_size_labels(name, &len); - log_assert(!dp->dp_type_mlc); - /* slow check for duplicates to avoid counting failures when - * adding the same server as a dependency twice */ - if(delegpt_find_ns(dp, name, len)) - return 1; - ns = (struct delegpt_ns*)regional_alloc(region, - sizeof(struct delegpt_ns)); - if(!ns) - return 0; - ns->next = dp->nslist; - ns->namelen = len; - dp->nslist = ns; - ns->name = regional_alloc_init(region, name, ns->namelen); - ns->cache_lookup_count = 0; - ns->resolved = 0; - ns->got4 = 0; - ns->got6 = 0; - ns->lame = lame; - ns->done_pside4 = 0; - ns->done_pside6 = 0; - ns->port = port; - if(tls_auth_name) { - ns->tls_auth_name = regional_strdup(region, tls_auth_name); - if(!ns->tls_auth_name) - return 0; - } else { - ns->tls_auth_name = NULL; - } - return ns->name != 0; -} - -struct delegpt_ns* -delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen) -{ - struct delegpt_ns* p = dp->nslist; - while(p) { - if(namelen == p->namelen && - query_dname_compare(name, p->name) == 0) { - return p; - } - p = p->next; - } - return NULL; -} - -struct delegpt_addr* -delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - struct delegpt_addr* p = dp->target_list; - while(p) { - if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0 - && ((struct sockaddr_in*)addr)->sin_port == - ((struct sockaddr_in*)&p->addr)->sin_port) { - return p; - } - p = p->next_target; - } - return NULL; -} - -int -delegpt_add_target(struct delegpt* dp, struct regional* region, - uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions) -{ - struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); - log_assert(!dp->dp_type_mlc); - if(!ns) { - /* ignore it */ - return 1; - } - if(!lame) { - if(addr_is_ip6(addr, addrlen)) - ns->got6 = 1; - else ns->got4 = 1; - if(ns->got4 && ns->got6) - ns->resolved = 1; - } else { - if(addr_is_ip6(addr, addrlen)) - ns->done_pside6 = 1; - else ns->done_pside4 = 1; - } - log_assert(ns->port>0); - return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, - ns->tls_auth_name, ns->port, additions); -} - -int -delegpt_add_addr(struct delegpt* dp, struct regional* region, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, - uint8_t lame, char* tls_auth_name, int port, int* additions) -{ - struct delegpt_addr* a; - log_assert(!dp->dp_type_mlc); - if(port != -1) { - log_assert(port>0); - sockaddr_store_port(addr, addrlen, port); - } - /* check for duplicates */ - if((a = delegpt_find_addr(dp, addr, addrlen))) { - if(bogus) - a->bogus = bogus; - if(!lame) - a->lame = 0; - return 1; - } - if(additions) - *additions = 1; - - a = (struct delegpt_addr*)regional_alloc(region, - sizeof(struct delegpt_addr)); - if(!a) - return 0; - a->next_target = dp->target_list; - dp->target_list = a; - a->next_result = 0; - a->next_usable = dp->usable_list; - dp->usable_list = a; - memcpy(&a->addr, addr, addrlen); - a->addrlen = addrlen; - a->attempts = 0; - a->bogus = bogus; - a->lame = lame; - a->dnsseclame = 0; - if(tls_auth_name) { - a->tls_auth_name = regional_strdup(region, tls_auth_name); - if(!a->tls_auth_name) - return 0; - } else { - a->tls_auth_name = NULL; - } - return 1; -} - -void -delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing) -{ - struct delegpt_ns* ns; - *numns = 0; - *missing = 0; - for(ns = dp->nslist; ns; ns = ns->next) { - (*numns)++; - if(!ns->resolved) - (*missing)++; - } -} - -void -delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, - size_t* numavail) -{ - struct delegpt_addr* a; - *numaddr = 0; - *numres = 0; - *numavail = 0; - for(a = dp->target_list; a; a = a->next_target) { - (*numaddr)++; - } - for(a = dp->result_list; a; a = a->next_result) { - (*numres)++; - } - for(a = dp->usable_list; a; a = a->next_usable) { - (*numavail)++; - } -} - -void delegpt_log(enum verbosity_value v, struct delegpt* dp) -{ - char buf[LDNS_MAX_DOMAINLEN+1]; - struct delegpt_ns* ns; - struct delegpt_addr* a; - size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0; - if(verbosity < v) - return; - dname_str(dp->name, buf); - if(dp->nslist == NULL && dp->target_list == NULL) { - log_info("DelegationPoint<%s>: empty", buf); - return; - } - delegpt_count_ns(dp, &numns, &missing); - delegpt_count_addr(dp, &numaddr, &numres, &numavail); - log_info("DelegationPoint<%s>: %u names (%u missing), " - "%u addrs (%u result, %u avail)%s", - buf, (unsigned)numns, (unsigned)missing, - (unsigned)numaddr, (unsigned)numres, (unsigned)numavail, - (dp->has_parent_side_NS?" parentNS":" cacheNS")); - if(verbosity >= VERB_ALGO) { - for(ns = dp->nslist; ns; ns = ns->next) { - dname_str(ns->name, buf); - log_info(" %s %s%s%s%s%s%s%s", buf, - (ns->resolved?"*":""), - (ns->got4?" A":""), (ns->got6?" AAAA":""), - (dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""), - (ns->done_pside4?" PSIDE_A":""), - (ns->done_pside6?" PSIDE_AAAA":"")); - } - for(a = dp->target_list; a; a = a->next_target) { - char s[128]; - const char* str = " "; - if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; - else if(a->bogus) str = " BOGUS "; - else if(a->lame) str = " ADDR_LAME "; - if(a->tls_auth_name) - snprintf(s, sizeof(s), "%s[%s]", str, - a->tls_auth_name); - else snprintf(s, sizeof(s), "%s", str); - log_addr(VERB_ALGO, s, &a->addr, a->addrlen); - } - } -} - -int -delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find) -{ - struct delegpt_addr* a = dp->result_list; - while(a) { - if(a == find) - return 1; - a = a->next_result; - } - return 0; -} - -void -delegpt_usable_list_remove_addr(struct delegpt* dp, struct delegpt_addr* del) -{ - struct delegpt_addr* usa = dp->usable_list, *prev = NULL; - while(usa) { - if(usa == del) { - /* snip off the usable list */ - if(prev) - prev->next_usable = usa->next_usable; - else dp->usable_list = usa->next_usable; - return; - } - prev = usa; - usa = usa->next_usable; - } -} - -void -delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a) -{ - if(delegpt_addr_on_result_list(dp, a)) - return; - delegpt_usable_list_remove_addr(dp, a); - a->next_result = dp->result_list; - dp->result_list = a; -} - -void -delegpt_add_unused_targets(struct delegpt* dp) -{ - struct delegpt_addr* usa = dp->usable_list; - dp->usable_list = NULL; - while(usa) { - usa->next_result = dp->result_list; - dp->result_list = usa; - usa = usa->next_usable; - } -} - -size_t -delegpt_count_targets(struct delegpt* dp) -{ - struct delegpt_addr* a; - size_t n = 0; - for(a = dp->target_list; a; a = a->next_target) - n++; - return n; -} - -size_t -delegpt_count_missing_targets(struct delegpt* dp, int* alllame) -{ - struct delegpt_ns* ns; - size_t n = 0, nlame = 0; - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->resolved) continue; - n++; - if(ns->lame) nlame++; - } - if(alllame && n == nlame) *alllame = 1; - return n; -} - -/** find NS rrset in given list */ -static struct ub_packed_rrset_key* -find_NS(struct reply_info* rep, size_t from, size_t to) -{ - size_t i; - for(i=from; irrsets[i]->rk.type) == LDNS_RR_TYPE_NS) - return rep->rrsets[i]; - } - return NULL; -} - -struct delegpt* -delegpt_from_message(struct dns_msg* msg, struct regional* region) -{ - struct ub_packed_rrset_key* ns_rrset = NULL; - struct delegpt* dp; - size_t i; - /* look for NS records in the authority section... */ - ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets, - msg->rep->an_numrrsets+msg->rep->ns_numrrsets); - - /* In some cases (even legitimate, perfectly legal cases), the - * NS set for the "referral" might be in the answer section. */ - if(!ns_rrset) - ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets); - - /* If there was no NS rrset in the authority section, then this - * wasn't a referral message. (It might not actually be a - * referral message anyway) */ - if(!ns_rrset) - return NULL; - - /* If we found any, then Yay! we have a delegation point. */ - dp = delegpt_create(region); - if(!dp) - return NULL; - dp->has_parent_side_NS = 1; /* created from message */ - if(!delegpt_set_name(dp, region, ns_rrset->rk.dname)) - return NULL; - if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0)) - return NULL; - - /* add glue, A and AAAA in answer and additional section */ - for(i=0; irep->rrset_count; i++) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - /* skip auth section. FIXME really needed?*/ - if(msg->rep->an_numrrsets <= i && - i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets)) - continue; - - if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) { - if(!delegpt_add_rrset_A(dp, region, s, 0, NULL)) - return NULL; - } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) { - if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL)) - return NULL; - } - } - return dp; -} - -int -delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ns_rrset, uint8_t lame) -{ - struct packed_rrset_data* nsdata = (struct packed_rrset_data*) - ns_rrset->entry.data; - size_t i; - log_assert(!dp->dp_type_mlc); - if(nsdata->security == sec_status_bogus) - dp->bogus = 1; - for(i=0; icount; i++) { - if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */ - if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) != - (size_t)sldns_read_uint16(nsdata->rr_data[i])) - continue; /* bad format */ - /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */ - if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame, - NULL, UNBOUND_DNS_PORT)) - return 0; - } - return 1; -} - -int -delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) -{ - struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; - size_t i; - struct sockaddr_in sa; - socklen_t len = (socklen_t)sizeof(sa); - log_assert(!dp->dp_type_mlc); - memset(&sa, 0, len); - sa.sin_family = AF_INET; - for(i=0; icount; i++) { - if(d->rr_len[i] != 2 + INET_SIZE) - continue; - memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE); - if(!delegpt_add_target(dp, region, ak->rk.dname, - ak->rk.dname_len, (struct sockaddr_storage*)&sa, - len, (d->security==sec_status_bogus), lame, additions)) - return 0; - } - return 1; -} - -int -delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) -{ - struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; - size_t i; - struct sockaddr_in6 sa; - socklen_t len = (socklen_t)sizeof(sa); - log_assert(!dp->dp_type_mlc); - memset(&sa, 0, len); - sa.sin6_family = AF_INET6; - for(i=0; icount; i++) { - if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */ - continue; - memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE); - if(!delegpt_add_target(dp, region, ak->rk.dname, - ak->rk.dname_len, (struct sockaddr_storage*)&sa, - len, (d->security==sec_status_bogus), lame, additions)) - return 0; - } - return 1; -} - -int -delegpt_add_rrset(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions) -{ - if(!rrset) - return 1; - if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS) - return delegpt_rrset_add_ns(dp, region, rrset, lame); - else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A) - return delegpt_add_rrset_A(dp, region, rrset, lame, additions); - else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA) - return delegpt_add_rrset_AAAA(dp, region, rrset, lame, - additions); - log_warn("Unknown rrset type added to delegpt"); - return 1; -} - -void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype) -{ - if(ns) { - if(qtype == LDNS_RR_TYPE_A) - ns->got4 = 2; - else if(qtype == LDNS_RR_TYPE_AAAA) - ns->got6 = 2; - if(ns->got4 && ns->got6) - ns->resolved = 1; - } -} - -void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) -{ - struct reply_info* rep = (struct reply_info*)msg->entry.data; - if(!rep) return; - - /* if error or no answers */ - if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { - struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, - msg->key.qname_len); - delegpt_mark_neg(ns, msg->key.qtype); - } -} - -void delegpt_no_ipv6(struct delegpt* dp) -{ - struct delegpt_ns* ns; - for(ns = dp->nslist; ns; ns = ns->next) { - /* no ipv6, so only ipv4 is enough to resolve a nameserver */ - if(ns->got4) - ns->resolved = 1; - } -} - -void delegpt_no_ipv4(struct delegpt* dp) -{ - struct delegpt_ns* ns; - for(ns = dp->nslist; ns; ns = ns->next) { - /* no ipv4, so only ipv6 is enough to resolve a nameserver */ - if(ns->got6) - ns->resolved = 1; - } -} - -struct delegpt* delegpt_create_mlc(uint8_t* name) -{ - struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp)); - if(!dp) - return NULL; - dp->dp_type_mlc = 1; - if(name) { - dp->namelabs = dname_count_size_labels(name, &dp->namelen); - dp->name = memdup(name, dp->namelen); - if(!dp->name) { - free(dp); - return NULL; - } - } - return dp; -} - -void delegpt_free_mlc(struct delegpt* dp) -{ - struct delegpt_ns* n, *nn; - struct delegpt_addr* a, *na; - if(!dp) return; - log_assert(dp->dp_type_mlc); - n = dp->nslist; - while(n) { - nn = n->next; - free(n->name); - free(n->tls_auth_name); - free(n); - n = nn; - } - a = dp->target_list; - while(a) { - na = a->next_target; - free(a->tls_auth_name); - free(a); - a = na; - } - free(dp->name); - free(dp); -} - -int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) -{ - log_assert(dp->dp_type_mlc); - dp->namelabs = dname_count_size_labels(name, &dp->namelen); - dp->name = memdup(name, dp->namelen); - return (dp->name != NULL); -} - -int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame, - char* tls_auth_name, int port) -{ - struct delegpt_ns* ns; - size_t len; - (void)dname_count_size_labels(name, &len); - log_assert(dp->dp_type_mlc); - /* slow check for duplicates to avoid counting failures when - * adding the same server as a dependency twice */ - if(delegpt_find_ns(dp, name, len)) - return 1; - ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns)); - if(!ns) - return 0; - ns->namelen = len; - ns->name = memdup(name, ns->namelen); - if(!ns->name) { - free(ns); - return 0; - } - ns->next = dp->nslist; - dp->nslist = ns; - ns->cache_lookup_count = 0; - ns->resolved = 0; - ns->got4 = 0; - ns->got6 = 0; - ns->lame = (uint8_t)lame; - ns->done_pside4 = 0; - ns->done_pside6 = 0; - ns->port = port; - if(tls_auth_name) { - ns->tls_auth_name = strdup(tls_auth_name); - if(!ns->tls_auth_name) { - free(ns->name); - free(ns); - return 0; - } - } else { - ns->tls_auth_name = NULL; - } - return 1; -} - -int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name, - int port) -{ - struct delegpt_addr* a; - log_assert(dp->dp_type_mlc); - if(port != -1) { - log_assert(port>0); - sockaddr_store_port(addr, addrlen, port); - } - /* check for duplicates */ - if((a = delegpt_find_addr(dp, addr, addrlen))) { - if(bogus) - a->bogus = bogus; - if(!lame) - a->lame = 0; - return 1; - } - - a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr)); - if(!a) - return 0; - a->next_target = dp->target_list; - dp->target_list = a; - a->next_result = 0; - a->next_usable = dp->usable_list; - dp->usable_list = a; - memcpy(&a->addr, addr, addrlen); - a->addrlen = addrlen; - a->attempts = 0; - a->bogus = bogus; - a->lame = lame; - a->dnsseclame = 0; - if(tls_auth_name) { - a->tls_auth_name = strdup(tls_auth_name); - if(!a->tls_auth_name) { - free(a); - return 0; - } - } else { - a->tls_auth_name = NULL; - } - return 1; -} - -int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, - uint8_t lame) -{ - struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); - log_assert(dp->dp_type_mlc); - if(!ns) { - /* ignore it */ - return 1; - } - if(!lame) { - if(addr_is_ip6(addr, addrlen)) - ns->got6 = 1; - else ns->got4 = 1; - if(ns->got4 && ns->got6) - ns->resolved = 1; - } else { - if(addr_is_ip6(addr, addrlen)) - ns->done_pside6 = 1; - else ns->done_pside4 = 1; - } - log_assert(ns->port>0); - return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, - ns->tls_auth_name, ns->port); -} - -size_t delegpt_get_mem(struct delegpt* dp) -{ - struct delegpt_ns* ns; - size_t s; - if(!dp) return 0; - s = sizeof(*dp) + dp->namelen + - delegpt_count_targets(dp)*sizeof(struct delegpt_addr); - for(ns=dp->nslist; ns; ns=ns->next) - s += sizeof(*ns)+ns->namelen; - return s; -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_delegpt.h b/crates/libunbound-sys/unbound/iterator/iter_delegpt.h deleted file mode 100644 index 49f6f6b8..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_delegpt.h +++ /dev/null @@ -1,485 +0,0 @@ -/* - * iterator/iter_delegpt.h - delegation point with NS and address information. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file implements the Delegation Point. It contains a list of name servers - * and their addresses if known. - */ - -#ifndef ITERATOR_ITER_DELEGPT_H -#define ITERATOR_ITER_DELEGPT_H -#include "util/log.h" -struct regional; -struct delegpt_ns; -struct delegpt_addr; -struct dns_msg; -struct ub_packed_rrset_key; -struct msgreply_entry; - -/** - * Delegation Point. - * For a domain name, the NS rrset, and the A and AAAA records for those. - */ -struct delegpt { - /** the domain name of the delegation point. */ - uint8_t* name; - /** length of the delegation point name */ - size_t namelen; - /** number of labels in delegation point */ - int namelabs; - - /** the nameservers, names from the NS RRset rdata. */ - struct delegpt_ns* nslist; - /** the target addresses for delegation */ - struct delegpt_addr* target_list; - /** the list of usable targets; subset of target_list - * the items in this list are not part of the result list. */ - struct delegpt_addr* usable_list; - /** the list of returned targets; subset of target_list */ - struct delegpt_addr* result_list; - - /** if true, the NS RRset was bogus. All info is bad. */ - int bogus; - /** if true, the parent-side NS record has been applied: - * its names have been added and their addresses can follow later. - * Also true if the delegationpoint was created from a delegation - * message and thus contains the parent-side-info already. */ - uint8_t has_parent_side_NS; - /** for assertions on type of delegpt */ - uint8_t dp_type_mlc; - /** use SSL for upstream query */ - uint8_t ssl_upstream; - /** use TCP for upstream query */ - uint8_t tcp_upstream; - /** delegpt from authoritative zone that is locally hosted */ - uint8_t auth_dp; - /*** no cache */ - int no_cache; -}; - -/** - * Nameservers for a delegation point. - */ -struct delegpt_ns { - /** next in list */ - struct delegpt_ns* next; - /** name of nameserver */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** number of cache lookups for the name */ - int cache_lookup_count; - /** - * If the name has been resolved. false if not queried for yet. - * true if the A, AAAA queries have been generated. - * marked true if those queries fail. - * and marked true if got4 and got6 are both true. - */ - int resolved; - /** if the ipv4 address is in the delegpt, 0=not, 1=yes 2=negative, - * negative means it was done, but no content. */ - uint8_t got4; - /** if the ipv6 address is in the delegpt, 0=not, 1=yes 2=negative */ - uint8_t got6; - /** - * If the name is parent-side only and thus dispreferred. - * Its addresses become dispreferred as well - */ - uint8_t lame; - /** if the parent-side ipv4 address has been looked up (last resort). - * Also enabled if a parent-side cache entry exists, or a parent-side - * negative-cache entry exists. */ - uint8_t done_pside4; - /** if the parent-side ipv6 address has been looked up (last resort). - * Also enabled if a parent-side cache entry exists, or a parent-side - * negative-cache entry exists. */ - uint8_t done_pside6; - /** the TLS authentication name, (if not NULL) to use. */ - char* tls_auth_name; - /** the port to use; it should mostly be the default 53 but configured - * upstreams can provide nondefault ports. */ - int port; -}; - -/** - * Address of target nameserver in delegation point. - */ -struct delegpt_addr { - /** next delegation point in results */ - struct delegpt_addr* next_result; - /** next delegation point in usable list */ - struct delegpt_addr* next_usable; - /** next delegation point in all targets list */ - struct delegpt_addr* next_target; - - /** delegation point address */ - struct sockaddr_storage addr; - /** length of addr */ - socklen_t addrlen; - /** number of attempts for this addr */ - int attempts; - /** rtt stored here in the selection algorithm */ - int sel_rtt; - /** if true, the A or AAAA RR was bogus, so this address is bad. - * Also check the dp->bogus to see if everything is bogus. */ - uint8_t bogus; - /** if true, this address is dispreferred: it is a lame IP address */ - uint8_t lame; - /** if the address is dnsseclame, but this cannot be cached, this - * option is useful to mark the address dnsseclame. - * This value is not copied in addr-copy and dp-copy. */ - uint8_t dnsseclame; - /** the TLS authentication name, (if not NULL) to use. */ - char* tls_auth_name; -}; - -/** - * Create new delegation point. - * @param regional: where to allocate it. - * @return new delegation point or NULL on error. - */ -struct delegpt* delegpt_create(struct regional* regional); - -/** - * Create a copy of a delegation point. - * @param dp: delegation point to copy. - * @param regional: where to allocate it. - * @return new delegation point or NULL on error. - */ -struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* regional); - -/** - * Set name of delegation point. - * @param dp: delegation point. - * @param regional: where to allocate the name copy. - * @param name: name to use. - * @return false on error. - */ -int delegpt_set_name(struct delegpt* dp, struct regional* regional, - uint8_t* name); - -/** - * Add a name to the delegation point. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param name: domain name in wire format. - * @param lame: name is lame, disprefer it. - * @param tls_auth_name: TLS authentication name (or NULL). - * @param port: port to use for resolved addresses. - * @return false on error. - */ -int delegpt_add_ns(struct delegpt* dp, struct regional* regional, - uint8_t* name, uint8_t lame, char* tls_auth_name, int port); - -/** - * Add NS rrset; calls add_ns repeatedly. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param ns_rrset: NS rrset. - * @param lame: rrset is lame, disprefer it. - * @return 0 on alloc error. - */ -int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* ns_rrset, uint8_t lame); - -/** - * Add target address to the delegation point. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param name: name for which target was found (must be in nslist). - * This name is marked resolved. - * @param namelen: length of name. - * @param addr: the address. - * @param addrlen: the length of addr. - * @param bogus: security status for the address, pass true if bogus. - * @param lame: address is lame. - * @param additions: will be set to 1 if a new address is added - * @return false on error. - */ -int delegpt_add_target(struct delegpt* dp, struct regional* regional, - uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions); - -/** - * Add A RRset to delegpt. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param rrset: RRset A to add. - * @param lame: rrset is lame, disprefer it. - * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ -int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - -/** - * Add AAAA RRset to delegpt. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param rrset: RRset AAAA to add. - * @param lame: rrset is lame, disprefer it. - * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ -int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - -/** - * Add any RRset to delegpt. - * Does not check for duplicates added. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param rrset: RRset to add, NS, A, AAAA. - * @param lame: rrset is lame, disprefer it. - * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ -int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - -/** - * Add address to the delegation point. No servername is associated or checked. - * @param dp: delegation point. - * @param regional: where to allocate the info. - * @param addr: the address. - * @param addrlen: the length of addr. - * @param bogus: if address is bogus. - * @param lame: if address is lame. - * @param tls_auth_name: TLS authentication name (or NULL). - * @param port: the port to use; if -1 the port is taken from addr. - * @param additions: will be set to 1 if a new address is added - * @return false on error. - */ -int delegpt_add_addr(struct delegpt* dp, struct regional* regional, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t bogus, uint8_t lame, char* tls_auth_name, int port, - int* additions); - -/** - * Find NS record in name list of delegation point. - * @param dp: delegation point. - * @param name: name of nameserver to look for, uncompressed wireformat. - * @param namelen: length of name. - * @return the ns structure or NULL if not found. - */ -struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name, - size_t namelen); - -/** - * Find address record in total list of delegation point. - * @param dp: delegation point. - * @param addr: address - * @param addrlen: length of addr - * @return the addr structure or NULL if not found. - */ -struct delegpt_addr* delegpt_find_addr(struct delegpt* dp, - struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Print the delegation point to the log. For debugging. - * @param v: verbosity value that is needed to emit to log. - * @param dp: delegation point. - */ -void delegpt_log(enum verbosity_value v, struct delegpt* dp); - -/** count NS and number missing for logging */ -void delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing); - -/** count addresses, and number in result and available lists, for logging */ -void delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, - size_t* numavail); - -/** - * Add all usable targets to the result list. - * @param dp: delegation point. - */ -void delegpt_add_unused_targets(struct delegpt* dp); - -/** - * Count number of missing targets. These are ns names with no resolved flag. - * @param dp: delegation point. - * @param alllame: if set, check if all the missing targets are lame. - * @return number of missing targets (or 0). - */ -size_t delegpt_count_missing_targets(struct delegpt* dp, int* alllame); - -/** count total number of targets in dp */ -size_t delegpt_count_targets(struct delegpt* dp); - -/** - * Create new delegation point from a dns message - * - * Note that this method does not actually test to see if the message is an - * actual referral. It really is just checking to see if it can construct a - * delegation point, so the message could be of some other type (some ANSWER - * messages, some CNAME messages, generally.) Note that the resulting - * DelegationPoint will contain targets for all "relevant" glue (i.e., - * address records whose ownernames match the target of one of the NS - * records), so if policy dictates that some glue should be discarded beyond - * that, discard it before calling this method. Note that this method will - * find "glue" in either the ADDITIONAL section or the ANSWER section. - * - * @param msg: the dns message, referral. - * @param regional: where to allocate delegation point. - * @return new delegation point or NULL on alloc error, or if the - * message was not appropriate. - */ -struct delegpt* delegpt_from_message(struct dns_msg* msg, - struct regional* regional); - -/** - * Mark negative return in delegation point for specific nameserver. - * sets the got4 or got6 to negative, updates the ns->resolved. - * @param ns: the nameserver in the delegpt. - * @param qtype: A or AAAA (host order). - */ -void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype); - -/** - * Add negative message to delegation point. - * @param dp: delegation point. - * @param msg: the message added, marks off A or AAAA from an NS entry. - */ -void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg); - -/** - * Register the fact that there is no ipv6 and thus AAAAs are not going - * to be queried for or be useful. - * @param dp: the delegation point. Updated to reflect no ipv6. - */ -void delegpt_no_ipv6(struct delegpt* dp); - -/** - * Register the fact that there is no ipv4 and thus As are not going - * to be queried for or be useful. - * @param dp: the delegation point. Updated to reflect no ipv4. - */ -void delegpt_no_ipv4(struct delegpt* dp); - -/** - * create malloced delegation point, with the given name - * @param name: uncompressed wireformat of delegpt name. - * @return NULL on alloc failure - */ -struct delegpt* delegpt_create_mlc(uint8_t* name); - -/** - * free malloced delegation point. - * @param dp: must have been created with delegpt_create_mlc, free'd. - */ -void delegpt_free_mlc(struct delegpt* dp); - -/** - * Set name of delegation point. - * @param dp: delegation point. malloced. - * @param name: name to use. - * @return false on error. - */ -int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name); - -/** - * add a name to malloced delegation point. - * @param dp: must have been created with delegpt_create_mlc. - * @param name: the name to add. - * @param lame: the name is lame, disprefer. - * @param tls_auth_name: TLS authentication name (or NULL). - * @param port: port to use for resolved addresses. - * @return false on error. - */ -int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame, - char* tls_auth_name, int port); - -/** - * add an address to a malloced delegation point. - * @param dp: must have been created with delegpt_create_mlc. - * @param addr: the address. - * @param addrlen: the length of addr. - * @param bogus: if address is bogus. - * @param lame: if address is lame. - * @param tls_auth_name: TLS authentication name (or NULL). - * @param port: the port to use; if -1 the port is taken from addr. - * @return false on error. - */ -int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name, - int port); - -/** - * Add target address to the delegation point. - * @param dp: must have been created with delegpt_create_mlc. - * @param name: name for which target was found (must be in nslist). - * This name is marked resolved. - * @param namelen: length of name. - * @param addr: the address. - * @param addrlen: the length of addr. - * @param bogus: security status for the address, pass true if bogus. - * @param lame: address is lame. - * @return false on error. - */ -int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, - uint8_t lame); - -/** get memory in use by dp */ -size_t delegpt_get_mem(struct delegpt* dp); - -/** - * See if the addr is on the result list. - * @param dp: delegation point. - * @param find: the pointer is searched for on the result list. - * @return 1 if found, 0 if not found. - */ -int delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find); - -/** - * Remove the addr from the usable list. - * @param dp: the delegation point. - * @param del: the addr to remove from the list, the pointer is searched for. - */ -void delegpt_usable_list_remove_addr(struct delegpt* dp, - struct delegpt_addr* del); - -/** - * Add the delegpt_addr back to the result list, if it is not already on - * the result list. Also removes it from the usable list. - * @param dp: delegation point. - * @param a: addr to add, nothing happens if it is already on the result list. - * It is removed from the usable list. - */ -void delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a); - -#endif /* ITERATOR_ITER_DELEGPT_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_donotq.c b/crates/libunbound-sys/unbound/iterator/iter_donotq.c deleted file mode 100644 index 40ffb45c..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_donotq.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * iterator/iter_donotq.c - iterative resolver donotqueryaddresses storage. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * The donotqueryaddresses are stored and looked up. These addresses - * (like 127.0.0.1) must not be used to send queries to, and can be - * discarded immediately from the server selection. - */ -#include "config.h" -#include "iterator/iter_donotq.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" - -struct iter_donotq* -donotq_create(void) -{ - struct iter_donotq* dq = (struct iter_donotq*)calloc(1, - sizeof(struct iter_donotq)); - if(!dq) - return NULL; - dq->region = regional_create(); - if(!dq->region) { - donotq_delete(dq); - return NULL; - } - return dq; -} - -void -donotq_delete(struct iter_donotq* dq) -{ - if(!dq) - return; - regional_destroy(dq->region); - free(dq); -} - -/** insert new address into donotq structure */ -static int -donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr, - socklen_t addrlen, int net) -{ - struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc( - dq->region, sizeof(*node)); - if(!node) - return 0; - if(!addr_tree_insert(&dq->tree, node, addr, addrlen, net)) { - verbose(VERB_QUERY, "duplicate donotquery address ignored."); - } - return 1; -} - -/** apply donotq string */ -static int -donotq_str_cfg(struct iter_donotq* dq, const char* str) -{ - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - verbose(VERB_ALGO, "donotq: %s", str); - if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { - log_err("cannot parse donotquery netblock: %s", str); - return 0; - } - if(!donotq_insert(dq, &addr, addrlen, net)) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** read donotq config */ -static int -read_donotq(struct iter_donotq* dq, struct config_file* cfg) -{ - struct config_strlist* p; - for(p = cfg->donotqueryaddrs; p; p = p->next) { - log_assert(p->str); - if(!donotq_str_cfg(dq, p->str)) - return 0; - } - return 1; -} - -int -donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg) -{ - regional_free_all(dq->region); - addr_tree_init(&dq->tree); - if(!read_donotq(dq, cfg)) - return 0; - if(cfg->donotquery_localhost) { - if(!donotq_str_cfg(dq, "127.0.0.0/8")) - return 0; - if(cfg->do_ip6) { - if(!donotq_str_cfg(dq, "::1")) - return 0; - } - } - addr_tree_init_parents(&dq->tree); - return 1; -} - -int -donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - return addr_tree_lookup(&donotq->tree, addr, addrlen) != NULL; -} - -size_t -donotq_get_mem(struct iter_donotq* donotq) -{ - if(!donotq) return 0; - return sizeof(*donotq) + regional_get_mem(donotq->region); -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_donotq.h b/crates/libunbound-sys/unbound/iterator/iter_donotq.h deleted file mode 100644 index 14105073..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_donotq.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * iterator/iter_donotq.h - iterative resolver donotqueryaddresses storage. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of the donotquery addresses and lookup fast. - */ - -#ifndef ITERATOR_ITER_DONOTQ_H -#define ITERATOR_ITER_DONOTQ_H -#include "util/storage/dnstree.h" -struct iter_env; -struct config_file; -struct regional; - -/** - * Iterator donotqueryaddresses structure - */ -struct iter_donotq { - /** regional for allocation */ - struct regional* region; - /** - * Tree of the address spans that are blocked. - * contents of type addr_tree_node. Each node is an address span - * that must not be used to send queries to. - */ - rbtree_type tree; -}; - -/** - * Create donotqueryaddresses structure - * @return new structure or NULL on error. - */ -struct iter_donotq* donotq_create(void); - -/** - * Delete donotqueryaddresses structure. - * @param donotq: to delete. - */ -void donotq_delete(struct iter_donotq* donotq); - -/** - * Process donotqueryaddresses config. - * @param donotq: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int donotq_apply_cfg(struct iter_donotq* donotq, struct config_file* cfg); - -/** - * See if an address is blocked. - * @param donotq: structure for address storage. - * @param addr: address to check - * @param addrlen: length of addr. - * @return: true if the address must not be queried. false if unlisted. - */ -int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, - socklen_t addrlen); - -/** - * Get memory used by donotqueryaddresses structure. - * @param donotq: structure for address storage. - * @return bytes in use. - */ -size_t donotq_get_mem(struct iter_donotq* donotq); - -#endif /* ITERATOR_ITER_DONOTQ_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_fwd.c b/crates/libunbound-sys/unbound/iterator/iter_fwd.c deleted file mode 100644 index 15137291..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_fwd.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * iterator/iter_fwd.c - iterative resolver module forward zones. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of forward zones and config settings. - */ -#include "config.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_delegpt.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "sldns/rrdef.h" -#include "sldns/str2wire.h" - -int -fwd_cmp(const void* k1, const void* k2) -{ - int m; - struct iter_forward_zone* n1 = (struct iter_forward_zone*)k1; - struct iter_forward_zone* n2 = (struct iter_forward_zone*)k2; - if(n1->dclass != n2->dclass) { - if(n1->dclass < n2->dclass) - return -1; - return 1; - } - return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, - &m); -} - -struct iter_forwards* -forwards_create(void) -{ - struct iter_forwards* fwd = (struct iter_forwards*)calloc(1, - sizeof(struct iter_forwards)); - if(!fwd) - return NULL; - return fwd; -} - -static void fwd_zone_free(struct iter_forward_zone* n) -{ - if(!n) return; - delegpt_free_mlc(n->dp); - free(n->name); - free(n); -} - -static void delfwdnode(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct iter_forward_zone* node = (struct iter_forward_zone*)n; - fwd_zone_free(node); -} - -static void fwd_del_tree(struct iter_forwards* fwd) -{ - if(fwd->tree) - traverse_postorder(fwd->tree, &delfwdnode, NULL); - free(fwd->tree); -} - -void -forwards_delete(struct iter_forwards* fwd) -{ - if(!fwd) - return; - fwd_del_tree(fwd); - free(fwd); -} - -/** insert info into forward structure */ -static int -forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm, - size_t nmlen, int nmlabs, struct delegpt* dp) -{ - struct iter_forward_zone* node = (struct iter_forward_zone*)malloc( - sizeof(struct iter_forward_zone)); - if(!node) { - delegpt_free_mlc(dp); - return 0; - } - node->node.key = node; - node->dclass = c; - node->name = memdup(nm, nmlen); - if(!node->name) { - delegpt_free_mlc(dp); - free(node); - return 0; - } - node->namelen = nmlen; - node->namelabs = nmlabs; - node->dp = dp; - if(!rbtree_insert(fwd->tree, &node->node)) { - char buf[257]; - dname_str(nm, buf); - log_err("duplicate forward zone %s ignored.", buf); - delegpt_free_mlc(dp); - free(node->name); - free(node); - } - return 1; -} - -/** insert new info into forward structure given dp */ -static int -forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) -{ - return forwards_insert_data(fwd, c, dp->name, dp->namelen, - dp->namelabs, dp); -} - -/** initialise parent pointers in the tree */ -static void -fwd_init_parents(struct iter_forwards* fwd) -{ - struct iter_forward_zone* node, *prev = NULL, *p; - int m; - RBTREE_FOR(node, struct iter_forward_zone*, fwd->tree) { - node->parent = NULL; - if(!prev || prev->dclass != node->dclass) { - prev = node; - continue; - } - (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, - node->namelabs, &m); /* we know prev is smaller */ - /* sort order like: . com. bla.com. zwb.com. net. */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - /* looking for name with few labels, a parent */ - if(p->namelabs <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - -/** set zone name */ -static struct delegpt* -read_fwds_name(struct config_stub* s) -{ - struct delegpt* dp; - uint8_t* dname; - size_t dname_len; - if(!s->name) { - log_err("forward zone without a name (use name \".\" to forward everything)"); - return NULL; - } - dname = sldns_str2wire_dname(s->name, &dname_len); - if(!dname) { - log_err("cannot parse forward zone name %s", s->name); - return NULL; - } - if(!(dp=delegpt_create_mlc(dname))) { - free(dname); - log_err("out of memory"); - return NULL; - } - free(dname); - return dp; -} - -/** set fwd host names */ -static int -read_fwds_host(struct config_stub* s, struct delegpt* dp) -{ - struct config_strlist* p; - uint8_t* dname; - char* tls_auth_name; - int port; - for(p = s->hosts; p; p = p->next) { - log_assert(p->str); - dname = authextstrtodname(p->str, &port, &tls_auth_name); - if(!dname) { - log_err("cannot parse forward %s server name: '%s'", - s->name, p->str); - return 0; - } -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(tls_auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", p->str); -#endif - if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) { - free(dname); - log_err("out of memory"); - return 0; - } - free(dname); - } - return 1; -} - -/** set fwd server addresses */ -static int -read_fwds_addr(struct config_stub* s, struct delegpt* dp) -{ - struct config_strlist* p; - struct sockaddr_storage addr; - socklen_t addrlen; - char* tls_auth_name; - for(p = s->addrs; p; p = p->next) { - log_assert(p->str); - if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) { - log_err("cannot parse forward %s ip address: '%s'", - s->name, p->str); - return 0; - } -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(tls_auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", p->str); -#endif - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, - tls_auth_name, -1)) { - log_err("out of memory"); - return 0; - } - } - return 1; -} - -/** read forwards config */ -static int -read_forwards(struct iter_forwards* fwd, struct config_file* cfg) -{ - struct config_stub* s; - for(s = cfg->forwards; s; s = s->next) { - struct delegpt* dp; - if(!(dp=read_fwds_name(s))) - return 0; - if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) { - delegpt_free_mlc(dp); - return 0; - } - /* set flag that parent side NS information is included. - * Asking a (higher up) server on the internet is not useful */ - /* the flag is turned off for 'forward-first' so that the - * last resort will ask for parent-side NS record and thus - * fallback to the internet name servers on a failure */ - dp->has_parent_side_NS = (uint8_t)!s->isfirst; - /* Do not cache if set. */ - dp->no_cache = s->no_cache; - /* use SSL for queries to this forwarder */ - dp->ssl_upstream = (uint8_t)s->ssl_upstream; - /* use TCP for queries to this forwarder */ - dp->tcp_upstream = (uint8_t)s->tcp_upstream; - verbose(VERB_QUERY, "Forward zone server list:"); - delegpt_log(VERB_QUERY, dp); - if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp)) - return 0; - } - return 1; -} - -/** insert a stub hole (if necessary) for stub name */ -static int -fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = c; - key.name = nm; - key.namelabs = dname_count_size_labels(key.name, &key.namelen); - return forwards_insert_data(fwd, key.dclass, key.name, - key.namelen, key.namelabs, NULL); -} - -/** make NULL entries for stubs */ -static int -make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) -{ - struct config_stub* s; - uint8_t* dname; - size_t dname_len; - for(s = cfg->stubs; s; s = s->next) { - if(!s->name) continue; - dname = sldns_str2wire_dname(s->name, &dname_len); - if(!dname) { - log_err("cannot parse stub name '%s'", s->name); - return 0; - } - if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) { - free(dname); - log_err("out of memory"); - return 0; - } - free(dname); - } - return 1; -} - -int -forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) -{ - fwd_del_tree(fwd); - fwd->tree = rbtree_create(fwd_cmp); - if(!fwd->tree) - return 0; - - /* read forward zones */ - if(!read_forwards(fwd, cfg)) - return 0; - if(!make_stub_holes(fwd, cfg)) - return 0; - fwd_init_parents(fwd); - return 1; -} - -struct delegpt* -forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) -{ - rbnode_type* res = NULL; - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = qclass; - key.name = qname; - key.namelabs = dname_count_size_labels(qname, &key.namelen); - res = rbtree_search(fwd->tree, &key); - if(res) return ((struct iter_forward_zone*)res)->dp; - return NULL; -} - -struct delegpt* -forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) -{ - /* lookup the forward zone in the tree */ - rbnode_type* res = NULL; - struct iter_forward_zone *result; - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = qclass; - key.name = qname; - key.namelabs = dname_count_size_labels(qname, &key.namelen); - if(rbtree_find_less_equal(fwd->tree, &key, &res)) { - /* exact */ - result = (struct iter_forward_zone*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct iter_forward_zone*)res; - if(!result || result->dclass != qclass) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->namelabs, key.name, - key.namelabs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->namelabs <= m) - break; - result = result->parent; - } - } - if(result) - return result->dp; - return NULL; -} - -struct delegpt* -forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass) -{ - uint8_t root = 0; - return forwards_lookup(fwd, &root, qclass); -} - -int -forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) -{ - struct iter_forward_zone key; - rbnode_type* n; - struct iter_forward_zone* p; - if(*dclass == 0) { - /* first root item is first item in tree */ - n = rbtree_first(fwd->tree); - if(n == RBTREE_NULL) - return 0; - p = (struct iter_forward_zone*)n; - if(dname_is_root(p->name)) { - *dclass = p->dclass; - return 1; - } - /* root not first item? search for higher items */ - *dclass = p->dclass + 1; - return forwards_next_root(fwd, dclass); - } - /* find class n in tree, we may get a direct hit, or if we don't - * this is the last item of the previous class so rbtree_next() takes - * us to the next root (if any) */ - key.node.key = &key; - key.name = (uint8_t*)"\000"; - key.namelen = 1; - key.namelabs = 0; - key.dclass = *dclass; - n = NULL; - if(rbtree_find_less_equal(fwd->tree, &key, &n)) { - /* exact */ - return 1; - } else { - /* smaller element */ - if(!n || n == RBTREE_NULL) - return 0; /* nothing found */ - n = rbtree_next(n); - if(n == RBTREE_NULL) - return 0; /* no higher */ - p = (struct iter_forward_zone*)n; - if(dname_is_root(p->name)) { - *dclass = p->dclass; - return 1; - } - /* not a root node, return next higher item */ - *dclass = p->dclass+1; - return forwards_next_root(fwd, dclass); - } -} - -size_t -forwards_get_mem(struct iter_forwards* fwd) -{ - struct iter_forward_zone* p; - size_t s; - if(!fwd) - return 0; - s = sizeof(*fwd) + sizeof(*fwd->tree); - RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) { - s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp); - } - return s; -} - -static struct iter_forward_zone* -fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = c; - key.name = nm; - key.namelabs = dname_count_size_labels(nm, &key.namelen); - return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key); -} - -int -forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) -{ - struct iter_forward_zone *z; - if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) { - (void)rbtree_delete(fwd->tree, &z->node); - fwd_zone_free(z); - } - if(!forwards_insert(fwd, c, dp)) - return 0; - fwd_init_parents(fwd); - return 1; -} - -void -forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - struct iter_forward_zone *z; - if(!(z=fwd_zone_find(fwd, c, nm))) - return; /* nothing to do */ - (void)rbtree_delete(fwd->tree, &z->node); - fwd_zone_free(z); - fwd_init_parents(fwd); -} - -int -forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - if(!fwd_add_stub_hole(fwd, c, nm)) { - return 0; - } - fwd_init_parents(fwd); - return 1; -} - -void -forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - struct iter_forward_zone *z; - if(!(z=fwd_zone_find(fwd, c, nm))) - return; /* nothing to do */ - if(z->dp != NULL) - return; /* not a stub hole */ - (void)rbtree_delete(fwd->tree, &z->node); - fwd_zone_free(z); - fwd_init_parents(fwd); -} - diff --git a/crates/libunbound-sys/unbound/iterator/iter_fwd.h b/crates/libunbound-sys/unbound/iterator/iter_fwd.h deleted file mode 100644 index e90b74c1..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_fwd.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * iterator/iter_fwd.h - iterative resolver module forward zones. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of forward zones, and read those from config. - */ - -#ifndef ITERATOR_ITER_FWD_H -#define ITERATOR_ITER_FWD_H -#include "util/rbtree.h" -struct config_file; -struct delegpt; - -/** - * Iterator forward zones structure - */ -struct iter_forwards { - /** - * Zones are stored in this tree. Sort order is specially chosen. - * first sorted on qclass. Then on dname in nsec-like order, so that - * a lookup on class, name will return an exact match or the closest - * match which gives the ancestor needed. - * contents of type iter_forward_zone. - */ - rbtree_type* tree; -}; - -/** - * Iterator forward servers for a particular zone. - */ -struct iter_forward_zone { - /** redblacktree node, key is this structure: class and name */ - rbnode_type node; - /** name */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** number of labels in name */ - int namelabs; - /** delegation point with forward server information for this zone. - * If NULL then this forward entry is used to indicate that a - * stub-zone with the same name exists, and should be used. - * This delegation point is malloced. - */ - struct delegpt* dp; - /** pointer to parent in tree (or NULL if none) */ - struct iter_forward_zone* parent; - /** class. host order. */ - uint16_t dclass; -}; - -/** - * Create forwards - * @return new forwards or NULL on error. - */ -struct iter_forwards* forwards_create(void); - -/** - * Delete forwards. - * @param fwd: to delete. - */ -void forwards_delete(struct iter_forwards* fwd); - -/** - * Process forwards config. - * @param fwd: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg); - -/** - * Find forward zone exactly by name - * @param fwd: forward storage. - * @param qname: The qname of the query. - * @param qclass: The qclass of the query. - * @return: A delegation point or null. - */ -struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname, - uint16_t qclass); - -/** - * Find forward zone information - * For this qname/qclass find forward zone information, returns delegation - * point with server names and addresses, or NULL if no forwarding is needed. - * - * @param fwd: forward storage. - * @param qname: The qname of the query. - * @param qclass: The qclass of the query. - * @return: A delegation point if the query has to be forwarded to that list, - * otherwise null. - */ -struct delegpt* forwards_lookup(struct iter_forwards* fwd, - uint8_t* qname, uint16_t qclass); - -/** - * Same as forwards_lookup, but for the root only - * @param fwd: forward storage. - * @param qclass: The qclass of the query. - * @return: A delegation point if root forward exists, otherwise null. - */ -struct delegpt* forwards_lookup_root(struct iter_forwards* fwd, - uint16_t qclass); - -/** - * Find next root item in forwards lookup tree. - * @param fwd: the forward storage - * @param qclass: class to look at next, or higher. - * @return false if none found, or if true stored in qclass. - */ -int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass); - -/** - * Get memory in use by forward storage - * @param fwd: forward storage. - * @return bytes in use - */ -size_t forwards_get_mem(struct iter_forwards* fwd); - -/** compare two fwd entries */ -int fwd_cmp(const void* k1, const void* k2); - -/** - * Add zone to forward structure. For external use since it recalcs - * the tree parents. - * @param fwd: the forward data structure - * @param c: class of zone - * @param dp: delegation point with name and target nameservers for new - * forward zone. malloced. - * @return false on failure (out of memory); - */ -int forwards_add_zone(struct iter_forwards* fwd, uint16_t c, - struct delegpt* dp); - -/** - * Remove zone from forward structure. For external use since it - * recalcs the tree parents. - * @param fwd: the forward data structure - * @param c: class of zone - * @param nm: name of zone (in uncompressed wireformat). - */ -void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); - -/** - * Add stub hole (empty entry in forward table, that makes resolution skip - * a forward-zone because the stub zone should override the forward zone). - * Does not add one if not necessary. - * @param fwd: the forward data structure - * @param c: class of zone - * @param nm: name of zone (in uncompressed wireformat). - * @return false on failure (out of memory); - */ -int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); - -/** - * Remove stub hole, if one exists. - * @param fwd: the forward data structure - * @param c: class of zone - * @param nm: name of zone (in uncompressed wireformat). - */ -void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, - uint8_t* nm); - -#endif /* ITERATOR_ITER_FWD_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_hints.c b/crates/libunbound-sys/unbound/iterator/iter_hints.c deleted file mode 100644 index a60d9a6b..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_hints.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * iterator/iter_hints.c - iterative resolver module stub and root hints. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of stub and root hints, and read those from config. - */ -#include "config.h" -#include "iterator/iter_hints.h" -#include "iterator/iter_delegpt.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "sldns/rrdef.h" -#include "sldns/str2wire.h" -#include "sldns/wire2str.h" - -struct iter_hints* -hints_create(void) -{ - struct iter_hints* hints = (struct iter_hints*)calloc(1, - sizeof(struct iter_hints)); - if(!hints) - return NULL; - return hints; -} - -static void hints_stub_free(struct iter_hints_stub* s) -{ - if(!s) return; - delegpt_free_mlc(s->dp); - free(s); -} - -static void delhintnode(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct iter_hints_stub* node = (struct iter_hints_stub*)n; - hints_stub_free(node); -} - -static void hints_del_tree(struct iter_hints* hints) -{ - traverse_postorder(&hints->tree, &delhintnode, NULL); -} - -void -hints_delete(struct iter_hints* hints) -{ - if(!hints) - return; - hints_del_tree(hints); - free(hints); -} - -/** add hint to delegation hints */ -static int -ah(struct delegpt* dp, const char* sv, const char* ip) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - size_t dname_len; - uint8_t* dname = sldns_str2wire_dname(sv, &dname_len); - if(!dname) { - log_err("could not parse %s", sv); - return 0; - } - if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) || - !extstrtoaddr(ip, &addr, &addrlen, UNBOUND_DNS_PORT) || - !delegpt_add_target_mlc(dp, dname, dname_len, - &addr, addrlen, 0, 0)) { - free(dname); - return 0; - } - free(dname); - return 1; -} - -/** obtain compiletime provided root hints */ -static struct delegpt* -compile_time_root_prime(int do_ip4, int do_ip6) -{ - /* from: - ; This file is made available by InterNIC - ; under anonymous FTP as - ; file /domain/named.cache - ; on server FTP.INTERNIC.NET - ; -OR- RS.INTERNIC.NET - ; - ; related version of root zone: changes-on-20120103 - */ - struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000"); - if(!dp) - return NULL; - dp->has_parent_side_NS = 1; - if(do_ip4) { - if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed; - if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed; - if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed; - if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed; - if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed; - if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) goto failed; - if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) goto failed; - if(!ah(dp, "H.ROOT-SERVERS.NET.", "198.97.190.53")) goto failed; - if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) goto failed; - if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) goto failed; - if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) goto failed; - if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) goto failed; - if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) goto failed; - } - if(do_ip6) { - if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed; - if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed; - if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed; - if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed; - if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed; - if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed; - if(!ah(dp, "G.ROOT-SERVERS.NET.", "2001:500:12::d0d")) goto failed; - if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed; - if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed; - if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed; - if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed; - if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:9f::42")) goto failed; - if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) goto failed; - } - return dp; -failed: - delegpt_free_mlc(dp); - return 0; -} - -/** insert new hint info into hint structure */ -static int -hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp, - int noprime) -{ - struct iter_hints_stub* node = (struct iter_hints_stub*)malloc( - sizeof(struct iter_hints_stub)); - if(!node) { - delegpt_free_mlc(dp); - return 0; - } - node->dp = dp; - node->noprime = (uint8_t)noprime; - if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen, - dp->namelabs, c)) { - char buf[257]; - dname_str(dp->name, buf); - log_err("second hints for zone %s ignored.", buf); - delegpt_free_mlc(dp); - free(node); - } - return 1; -} - -/** set stub name */ -static struct delegpt* -read_stubs_name(struct config_stub* s) -{ - struct delegpt* dp; - size_t dname_len; - uint8_t* dname; - if(!s->name) { - log_err("stub zone without a name"); - return NULL; - } - dname = sldns_str2wire_dname(s->name, &dname_len); - if(!dname) { - log_err("cannot parse stub zone name %s", s->name); - return NULL; - } - if(!(dp=delegpt_create_mlc(dname))) { - free(dname); - log_err("out of memory"); - return NULL; - } - free(dname); - return dp; -} - -/** set stub host names */ -static int -read_stubs_host(struct config_stub* s, struct delegpt* dp) -{ - struct config_strlist* p; - uint8_t* dname; - char* tls_auth_name; - int port; - for(p = s->hosts; p; p = p->next) { - log_assert(p->str); - dname = authextstrtodname(p->str, &port, &tls_auth_name); - if(!dname) { - log_err("cannot parse stub %s nameserver name: '%s'", - s->name, p->str); - return 0; - } -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(tls_auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", p->str); -#endif - if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) { - free(dname); - log_err("out of memory"); - return 0; - } - free(dname); - } - return 1; -} - -/** set stub server addresses */ -static int -read_stubs_addr(struct config_stub* s, struct delegpt* dp) -{ - struct config_strlist* p; - struct sockaddr_storage addr; - socklen_t addrlen; - char* auth_name; - for(p = s->addrs; p; p = p->next) { - log_assert(p->str); - if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) { - log_err("cannot parse stub %s ip address: '%s'", - s->name, p->str); - return 0; - } -#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - if(auth_name) - log_err("no name verification functionality in " - "ssl library, ignored name for %s", p->str); -#endif - if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0, - auth_name, -1)) { - log_err("out of memory"); - return 0; - } - } - return 1; -} - -/** read stubs config */ -static int -read_stubs(struct iter_hints* hints, struct config_file* cfg) -{ - struct config_stub* s; - struct delegpt* dp; - for(s = cfg->stubs; s; s = s->next) { - if(!(dp=read_stubs_name(s))) - return 0; - if(!read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) { - delegpt_free_mlc(dp); - return 0; - } - /* the flag is turned off for 'stub-first' so that the - * last resort will ask for parent-side NS record and thus - * fallback to the internet name servers on a failure */ - dp->has_parent_side_NS = (uint8_t)!s->isfirst; - /* Do not cache if set. */ - dp->no_cache = s->no_cache; - /* ssl_upstream */ - dp->ssl_upstream = (uint8_t)s->ssl_upstream; - /* tcp_upstream */ - dp->tcp_upstream = (uint8_t)s->tcp_upstream; - delegpt_log(VERB_QUERY, dp); - if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime)) - return 0; - } - return 1; -} - -/** read root hints from file */ -static int -read_root_hints(struct iter_hints* hints, char* fname) -{ - struct sldns_file_parse_state pstate; - struct delegpt* dp; - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t rr_len, dname_len; - int status; - uint16_t c = LDNS_RR_CLASS_IN; - FILE* f = fopen(fname, "r"); - if(!f) { - log_err("could not read root hints %s: %s", - fname, strerror(errno)); - return 0; - } - dp = delegpt_create_mlc(NULL); - if(!dp) { - log_err("out of memory reading root hints"); - fclose(f); - return 0; - } - verbose(VERB_QUERY, "Reading root hints from %s", fname); - memset(&pstate, 0, sizeof(pstate)); - pstate.lineno = 1; - dp->has_parent_side_NS = 1; - while(!feof(f)) { - rr_len = sizeof(rr); - dname_len = 0; - status = sldns_fp2wire_rr_buf(f, rr, &rr_len, &dname_len, - &pstate); - if(status != 0) { - log_err("reading root hints %s %d:%d: %s", fname, - pstate.lineno, LDNS_WIREPARSE_OFFSET(status), - sldns_get_errorstr_parse(status)); - goto stop_read; - } - if(rr_len == 0) - continue; /* EMPTY line, TTL or ORIGIN */ - if(sldns_wirerr_get_type(rr, rr_len, dname_len) - == LDNS_RR_TYPE_NS) { - if(!delegpt_add_ns_mlc(dp, sldns_wirerr_get_rdata(rr, - rr_len, dname_len), 0, NULL, UNBOUND_DNS_PORT)) { - log_err("out of memory reading root hints"); - goto stop_read; - } - c = sldns_wirerr_get_class(rr, rr_len, dname_len); - if(!dp->name) { - if(!delegpt_set_name_mlc(dp, rr)) { - log_err("out of memory."); - goto stop_read; - } - } - } else if(sldns_wirerr_get_type(rr, rr_len, dname_len) - == LDNS_RR_TYPE_A && sldns_wirerr_get_rdatalen(rr, - rr_len, dname_len) == INET_SIZE) { - struct sockaddr_in sa; - socklen_t len = (socklen_t)sizeof(sa); - memset(&sa, 0, len); - sa.sin_family = AF_INET; - sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); - memmove(&sa.sin_addr, - sldns_wirerr_get_rdata(rr, rr_len, dname_len), - INET_SIZE); - if(!delegpt_add_target_mlc(dp, rr, dname_len, - (struct sockaddr_storage*)&sa, len, - 0, 0)) { - log_err("out of memory reading root hints"); - goto stop_read; - } - } else if(sldns_wirerr_get_type(rr, rr_len, dname_len) - == LDNS_RR_TYPE_AAAA && sldns_wirerr_get_rdatalen(rr, - rr_len, dname_len) == INET6_SIZE) { - struct sockaddr_in6 sa; - socklen_t len = (socklen_t)sizeof(sa); - memset(&sa, 0, len); - sa.sin6_family = AF_INET6; - sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); - memmove(&sa.sin6_addr, - sldns_wirerr_get_rdata(rr, rr_len, dname_len), - INET6_SIZE); - if(!delegpt_add_target_mlc(dp, rr, dname_len, - (struct sockaddr_storage*)&sa, len, - 0, 0)) { - log_err("out of memory reading root hints"); - goto stop_read; - } - } else { - char buf[17]; - sldns_wire2str_type_buf(sldns_wirerr_get_type(rr, - rr_len, dname_len), buf, sizeof(buf)); - log_warn("root hints %s:%d skipping type %s", - fname, pstate.lineno, buf); - } - } - fclose(f); - if(!dp->name) { - log_warn("root hints %s: no NS content", fname); - delegpt_free_mlc(dp); - return 1; - } - delegpt_log(VERB_QUERY, dp); - if(!hints_insert(hints, c, dp, 0)) { - return 0; - } - return 1; - -stop_read: - delegpt_free_mlc(dp); - fclose(f); - return 0; -} - -/** read root hints list */ -static int -read_root_hints_list(struct iter_hints* hints, struct config_file* cfg) -{ - struct config_strlist* p; - for(p = cfg->root_hints; p; p = p->next) { - log_assert(p->str); - if(p->str && p->str[0]) { - char* f = p->str; - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(p->str, cfg->chrootdir, - strlen(cfg->chrootdir)) == 0) - f += strlen(cfg->chrootdir); - if(!read_root_hints(hints, f)) - return 0; - } - } - return 1; -} - -int -hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg) -{ - hints_del_tree(hints); - name_tree_init(&hints->tree); - - /* read root hints */ - if(!read_root_hints_list(hints, cfg)) - return 0; - - /* read stub hints */ - if(!read_stubs(hints, cfg)) - return 0; - - /* use fallback compiletime root hints */ - if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) { - struct delegpt* dp = compile_time_root_prime(cfg->do_ip4, - cfg->do_ip6); - verbose(VERB_ALGO, "no config, using builtin root hints."); - if(!dp) - return 0; - if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) - return 0; - } - - name_tree_init_parents(&hints->tree); - return 1; -} - -struct delegpt* -hints_lookup_root(struct iter_hints* hints, uint16_t qclass) -{ - uint8_t rootlab = 0; - struct iter_hints_stub *stub; - stub = (struct iter_hints_stub*)name_tree_find(&hints->tree, - &rootlab, 1, 1, qclass); - if(!stub) - return NULL; - return stub->dp; -} - -struct iter_hints_stub* -hints_lookup_stub(struct iter_hints* hints, uint8_t* qname, - uint16_t qclass, struct delegpt* cache_dp) -{ - size_t len; - int labs; - struct iter_hints_stub *r; - - /* first lookup the stub */ - labs = dname_count_size_labels(qname, &len); - r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname, - len, labs, qclass); - if(!r) return NULL; - - /* If there is no cache (root prime situation) */ - if(cache_dp == NULL) { - if(r->dp->namelabs != 1) - return r; /* no cache dp, use any non-root stub */ - return NULL; - } - - /* - * If the stub is same as the delegation we got - * And has noprime set, we need to 'prime' to use this stub instead. - */ - if(r->noprime && query_dname_compare(cache_dp->name, r->dp->name)==0) - return r; /* use this stub instead of cached dp */ - - /* - * If our cached delegation point is above the hint, we need to prime. - */ - if(dname_strict_subdomain(r->dp->name, r->dp->namelabs, - cache_dp->name, cache_dp->namelabs)) - return r; /* need to prime this stub */ - return NULL; -} - -int hints_next_root(struct iter_hints* hints, uint16_t* qclass) -{ - return name_tree_next_root(&hints->tree, qclass); -} - -size_t -hints_get_mem(struct iter_hints* hints) -{ - size_t s; - struct iter_hints_stub* p; - if(!hints) return 0; - s = sizeof(*hints); - RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) { - s += sizeof(*p) + delegpt_get_mem(p->dp); - } - return s; -} - -int -hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp, - int noprime) -{ - struct iter_hints_stub *z; - if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree, - dp->name, dp->namelen, dp->namelabs, c)) != NULL) { - (void)rbtree_delete(&hints->tree, &z->node); - hints_stub_free(z); - } - if(!hints_insert(hints, c, dp, noprime)) - return 0; - name_tree_init_parents(&hints->tree); - return 1; -} - -void -hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm) -{ - struct iter_hints_stub *z; - size_t len; - int labs = dname_count_size_labels(nm, &len); - if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree, - nm, len, labs, c))) - return; /* nothing to do */ - (void)rbtree_delete(&hints->tree, &z->node); - hints_stub_free(z); - name_tree_init_parents(&hints->tree); -} - diff --git a/crates/libunbound-sys/unbound/iterator/iter_hints.h b/crates/libunbound-sys/unbound/iterator/iter_hints.h deleted file mode 100644 index 06b4b966..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_hints.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * iterator/iter_hints.h - iterative resolver module stub and root hints. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of stub and root hints, and read those from config. - */ - -#ifndef ITERATOR_ITER_HINTS_H -#define ITERATOR_ITER_HINTS_H -#include "util/storage/dnstree.h" -struct iter_env; -struct config_file; -struct delegpt; - -/** - * Iterator hints structure - */ -struct iter_hints { - /** - * Hints are stored in this tree. Sort order is specially chosen. - * first sorted on qclass. Then on dname in nsec-like order, so that - * a lookup on class, name will return an exact match or the closest - * match which gives the ancestor needed. - * contents of type iter_hints_stub. The class IN root is in here. - * uses name_tree_node from dnstree.h. - */ - rbtree_type tree; -}; - -/** - * Iterator hints for a particular stub. - */ -struct iter_hints_stub { - /** tree sorted by name, class */ - struct name_tree_node node; - /** delegation point with hint information for this stub. malloced. */ - struct delegpt* dp; - /** does the stub need to forego priming (like on other ports) */ - uint8_t noprime; -}; - -/** - * Create hints - * @return new hints or NULL on error. - */ -struct iter_hints* hints_create(void); - -/** - * Delete hints. - * @param hints: to delete. - */ -void hints_delete(struct iter_hints* hints); - -/** - * Process hints config. Sets default values for root hints if no config. - * @param hints: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg); - -/** - * Find root hints for the given class. - * @param hints: hint storage. - * @param qclass: class for which root hints are requested. host order. - * @return: NULL if no hints, or a ptr to stored hints. - */ -struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass); - -/** - * Find next root hints (to cycle through all root hints). - * @param hints: hint storage - * @param qclass: class for which root hints are sought. - * 0 means give the first available root hints class. - * x means, give class x or a higher class if any. - * returns the found class in this variable. - * @return true if a root hint class is found. - * false if not root hint class is found (qclass may have been changed). - */ -int hints_next_root(struct iter_hints* hints, uint16_t* qclass); - -/** - * Given a qname/qclass combination, and the delegation point from the cache - * for this qname/qclass, determine if this combination indicates that a - * stub hint exists and must be primed. - * - * @param hints: hint storage. - * @param qname: The qname that generated the delegation point. - * @param qclass: The qclass that generated the delegation point. - * @param dp: The cache generated delegation point. - * @return: A priming delegation point if there is a stub hint that must - * be primed, otherwise null. - */ -struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints, - uint8_t* qname, uint16_t qclass, struct delegpt* dp); - -/** - * Get memory in use by hints - * @param hints: hint storage. - * @return bytes in use - */ -size_t hints_get_mem(struct iter_hints* hints); - -/** - * Add stub to hints structure. For external use since it recalcs - * the tree parents. - * @param hints: the hints data structure - * @param c: class of zone - * @param dp: delegation point with name and target nameservers for new - * hints stub. malloced. - * @param noprime: set noprime option to true or false on new hint stub. - * @return false on failure (out of memory); - */ -int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp, - int noprime); - -/** - * Remove stub from hints structure. For external use since it - * recalcs the tree parents. - * @param hints: the hints data structure - * @param c: class of stub zone - * @param nm: name of stub zone (in uncompressed wireformat). - */ -void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm); - -#endif /* ITERATOR_ITER_HINTS_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_priv.c b/crates/libunbound-sys/unbound/iterator/iter_priv.c deleted file mode 100644 index 90bea174..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_priv.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * iterator/iter_priv.c - iterative resolver private address and domain store - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of the private addresses and lookup fast. - */ - -#include "config.h" -#include "iterator/iter_priv.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/data/dname.h" -#include "util/data/msgparse.h" -#include "util/net_help.h" -#include "util/storage/dnstree.h" -#include "sldns/str2wire.h" -#include "sldns/sbuffer.h" - -struct iter_priv* priv_create(void) -{ - struct iter_priv* priv = (struct iter_priv*)calloc(1, sizeof(*priv)); - if(!priv) - return NULL; - priv->region = regional_create(); - if(!priv->region) { - priv_delete(priv); - return NULL; - } - addr_tree_init(&priv->a); - name_tree_init(&priv->n); - return priv; -} - -void priv_delete(struct iter_priv* priv) -{ - if(!priv) return; - regional_destroy(priv->region); - free(priv); -} - -/** Read private-addr declarations from config */ -static int read_addrs(struct iter_priv* priv, struct config_file* cfg) -{ - /* parse addresses, report errors, insert into tree */ - struct config_strlist* p; - struct addr_tree_node* n; - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - - for(p = cfg->private_address; p; p = p->next) { - log_assert(p->str); - if(!netblockstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr, - &addrlen, &net)) { - log_err("cannot parse private-address: %s", p->str); - return 0; - } - n = (struct addr_tree_node*)regional_alloc(priv->region, - sizeof(*n)); - if(!n) { - log_err("out of memory"); - return 0; - } - if(!addr_tree_insert(&priv->a, n, &addr, addrlen, net)) { - verbose(VERB_QUERY, "ignoring duplicate " - "private-address: %s", p->str); - } - } - return 1; -} - -/** Read private-domain declarations from config */ -static int read_names(struct iter_priv* priv, struct config_file* cfg) -{ - /* parse names, report errors, insert into tree */ - struct config_strlist* p; - struct name_tree_node* n; - uint8_t* nm, *nmr; - size_t nm_len; - int nm_labs; - - for(p = cfg->private_domain; p; p = p->next) { - log_assert(p->str); - nm = sldns_str2wire_dname(p->str, &nm_len); - if(!nm) { - log_err("cannot parse private-domain: %s", p->str); - return 0; - } - nm_labs = dname_count_size_labels(nm, &nm_len); - nmr = (uint8_t*)regional_alloc_init(priv->region, nm, nm_len); - free(nm); - if(!nmr) { - log_err("out of memory"); - return 0; - } - n = (struct name_tree_node*)regional_alloc(priv->region, - sizeof(*n)); - if(!n) { - log_err("out of memory"); - return 0; - } - if(!name_tree_insert(&priv->n, n, nmr, nm_len, nm_labs, - LDNS_RR_CLASS_IN)) { - verbose(VERB_QUERY, "ignoring duplicate " - "private-domain: %s", p->str); - } - } - return 1; -} - -int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg) -{ - /* empty the current contents */ - regional_free_all(priv->region); - addr_tree_init(&priv->a); - name_tree_init(&priv->n); - - /* read new contents */ - if(!read_addrs(priv, cfg)) - return 0; - if(!read_names(priv, cfg)) - return 0; - - /* prepare for lookups */ - addr_tree_init_parents(&priv->a); - name_tree_init_parents(&priv->n); - return 1; -} - -/** - * See if an address is blocked. - * @param priv: structure for address storage. - * @param addr: address to check - * @param addrlen: length of addr. - * @return: true if the address must not be queried. false if unlisted. - */ -static int -priv_lookup_addr(struct iter_priv* priv, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - return addr_tree_lookup(&priv->a, addr, addrlen) != NULL; -} - -/** - * See if a name is whitelisted. - * @param priv: structure for address storage. - * @param pkt: the packet (for compression ptrs). - * @param name: name to check. - * @param name_len: uncompressed length of the name to check. - * @param dclass: class to check. - * @return: true if the name is OK. false if unlisted. - */ -static int -priv_lookup_name(struct iter_priv* priv, sldns_buffer* pkt, - uint8_t* name, size_t name_len, uint16_t dclass) -{ - size_t len; - uint8_t decomp[256]; - int labs; - if(name_len >= sizeof(decomp)) - return 0; - dname_pkt_copy(pkt, decomp, name); - labs = dname_count_size_labels(decomp, &len); - log_assert(name_len == len); - return name_tree_lookup(&priv->n, decomp, len, labs, dclass) != NULL; -} - -size_t priv_get_mem(struct iter_priv* priv) -{ - if(!priv) return 0; - return sizeof(*priv) + regional_get_mem(priv->region); -} - -/** remove RR from msgparse RRset, return true if rrset is entirely bad */ -static int -remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset, - struct rr_parse* prev, struct rr_parse** rr, struct sockaddr_storage* addr, socklen_t addrlen) -{ - if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) { - uint8_t buf[LDNS_MAX_DOMAINLEN+1]; - dname_pkt_copy(pkt, buf, rrset->dname); - log_name_addr(VERB_QUERY, str, buf, addr, addrlen); - } - if(prev) - prev->next = (*rr)->next; - else rrset->rr_first = (*rr)->next; - if(rrset->rr_last == *rr) - rrset->rr_last = prev; - rrset->rr_count --; - rrset->size -= (*rr)->size; - /* rr struct still exists, but is unlinked, so that in the for loop - * the rr->next works fine to continue. */ - return rrset->rr_count == 0; -} - -int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt, - struct rrset_parse* rrset) -{ - if(priv->a.count == 0) - return 0; /* there are no blocked addresses */ - - /* see if it is a private name, that is allowed to have any */ - if(priv_lookup_name(priv, pkt, rrset->dname, rrset->dname_len, - ntohs(rrset->rrset_class))) { - return 0; - } else { - /* so its a public name, check the address */ - socklen_t len; - struct rr_parse* rr, *prev = NULL; - if(rrset->type == LDNS_RR_TYPE_A) { - struct sockaddr_storage addr; - struct sockaddr_in sa; - - len = (socklen_t)sizeof(sa); - memset(&sa, 0, len); - sa.sin_family = AF_INET; - sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); - for(rr = rrset->rr_first; rr; rr = rr->next) { - if(sldns_read_uint16(rr->ttl_data+4) - != INET_SIZE) { - prev = rr; - continue; - } - memmove(&sa.sin_addr, rr->ttl_data+4+2, - INET_SIZE); - memmove(&addr, &sa, len); - if(priv_lookup_addr(priv, &addr, len)) { - if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len)) - return 1; - continue; - } - prev = rr; - } - } else if(rrset->type == LDNS_RR_TYPE_AAAA) { - struct sockaddr_storage addr; - struct sockaddr_in6 sa; - len = (socklen_t)sizeof(sa); - memset(&sa, 0, len); - sa.sin6_family = AF_INET6; - sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); - for(rr = rrset->rr_first; rr; rr = rr->next) { - if(sldns_read_uint16(rr->ttl_data+4) - != INET6_SIZE) { - prev = rr; - continue; - } - memmove(&sa.sin6_addr, rr->ttl_data+4+2, - INET6_SIZE); - memmove(&addr, &sa, len); - if(priv_lookup_addr(priv, &addr, len)) { - if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len)) - return 1; - continue; - } - prev = rr; - } - } - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_priv.h b/crates/libunbound-sys/unbound/iterator/iter_priv.h deleted file mode 100644 index 0430d57e..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_priv.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * iterator/iter_priv.h - iterative resolver private address and domain store - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Keep track of the private addresses and lookup fast. - */ - -#ifndef ITERATOR_ITER_PRIV_H -#define ITERATOR_ITER_PRIV_H -#include "util/rbtree.h" -struct sldns_buffer; -struct iter_env; -struct config_file; -struct regional; -struct rrset_parse; - -/** - * Iterator priv structure - */ -struct iter_priv { - /** regional for allocation */ - struct regional* region; - /** - * Tree of the address spans that are blocked. - * contents of type addr_tree_node. - * No further data need, only presence or absence. - */ - rbtree_type a; - /** - * Tree of the domains spans that are allowed to contain - * the blocked address spans. - * contents of type name_tree_node. - * No further data need, only presence or absence. - */ - rbtree_type n; -}; - -/** - * Create priv structure - * @return new structure or NULL on error. - */ -struct iter_priv* priv_create(void); - -/** - * Delete priv structure. - * @param priv: to delete. - */ -void priv_delete(struct iter_priv* priv); - -/** - * Process priv config. - * @param priv: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg); - -/** - * See if rrset is bad. - * Will remove individual RRs that are bad (if possible) to - * sanitize the RRset without removing it completely. - * @param priv: structure for private address storage. - * @param pkt: packet to decompress rrset name in. - * @param rrset: the rrset to examine, A or AAAA. - * @return true if the rrset is bad and should be removed. - */ -int priv_rrset_bad(struct iter_priv* priv, struct sldns_buffer* pkt, - struct rrset_parse* rrset); - -/** - * Get memory used by priv structure. - * @param priv: structure for address storage. - * @return bytes in use. - */ -size_t priv_get_mem(struct iter_priv* priv); - -#endif /* ITERATOR_ITER_PRIV_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_resptype.c b/crates/libunbound-sys/unbound/iterator/iter_resptype.c deleted file mode 100644 index e85595b8..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_resptype.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * iterator/iter_resptype.c - response type information and classification. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file defines the response type. DNS Responses can be classified as - * one of the response types. - */ -#include "config.h" -#include "iterator/iter_resptype.h" -#include "iterator/iter_delegpt.h" -#include "services/cache/dns.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "sldns/rrdef.h" -#include "sldns/pkthdr.h" - -enum response_type -response_type_from_cache(struct dns_msg* msg, - struct query_info* request) -{ - /* If the message is NXDOMAIN, then it is an ANSWER. */ - if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) - return RESPONSE_TYPE_ANSWER; - if(request->qtype == LDNS_RR_TYPE_ANY) - return RESPONSE_TYPE_ANSWER; - - /* First we look at the answer section. This can tell us if this is - * CNAME or positive ANSWER. */ - if(msg->rep->an_numrrsets > 0) { - /* Now look at the answer section first. 3 states: - * o our answer is there directly, - * o our answer is there after a cname, - * o or there is just a cname. */ - uint8_t* mname = request->qname; - size_t mname_len = request->qname_len; - size_t i; - for(i=0; irep->an_numrrsets; i++) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - - /* If we have encountered an answer (before or - * after a CNAME), then we are done! Note that - * if qtype == CNAME then this will be noted as - * an ANSWER before it gets treated as a CNAME, - * as it should */ - if(ntohs(s->rk.type) == request->qtype && - ntohs(s->rk.rrset_class) == request->qclass && - query_dname_compare(mname, s->rk.dname) == 0) { - return RESPONSE_TYPE_ANSWER; - } - - /* If we have encountered a CNAME, make sure that - * it is relevant. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(mname, s->rk.dname) == 0) { - get_cname_target(s, &mname, &mname_len); - } - } - - /* if we encountered a CNAME (or a bunch of CNAMEs), and - * still got to here, then it is a CNAME response. (i.e., - * the CNAME chain didn't terminate in an answer rrset.) */ - if(mname != request->qname) { - return RESPONSE_TYPE_CNAME; - } - } - - /* At this point, since we don't need to detect REFERRAL or LAME - * messages, it can only be an ANSWER. */ - return RESPONSE_TYPE_ANSWER; -} - -enum response_type -response_type_from_server(int rdset, - struct dns_msg* msg, struct query_info* request, struct delegpt* dp) -{ - uint8_t* origzone = (uint8_t*)"\000"; /* the default */ - struct ub_packed_rrset_key* s; - size_t i; - - if(!msg || !request) - return RESPONSE_TYPE_THROWAWAY; - /* If the TC flag is set, the response is incomplete. Too large to - * fit even in TCP or so. Discard it, it cannot be retrieved here. */ - if((msg->rep->flags & BIT_TC)) - return RESPONSE_TYPE_THROWAWAY; - - /* If the message is NXDOMAIN, then it answers the question. */ - if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) { - /* make sure its not recursive when we don't want it to */ - if( (msg->rep->flags&BIT_RA) && - !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_REC_LAME; - /* it could be a CNAME with NXDOMAIN rcode */ - for(i=0; irep->an_numrrsets; i++) { - s = msg->rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(request->qname, - s->rk.dname) == 0) { - return RESPONSE_TYPE_CNAME; - } - } - return RESPONSE_TYPE_ANSWER; - } - - /* Other response codes mean (so far) to throw the response away as - * meaningless and move on to the next nameserver. */ - if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) - return RESPONSE_TYPE_THROWAWAY; - - /* Note: TC bit has already been handled */ - - if(dp) { - origzone = dp->name; - } - - /* First we look at the answer section. This can tell us if this is a - * CNAME or ANSWER or (provisional) ANSWER. */ - if(msg->rep->an_numrrsets > 0) { - uint8_t* mname = request->qname; - size_t mname_len = request->qname_len; - - /* Now look at the answer section first. 3 states: our - * answer is there directly, our answer is there after - * a cname, or there is just a cname. */ - for(i=0; irep->an_numrrsets; i++) { - s = msg->rep->rrsets[i]; - - /* if the answer section has NS rrset, and qtype ANY - * and the delegation is lower, and no CNAMEs followed, - * this is a referral where the NS went to AN section */ - if((request->qtype == LDNS_RR_TYPE_ANY || - request->qtype == LDNS_RR_TYPE_NS) && - ntohs(s->rk.type) == LDNS_RR_TYPE_NS && - ntohs(s->rk.rrset_class) == request->qclass && - dname_strict_subdomain_c(s->rk.dname, - origzone)) { - if((msg->rep->flags&BIT_AA)) - return RESPONSE_TYPE_ANSWER; - return RESPONSE_TYPE_REFERRAL; - } - - /* If we have encountered an answer (before or - * after a CNAME), then we are done! Note that - * if qtype == CNAME then this will be noted as an - * ANSWER before it gets treated as a CNAME, as - * it should. */ - if(ntohs(s->rk.type) == request->qtype && - ntohs(s->rk.rrset_class) == request->qclass && - query_dname_compare(mname, s->rk.dname) == 0) { - if((msg->rep->flags&BIT_AA)) - return RESPONSE_TYPE_ANSWER; - /* If the AA bit isn't on, and we've seen - * the answer, we only provisionally say - * 'ANSWER' -- it very well could be a - * REFERRAL. */ - break; - } - - /* If we have encountered a CNAME, make sure that - * it is relevant. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(mname, s->rk.dname) == 0) { - get_cname_target(s, &mname, &mname_len); - } - } - /* not a referral, and qtype any, thus an answer */ - if(request->qtype == LDNS_RR_TYPE_ANY) - return RESPONSE_TYPE_ANSWER; - /* if we encountered a CNAME (or a bunch of CNAMEs), and - * still got to here, then it is a CNAME response. - * (This is regardless of the AA bit at this point) */ - if(mname != request->qname) { - return RESPONSE_TYPE_CNAME; - } - } - - /* Looking at the authority section, we just look and see if - * there is a SOA record, that means a NOERROR/NODATA */ - for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets + - msg->rep->ns_numrrsets); i++) { - s = msg->rep->rrsets[i]; - - /* The normal way of detecting NOERROR/NODATA. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA && - dname_subdomain_c(request->qname, s->rk.dname)) { - /* we do our own recursion, thank you */ - if( (msg->rep->flags&BIT_RA) && - !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_REC_LAME; - return RESPONSE_TYPE_ANSWER; - } - } - /* Looking at the authority section, we just look and see if - * there is a delegation NS set, turning it into a delegation. - * Otherwise, we will have to conclude ANSWER (either it is - * NOERROR/NODATA, or an non-authoritative answer). */ - for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets + - msg->rep->ns_numrrsets); i++) { - s = msg->rep->rrsets[i]; - - /* Detect REFERRAL/LAME/ANSWER based on the relationship - * of the NS set to the originating zone name. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) { - /* If we are getting an NS set for the zone we - * thought we were contacting, then it is an answer.*/ - if(query_dname_compare(s->rk.dname, origzone) == 0) { - /* see if mistakenly a recursive server was - * deployed and is responding nonAA */ - if( (msg->rep->flags&BIT_RA) && - !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_REC_LAME; - /* Or if a lame server is deployed, - * which gives ns==zone delegation from cache - * without AA bit as well, with nodata nosoa*/ - /* real answer must be +AA and SOA RFC(2308), - * so this is wrong, and we SERVFAIL it if - * this is the only possible reply, if it - * is misdeployed the THROWAWAY makes us pick - * the next server from the selection */ - if(msg->rep->an_numrrsets==0 && - !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_THROWAWAY; - return RESPONSE_TYPE_ANSWER; - } - /* If we are getting a referral upwards (or to - * the same zone), then the server is 'lame'. */ - if(dname_subdomain_c(origzone, s->rk.dname)) { - if(rdset) /* forward or reclame not LAME */ - return RESPONSE_TYPE_THROWAWAY; - return RESPONSE_TYPE_LAME; - } - /* If the NS set is below the delegation point we - * are on, and it is non-authoritative, then it is - * a referral, otherwise it is an answer. */ - if(dname_subdomain_c(s->rk.dname, origzone)) { - /* NOTE: I no longer remember in what case - * we would like this to be an answer. - * NODATA should have a SOA or nothing, - * not an NS rrset. - * True, referrals should not have the AA - * bit set, but... */ - - /* if((msg->rep->flags&BIT_AA)) - return RESPONSE_TYPE_ANSWER; */ - return RESPONSE_TYPE_REFERRAL; - } - /* Otherwise, the NS set is irrelevant. */ - } - } - - /* If we've gotten this far, this is NOERROR/NODATA (which could - * be an entirely empty message) */ - /* but ignore entirely empty messages, noerror/nodata has a soa - * negative ttl value in the authority section, this makes it try - * again at another authority. And turns it from a 5 second empty - * message into a 5 second servfail response. */ - if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 && - msg->rep->ar_numrrsets == 0) - return RESPONSE_TYPE_THROWAWAY; - /* check if recursive answer; saying it has empty cache */ - if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset) - return RESPONSE_TYPE_REC_LAME; - return RESPONSE_TYPE_ANSWER; -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_resptype.h b/crates/libunbound-sys/unbound/iterator/iter_resptype.h deleted file mode 100644 index fee9ef35..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_resptype.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * iterator/iter_resptype.h - response type information and classification. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file defines the response type. DNS Responses can be classified as - * one of the response types. - */ - -#ifndef ITERATOR_ITER_RESPTYPE_H -#define ITERATOR_ITER_RESPTYPE_H -struct dns_msg; -struct query_info; -struct delegpt; - -/** - * The response type is used to interpret the response. - */ -enum response_type { - /** - * 'untyped' means that the type of this response hasn't been - * assigned. - */ - RESPONSE_TYPE_UNTYPED = 0, - - /** - * 'answer' means that the response terminates the resolution - * process. - */ - RESPONSE_TYPE_ANSWER, - - /** 'delegation' means that the response is a delegation. */ - RESPONSE_TYPE_REFERRAL, - - /** - * 'cname' means that the response is a cname without the final - * answer, and thus must be restarted. - */ - RESPONSE_TYPE_CNAME, - - /** - * 'throwaway' means that this particular response should be - * discarded and the next nameserver should be contacted - */ - RESPONSE_TYPE_THROWAWAY, - - /** - * 'lame' means that this particular response indicates that - * the nameserver knew nothing about the question. - */ - RESPONSE_TYPE_LAME, - - /** - * Recursion lame means that the nameserver is some sort of - * open recursor, and not authoritative for the question. - * It may know something, but not authoritatively. - */ - RESPONSE_TYPE_REC_LAME -}; - -/** - * Classifies a response message from cache based on the current request. - * Note that this routine assumes that THROWAWAY or LAME responses will not - * occur. Also, it will not detect REFERRAL type messages, since those are - * (currently) automatically classified based on how they came from the - * cache (findDelegation() instead of lookup()). - * - * @param msg: the message from the cache. - * @param request: the request that generated the response. - * @return the response type (CNAME or ANSWER). - */ -enum response_type response_type_from_cache(struct dns_msg* msg, - struct query_info* request); - -/** - * Classifies a response message (from the wire) based on the current - * request. - * - * NOTE: currently this routine uses the AA bit in the response to help - * distinguish between some non-standard referrals and answers. It also - * relies somewhat on the originating zone to be accurate (for lameness - * detection, mostly). - * - * @param rdset: if RD bit was sent in query sent by unbound. - * @param msg: the message from the cache. - * @param request: the request that generated the response. - * @param dp: The delegation point that was being queried - * when the response was returned. - * @return the response type (CNAME or ANSWER). - */ -enum response_type response_type_from_server(int rdset, - struct dns_msg* msg, struct query_info* request, struct delegpt* dp); - -#endif /* ITERATOR_ITER_RESPTYPE_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_scrub.c b/crates/libunbound-sys/unbound/iterator/iter_scrub.c deleted file mode 100644 index d1fedcd0..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_scrub.c +++ /dev/null @@ -1,892 +0,0 @@ -/* - * iterator/iter_scrub.c - scrubbing, normalization, sanitization of DNS msgs. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has routine(s) for cleaning up incoming DNS messages from - * possible useless or malicious junk in it. - */ -#include "config.h" -#include "iterator/iter_scrub.h" -#include "iterator/iterator.h" -#include "iterator/iter_priv.h" -#include "services/cache/rrset.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "util/module.h" -#include "util/data/msgparse.h" -#include "util/data/dname.h" -#include "util/data/msgreply.h" -#include "util/alloc.h" -#include "sldns/sbuffer.h" - -/** RRset flag used during scrubbing. The RRset is OK. */ -#define RRSET_SCRUB_OK 0x80 - -/** remove rrset, update loop variables */ -static void -remove_rrset(const char* str, sldns_buffer* pkt, struct msg_parse* msg, - struct rrset_parse* prev, struct rrset_parse** rrset) -{ - if(verbosity >= VERB_QUERY && str - && (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) { - uint8_t buf[LDNS_MAX_DOMAINLEN+1]; - dname_pkt_copy(pkt, buf, (*rrset)->dname); - log_nametypeclass(VERB_QUERY, str, buf, - (*rrset)->type, ntohs((*rrset)->rrset_class)); - } - if(prev) - prev->rrset_all_next = (*rrset)->rrset_all_next; - else msg->rrset_first = (*rrset)->rrset_all_next; - if(msg->rrset_last == *rrset) - msg->rrset_last = prev; - msg->rrset_count --; - switch((*rrset)->section) { - case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; - case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break; - case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break; - default: log_assert(0); - } - msgparse_bucket_remove(msg, *rrset); - *rrset = (*rrset)->rrset_all_next; -} - -/** return true if rr type has additional names in it */ -static int -has_additional(uint16_t t) -{ - switch(t) { - case LDNS_RR_TYPE_MB: - case LDNS_RR_TYPE_MD: - case LDNS_RR_TYPE_MF: - case LDNS_RR_TYPE_NS: - case LDNS_RR_TYPE_MX: - case LDNS_RR_TYPE_KX: - case LDNS_RR_TYPE_SRV: - return 1; - case LDNS_RR_TYPE_NAPTR: - /* TODO: NAPTR not supported, glue stripped off */ - return 0; - } - return 0; -} - -/** get additional name from rrset RR, return false if no name present */ -static int -get_additional_name(struct rrset_parse* rrset, struct rr_parse* rr, - uint8_t** nm, size_t* nmlen, sldns_buffer* pkt) -{ - size_t offset = 0; - size_t len, oldpos; - switch(rrset->type) { - case LDNS_RR_TYPE_MB: - case LDNS_RR_TYPE_MD: - case LDNS_RR_TYPE_MF: - case LDNS_RR_TYPE_NS: - offset = 0; - break; - case LDNS_RR_TYPE_MX: - case LDNS_RR_TYPE_KX: - offset = 2; - break; - case LDNS_RR_TYPE_SRV: - offset = 6; - break; - case LDNS_RR_TYPE_NAPTR: - /* TODO: NAPTR not supported, glue stripped off */ - return 0; - default: - return 0; - } - len = sldns_read_uint16(rr->ttl_data+sizeof(uint32_t)); - if(len < offset+1) - return 0; /* rdata field too small */ - *nm = rr->ttl_data+sizeof(uint32_t)+sizeof(uint16_t)+offset; - oldpos = sldns_buffer_position(pkt); - sldns_buffer_set_position(pkt, (size_t)(*nm - sldns_buffer_begin(pkt))); - *nmlen = pkt_dname_len(pkt); - sldns_buffer_set_position(pkt, oldpos); - if(*nmlen == 0) - return 0; - return 1; -} - -/** Place mark on rrsets in additional section they are OK */ -static void -mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg, - struct rrset_parse* rrset) -{ - /* Mark A and AAAA for NS as appropriate additional section info. */ - uint8_t* nm = NULL; - size_t nmlen = 0; - struct rr_parse* rr; - - if(!has_additional(rrset->type)) - return; - for(rr = rrset->rr_first; rr; rr = rr->next) { - if(get_additional_name(rrset, rr, &nm, &nmlen, pkt)) { - /* mark A */ - hashvalue_type h = pkt_hash_rrset(pkt, nm, - LDNS_RR_TYPE_A, rrset->rrset_class, 0); - struct rrset_parse* r = msgparse_hashtable_lookup( - msg, pkt, h, 0, nm, nmlen, - LDNS_RR_TYPE_A, rrset->rrset_class); - if(r && r->section == LDNS_SECTION_ADDITIONAL) { - r->flags |= RRSET_SCRUB_OK; - } - - /* mark AAAA */ - h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_AAAA, - rrset->rrset_class, 0); - r = msgparse_hashtable_lookup(msg, pkt, h, 0, nm, - nmlen, LDNS_RR_TYPE_AAAA, rrset->rrset_class); - if(r && r->section == LDNS_SECTION_ADDITIONAL) { - r->flags |= RRSET_SCRUB_OK; - } - } - } -} - -/** Get target name of a CNAME */ -static int -parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname, - size_t* snamelen, sldns_buffer* pkt) -{ - size_t oldpos, dlen; - if(rrset->rr_count != 1) { - struct rr_parse* sig; - verbose(VERB_ALGO, "Found CNAME rrset with " - "size > 1: %u", (unsigned)rrset->rr_count); - /* use the first CNAME! */ - rrset->rr_count = 1; - rrset->size = rrset->rr_first->size; - for(sig=rrset->rrsig_first; sig; sig=sig->next) - rrset->size += sig->size; - rrset->rr_last = rrset->rr_first; - rrset->rr_first->next = NULL; - } - if(rrset->rr_first->size < sizeof(uint16_t)+1) - return 0; /* CNAME rdata too small */ - *sname = rrset->rr_first->ttl_data + sizeof(uint32_t) - + sizeof(uint16_t); /* skip ttl, rdatalen */ - *snamelen = rrset->rr_first->size - sizeof(uint16_t); - - if(rrset->rr_first->outside_packet) { - if(!dname_valid(*sname, *snamelen)) - return 0; - return 1; - } - oldpos = sldns_buffer_position(pkt); - sldns_buffer_set_position(pkt, (size_t)(*sname - sldns_buffer_begin(pkt))); - dlen = pkt_dname_len(pkt); - sldns_buffer_set_position(pkt, oldpos); - if(dlen == 0) - return 0; /* parse fail on the rdata name */ - *snamelen = dlen; - return 1; -} - -/** Synthesize CNAME from DNAME, false if too long */ -static int -synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset, - uint8_t* alias, size_t* aliaslen, sldns_buffer* pkt) -{ - /* we already know that sname is a strict subdomain of DNAME owner */ - uint8_t* dtarg = NULL; - size_t dtarglen; - if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen, pkt)) - return 0; - if(qnamelen <= dname_rrset->dname_len) - return 0; - if(qnamelen == 0) - return 0; - log_assert(qnamelen > dname_rrset->dname_len); - /* DNAME from com. to net. with qname example.com. -> example.net. */ - /* so: \3com\0 to \3net\0 and qname \7example\3com\0 */ - *aliaslen = qnamelen + dtarglen - dname_rrset->dname_len; - if(*aliaslen > LDNS_MAX_DOMAINLEN) - return 0; /* should have been RCODE YXDOMAIN */ - /* decompress dnames into buffer, we know it fits */ - dname_pkt_copy(pkt, alias, qname); - dname_pkt_copy(pkt, alias+(qnamelen-dname_rrset->dname_len), dtarg); - return 1; -} - -/** synthesize a CNAME rrset */ -static struct rrset_parse* -synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias, - size_t aliaslen, struct regional* region, struct msg_parse* msg, - struct rrset_parse* rrset, struct rrset_parse* prev, - struct rrset_parse* nx, sldns_buffer* pkt) -{ - struct rrset_parse* cn = (struct rrset_parse*)regional_alloc(region, - sizeof(struct rrset_parse)); - if(!cn) - return NULL; - memset(cn, 0, sizeof(*cn)); - cn->rr_first = (struct rr_parse*)regional_alloc(region, - sizeof(struct rr_parse)); - if(!cn->rr_first) - return NULL; - cn->rr_last = cn->rr_first; - /* CNAME from sname to alias */ - cn->dname = (uint8_t*)regional_alloc(region, *snamelen); - if(!cn->dname) - return NULL; - dname_pkt_copy(pkt, cn->dname, *sname); - cn->dname_len = *snamelen; - cn->type = LDNS_RR_TYPE_CNAME; - cn->section = rrset->section; - cn->rrset_class = rrset->rrset_class; - cn->rr_count = 1; - cn->size = sizeof(uint16_t) + aliaslen; - cn->hash=pkt_hash_rrset(pkt, cn->dname, cn->type, cn->rrset_class, 0); - /* allocate TTL + rdatalen + uncompressed dname */ - memset(cn->rr_first, 0, sizeof(struct rr_parse)); - cn->rr_first->outside_packet = 1; - cn->rr_first->ttl_data = (uint8_t*)regional_alloc(region, - sizeof(uint32_t)+sizeof(uint16_t)+aliaslen); - if(!cn->rr_first->ttl_data) - return NULL; - sldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */ - sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen); - memmove(cn->rr_first->ttl_data+6, alias, aliaslen); - cn->rr_first->size = sizeof(uint16_t)+aliaslen; - - /* link it in */ - cn->rrset_all_next = nx; - if(prev) - prev->rrset_all_next = cn; - else msg->rrset_first = cn; - if(nx == NULL) - msg->rrset_last = cn; - msg->rrset_count ++; - msg->an_rrsets++; - /* it is not inserted in the msg hashtable. */ - - *sname = cn->rr_first->ttl_data + sizeof(uint32_t)+sizeof(uint16_t); - *snamelen = aliaslen; - return cn; -} - -/** check if DNAME applies to a name */ -static int -pkt_strict_sub(sldns_buffer* pkt, uint8_t* sname, uint8_t* dr) -{ - uint8_t buf1[LDNS_MAX_DOMAINLEN+1]; - uint8_t buf2[LDNS_MAX_DOMAINLEN+1]; - /* decompress names */ - dname_pkt_copy(pkt, buf1, sname); - dname_pkt_copy(pkt, buf2, dr); - return dname_strict_subdomain_c(buf1, buf2); -} - -/** check subdomain with decompression */ -static int -pkt_sub(sldns_buffer* pkt, uint8_t* comprname, uint8_t* zone) -{ - uint8_t buf[LDNS_MAX_DOMAINLEN+1]; - dname_pkt_copy(pkt, buf, comprname); - return dname_subdomain_c(buf, zone); -} - -/** check subdomain with decompression, compressed is parent */ -static int -sub_of_pkt(sldns_buffer* pkt, uint8_t* zone, uint8_t* comprname) -{ - uint8_t buf[LDNS_MAX_DOMAINLEN+1]; - dname_pkt_copy(pkt, buf, comprname); - return dname_subdomain_c(zone, buf); -} - -/** Check if there are SOA records in the authority section (negative) */ -static int -soa_in_auth(struct msg_parse* msg) -{ - struct rrset_parse* rrset; - for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next) - if(rrset->type == LDNS_RR_TYPE_SOA && - rrset->section == LDNS_SECTION_AUTHORITY) - return 1; - return 0; -} - -/** Check if type is allowed in the authority section */ -static int -type_allowed_in_authority_section(uint16_t tp) -{ - if(tp == LDNS_RR_TYPE_SOA || tp == LDNS_RR_TYPE_NS || - tp == LDNS_RR_TYPE_DS || tp == LDNS_RR_TYPE_NSEC || - tp == LDNS_RR_TYPE_NSEC3) - return 1; - return 0; -} - -/** Check if type is allowed in the additional section */ -static int -type_allowed_in_additional_section(uint16_t tp) -{ - if(tp == LDNS_RR_TYPE_A || tp == LDNS_RR_TYPE_AAAA) - return 1; - return 0; -} - -/** - * This routine normalizes a response. This includes removing "irrelevant" - * records from the answer and additional sections and (re)synthesizing - * CNAMEs from DNAMEs, if present. - * - * @param pkt: packet. - * @param msg: msg to normalize. - * @param qinfo: original query. - * @param region: where to allocate synthesized CNAMEs. - * @param env: module env with config options. - * @return 0 on error. - */ -static int -scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, - struct query_info* qinfo, struct regional* region, - struct module_env* env) -{ - uint8_t* sname = qinfo->qname; - size_t snamelen = qinfo->qname_len; - struct rrset_parse* rrset, *prev, *nsset=NULL; - - if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN) - return 1; - - /* For the ANSWER section, remove all "irrelevant" records and add - * synthesized CNAMEs from DNAMEs - * This will strip out-of-order CNAMEs as well. */ - - /* walk through the parse packet rrset list, keep track of previous - * for insert and delete ease, and examine every RRset */ - prev = NULL; - rrset = msg->rrset_first; - while(rrset && rrset->section == LDNS_SECTION_ANSWER) { - if(rrset->type == LDNS_RR_TYPE_DNAME && - pkt_strict_sub(pkt, sname, rrset->dname)) { - /* check if next rrset is correct CNAME. else, - * synthesize a CNAME */ - struct rrset_parse* nx = rrset->rrset_all_next; - uint8_t alias[LDNS_MAX_DOMAINLEN+1]; - size_t aliaslen = 0; - if(rrset->rr_count != 1) { - verbose(VERB_ALGO, "Found DNAME rrset with " - "size > 1: %u", - (unsigned)rrset->rr_count); - return 0; - } - if(!synth_cname(sname, snamelen, rrset, alias, - &aliaslen, pkt)) { - verbose(VERB_ALGO, "synthesized CNAME " - "too long"); - return 0; - } - if(nx && nx->type == LDNS_RR_TYPE_CNAME && - dname_pkt_compare(pkt, sname, nx->dname) == 0) { - /* check next cname */ - uint8_t* t = NULL; - size_t tlen = 0; - if(!parse_get_cname_target(nx, &t, &tlen, pkt)) - return 0; - if(dname_pkt_compare(pkt, alias, t) == 0) { - /* it's OK and better capitalized */ - prev = rrset; - rrset = nx; - continue; - } - /* synth ourselves */ - } - /* synth a CNAME rrset */ - prev = synth_cname_rrset(&sname, &snamelen, alias, - aliaslen, region, msg, rrset, rrset, nx, pkt); - if(!prev) { - log_err("out of memory synthesizing CNAME"); - return 0; - } - /* FIXME: resolve the conflict between synthesized - * CNAME ttls and the cache. */ - rrset = nx; - continue; - - } - - /* The only records in the ANSWER section not allowed to */ - if(dname_pkt_compare(pkt, sname, rrset->dname) != 0) { - remove_rrset("normalize: removing irrelevant RRset:", - pkt, msg, prev, &rrset); - continue; - } - - /* Follow the CNAME chain. */ - if(rrset->type == LDNS_RR_TYPE_CNAME) { - struct rrset_parse* nx = rrset->rrset_all_next; - uint8_t* oldsname = sname; - /* see if the next one is a DNAME, if so, swap them */ - if(nx && nx->section == LDNS_SECTION_ANSWER && - nx->type == LDNS_RR_TYPE_DNAME && - nx->rr_count == 1 && - pkt_strict_sub(pkt, sname, nx->dname)) { - /* there is a DNAME after this CNAME, it - * is in the ANSWER section, and the DNAME - * applies to the name we cover */ - /* check if the alias of the DNAME equals - * this CNAME */ - uint8_t alias[LDNS_MAX_DOMAINLEN+1]; - size_t aliaslen = 0; - uint8_t* t = NULL; - size_t tlen = 0; - if(synth_cname(sname, snamelen, nx, alias, - &aliaslen, pkt) && - parse_get_cname_target(rrset, &t, &tlen, pkt) && - dname_pkt_compare(pkt, alias, t) == 0) { - /* the synthesized CNAME equals the - * current CNAME. This CNAME is the - * one that the DNAME creates, and this - * CNAME is better capitalised */ - verbose(VERB_ALGO, "normalize: re-order of DNAME and its CNAME"); - if(prev) prev->rrset_all_next = nx; - else msg->rrset_first = nx; - if(nx->rrset_all_next == NULL) - msg->rrset_last = rrset; - rrset->rrset_all_next = - nx->rrset_all_next; - nx->rrset_all_next = rrset; - /* prev = nx; unused, enable if there - * is other rrset removal code after - * this */ - } - } - - /* move to next name in CNAME chain */ - if(!parse_get_cname_target(rrset, &sname, &snamelen, pkt)) - return 0; - prev = rrset; - rrset = rrset->rrset_all_next; - /* in CNAME ANY response, can have data after CNAME */ - if(qinfo->qtype == LDNS_RR_TYPE_ANY) { - while(rrset && rrset->section == - LDNS_SECTION_ANSWER && - dname_pkt_compare(pkt, oldsname, - rrset->dname) == 0) { - prev = rrset; - rrset = rrset->rrset_all_next; - } - } - continue; - } - - /* Otherwise, make sure that the RRset matches the qtype. */ - if(qinfo->qtype != LDNS_RR_TYPE_ANY && - qinfo->qtype != rrset->type) { - remove_rrset("normalize: removing irrelevant RRset:", - pkt, msg, prev, &rrset); - continue; - } - - /* Mark the additional names from relevant rrset as OK. */ - /* only for RRsets that match the query name, other ones - * will be removed by sanitize, so no additional for them */ - if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) - mark_additional_rrset(pkt, msg, rrset); - - prev = rrset; - rrset = rrset->rrset_all_next; - } - - /* Mark additional names from AUTHORITY */ - while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) { - /* protect internals of recursor by making sure to del these */ - if(rrset->type==LDNS_RR_TYPE_DNAME || - rrset->type==LDNS_RR_TYPE_CNAME || - rrset->type==LDNS_RR_TYPE_A || - rrset->type==LDNS_RR_TYPE_AAAA) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - /* Allowed list of types in the authority section */ - if(env->cfg->harden_unknown_additional && - !type_allowed_in_authority_section(rrset->type)) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - /* only one NS set allowed in authority section */ - if(rrset->type==LDNS_RR_TYPE_NS) { - /* NS set must be pertinent to the query */ - if(!sub_of_pkt(pkt, qinfo->qname, rrset->dname)) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - /* we don't want NS sets for NXDOMAIN answers, - * because they could contain poisonous contents, - * from. eg. fragmentation attacks, inserted after - * long RRSIGs in the packet get to the packet - * border and such */ - /* also for NODATA answers */ - if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN || - (FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR - && soa_in_auth(msg) && msg->an_rrsets == 0)) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - if(nsset == NULL) { - nsset = rrset; - } else { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - } - /* if this is type DS and we query for type DS we just got - * a referral answer for our type DS query, fix packet */ - if(rrset->type==LDNS_RR_TYPE_DS && - qinfo->qtype == LDNS_RR_TYPE_DS && - dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) { - rrset->section = LDNS_SECTION_ANSWER; - msg->ancount = rrset->rr_count + rrset->rrsig_count; - msg->nscount = 0; - msg->arcount = 0; - msg->an_rrsets = 1; - msg->ns_rrsets = 0; - msg->ar_rrsets = 0; - msg->rrset_count = 1; - msg->rrset_first = rrset; - msg->rrset_last = rrset; - rrset->rrset_all_next = NULL; - return 1; - } - mark_additional_rrset(pkt, msg, rrset); - prev = rrset; - rrset = rrset->rrset_all_next; - } - - /* For each record in the additional section, remove it if it is an - * address record and not in the collection of additional names - * found in ANSWER and AUTHORITY. */ - /* These records have not been marked OK previously */ - while(rrset && rrset->section == LDNS_SECTION_ADDITIONAL) { - if(rrset->type==LDNS_RR_TYPE_A || - rrset->type==LDNS_RR_TYPE_AAAA) - { - if((rrset->flags & RRSET_SCRUB_OK)) { - /* remove flag to clean up flags variable */ - rrset->flags &= ~RRSET_SCRUB_OK; - } else { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - } - /* protect internals of recursor by making sure to del these */ - if(rrset->type==LDNS_RR_TYPE_DNAME || - rrset->type==LDNS_RR_TYPE_CNAME || - rrset->type==LDNS_RR_TYPE_NS) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - /* Allowed list of types in the additional section */ - if(env->cfg->harden_unknown_additional && - !type_allowed_in_additional_section(rrset->type)) { - remove_rrset("normalize: removing irrelevant " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - prev = rrset; - rrset = rrset->rrset_all_next; - } - - return 1; -} - -/** - * Store potential poison in the cache (only if hardening disabled). - * The rrset is stored in the cache but removed from the message. - * So that it will be used for infrastructure purposes, but not be - * returned to the client. - * @param pkt: packet - * @param msg: message parsed - * @param env: environment with cache - * @param rrset: to store. - */ -static void -store_rrset(sldns_buffer* pkt, struct msg_parse* msg, struct module_env* env, - struct rrset_parse* rrset) -{ - struct ub_packed_rrset_key* k; - struct packed_rrset_data* d; - struct rrset_ref ref; - time_t now = *env->now; - - k = alloc_special_obtain(env->alloc); - if(!k) - return; - k->entry.data = NULL; - if(!parse_copy_decompress_rrset(pkt, msg, rrset, NULL, k)) { - alloc_special_release(env->alloc, k); - return; - } - d = (struct packed_rrset_data*)k->entry.data; - packed_rrset_ttl_add(d, now); - ref.key = k; - ref.id = k->id; - /*ignore ret: it was in the cache, ref updated */ - (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now); -} - -/** - * Check if right hand name in NSEC is within zone - * @param pkt: the packet buffer for decompression. - * @param rrset: the NSEC rrset - * @param zonename: the zone name. - * @return true if BAD. - */ -static int sanitize_nsec_is_overreach(sldns_buffer* pkt, - struct rrset_parse* rrset, uint8_t* zonename) -{ - struct rr_parse* rr; - uint8_t* rhs; - size_t len; - log_assert(rrset->type == LDNS_RR_TYPE_NSEC); - for(rr = rrset->rr_first; rr; rr = rr->next) { - size_t pos = sldns_buffer_position(pkt); - size_t rhspos; - rhs = rr->ttl_data+4+2; - len = sldns_read_uint16(rr->ttl_data+4); - rhspos = rhs-sldns_buffer_begin(pkt); - sldns_buffer_set_position(pkt, rhspos); - if(pkt_dname_len(pkt) == 0) { - /* malformed */ - sldns_buffer_set_position(pkt, pos); - return 1; - } - if(sldns_buffer_position(pkt)-rhspos > len) { - /* outside of rdata boundaries */ - sldns_buffer_set_position(pkt, pos); - return 1; - } - sldns_buffer_set_position(pkt, pos); - if(!pkt_sub(pkt, rhs, zonename)) { - /* overreaching */ - return 1; - } - } - /* all NSEC RRs OK */ - return 0; -} - -/** - * Given a response event, remove suspect RRsets from the response. - * "Suspect" rrsets are potentially poison. Note that this routine expects - * the response to be in a "normalized" state -- that is, all "irrelevant" - * RRsets have already been removed, CNAMEs are in order, etc. - * - * @param pkt: packet. - * @param msg: msg to normalize. - * @param qinfo: the question originally asked. - * @param zonename: name of server zone. - * @param env: module environment with config and cache. - * @param ie: iterator environment with private address data. - * @return 0 on error. - */ -static int -scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg, - struct query_info* qinfo, uint8_t* zonename, struct module_env* env, - struct iter_env* ie) -{ - int del_addi = 0; /* if additional-holding rrsets are deleted, we - do not trust the normalized additional-A-AAAA any more */ - struct rrset_parse* rrset, *prev; - prev = NULL; - rrset = msg->rrset_first; - - /* the first DNAME is allowed to stay. It needs checking before - * it can be used from the cache. After normalization, an initial - * DNAME will have a correctly synthesized CNAME after it. */ - if(rrset && rrset->type == LDNS_RR_TYPE_DNAME && - rrset->section == LDNS_SECTION_ANSWER && - pkt_strict_sub(pkt, qinfo->qname, rrset->dname) && - pkt_sub(pkt, rrset->dname, zonename)) { - prev = rrset; /* DNAME allowed to stay in answer section */ - rrset = rrset->rrset_all_next; - } - - /* remove all records from the answer section that are - * not the same domain name as the query domain name. - * The answer section should contain rrsets with the same name - * as the question. For DNAMEs a CNAME has been synthesized. - * Wildcards have the query name in answer section. - * ANY queries get query name in answer section. - * Remainders of CNAME chains are cut off and resolved by iterator. */ - while(rrset && rrset->section == LDNS_SECTION_ANSWER) { - if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) != 0) { - if(has_additional(rrset->type)) del_addi = 1; - remove_rrset("sanitize: removing extraneous answer " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - prev = rrset; - rrset = rrset->rrset_all_next; - } - - /* At this point, we brutally remove ALL rrsets that aren't - * children of the originating zone. The idea here is that, - * as far as we know, the server that we contacted is ONLY - * authoritative for the originating zone. It, of course, MAY - * be authoritative for any other zones, and of course, MAY - * NOT be authoritative for some subdomains of the originating - * zone. */ - prev = NULL; - rrset = msg->rrset_first; - while(rrset) { - - /* remove private addresses */ - if( (rrset->type == LDNS_RR_TYPE_A || - rrset->type == LDNS_RR_TYPE_AAAA)) { - - /* do not set servfail since this leads to too - * many drops of other people using rfc1918 space */ - /* also do not remove entire rrset, unless all records - * in it are bad */ - if(priv_rrset_bad(ie->priv, pkt, rrset)) { - remove_rrset(NULL, pkt, msg, prev, &rrset); - continue; - } - } - - /* skip DNAME records -- they will always be followed by a - * synthesized CNAME, which will be relevant. - * FIXME: should this do something differently with DNAME - * rrsets NOT in Section.ANSWER? */ - /* But since DNAME records are also subdomains of the zone, - * same check can be used */ - - if(!pkt_sub(pkt, rrset->dname, zonename)) { - if(msg->an_rrsets == 0 && - rrset->type == LDNS_RR_TYPE_NS && - rrset->section == LDNS_SECTION_AUTHORITY && - FLAGS_GET_RCODE(msg->flags) == - LDNS_RCODE_NOERROR && !soa_in_auth(msg) && - sub_of_pkt(pkt, zonename, rrset->dname)) { - /* noerror, nodata and this NS rrset is above - * the zone. This is LAME! - * Leave in the NS for lame classification. */ - /* remove everything from the additional - * (we dont want its glue that was approved - * during the normalize action) */ - del_addi = 1; - } else if(!env->cfg->harden_glue && ( - rrset->type == LDNS_RR_TYPE_A || - rrset->type == LDNS_RR_TYPE_AAAA)) { - /* store in cache! Since it is relevant - * (from normalize) it will be picked up - * from the cache to be used later */ - store_rrset(pkt, msg, env, rrset); - remove_rrset("sanitize: storing potential " - "poison RRset:", pkt, msg, prev, &rrset); - continue; - } else { - if(has_additional(rrset->type)) del_addi = 1; - remove_rrset("sanitize: removing potential " - "poison RRset:", pkt, msg, prev, &rrset); - continue; - } - } - if(del_addi && rrset->section == LDNS_SECTION_ADDITIONAL) { - remove_rrset("sanitize: removing potential " - "poison reference RRset:", pkt, msg, prev, &rrset); - continue; - } - /* check if right hand side of NSEC is within zone */ - if(rrset->type == LDNS_RR_TYPE_NSEC && - sanitize_nsec_is_overreach(pkt, rrset, zonename)) { - remove_rrset("sanitize: removing overreaching NSEC " - "RRset:", pkt, msg, prev, &rrset); - continue; - } - prev = rrset; - rrset = rrset->rrset_all_next; - } - return 1; -} - -int -scrub_message(sldns_buffer* pkt, struct msg_parse* msg, - struct query_info* qinfo, uint8_t* zonename, struct regional* region, - struct module_env* env, struct iter_env* ie) -{ - /* basic sanity checks */ - log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS, - qinfo->qclass); - if(msg->qdcount > 1) - return 0; - if( !(msg->flags&BIT_QR) ) - return 0; - msg->flags &= ~(BIT_AD|BIT_Z); /* force off bit AD and Z */ - - /* make sure that a query is echoed back when NOERROR or NXDOMAIN */ - /* this is not required for basic operation but is a forgery - * resistance (security) feature */ - if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) && - msg->qdcount == 0) - return 0; - - /* if a query is echoed back, make sure it is correct. Otherwise, - * this may be not a reply to our query. */ - if(msg->qdcount == 1) { - if(dname_pkt_compare(pkt, msg->qname, qinfo->qname) != 0) - return 0; - if(msg->qtype != qinfo->qtype || msg->qclass != qinfo->qclass) - return 0; - } - - /* normalize the response, this cleans up the additional. */ - if(!scrub_normalize(pkt, msg, qinfo, region, env)) - return 0; - /* delete all out-of-zone information */ - if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie)) - return 0; - return 1; -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_scrub.h b/crates/libunbound-sys/unbound/iterator/iter_scrub.h deleted file mode 100644 index cbbaf73c..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_scrub.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * iterator/iter_scrub.h - scrubbing, normalization, sanitization of DNS msgs. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has routine(s) for cleaning up incoming DNS messages from - * possible useless or malicious junk in it. - */ - -#ifndef ITERATOR_ITER_SCRUB_H -#define ITERATOR_ITER_SCRUB_H -struct sldns_buffer; -struct msg_parse; -struct query_info; -struct regional; -struct module_env; -struct iter_env; - -/** - * Cleanup the passed dns message. - * @param pkt: the packet itself, for resolving name compression pointers. - * the packet buffer is unaltered. - * @param msg: the parsed packet, this structure is cleaned up. - * @param qinfo: the query info that was sent to the server. Checked. - * @param zonename: the name of the last delegation point. - * Used to determine out of bailiwick information. - * @param regional: where to allocate (new) parts of the message. - * @param env: module environment with config settings and cache. - * @param ie: iterator module environment data. - * @return: false if the message is total waste. true if scrubbed with success. - */ -int scrub_message(struct sldns_buffer* pkt, struct msg_parse* msg, - struct query_info* qinfo, uint8_t* zonename, struct regional* regional, - struct module_env* env, struct iter_env* ie); - -#endif /* ITERATOR_ITER_SCRUB_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iter_utils.c b/crates/libunbound-sys/unbound/iterator/iter_utils.c deleted file mode 100644 index 10a8ec3e..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_utils.c +++ /dev/null @@ -1,1525 +0,0 @@ -/* - * iterator/iter_utils.c - iterative resolver module utility functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Configuration options. Forward zones. - */ -#include "config.h" -#include "iterator/iter_utils.h" -#include "iterator/iterator.h" -#include "iterator/iter_hints.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_donotq.h" -#include "iterator/iter_delegpt.h" -#include "iterator/iter_priv.h" -#include "services/cache/infra.h" -#include "services/cache/dns.h" -#include "services/cache/rrset.h" -#include "services/outside_network.h" -#include "util/net_help.h" -#include "util/module.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/regional.h" -#include "util/data/msgparse.h" -#include "util/data/dname.h" -#include "util/random.h" -#include "util/fptr_wlist.h" -#include "validator/val_anchor.h" -#include "validator/val_kcache.h" -#include "validator/val_kentry.h" -#include "validator/val_utils.h" -#include "validator/val_sigcrypt.h" -#include "sldns/sbuffer.h" -#include "sldns/str2wire.h" - -/** time when nameserver glue is said to be 'recent' */ -#define SUSPICION_RECENT_EXPIRY 86400 - -/** if NAT64 is enabled and no NAT64 prefix is configured, first fall back to - * DNS64 prefix. If that is not configured, fall back to this default value. - */ -static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96"; - -/** fillup fetch policy array */ -static void -fetch_fill(struct iter_env* ie, const char* str) -{ - char* s = (char*)str, *e; - int i; - for(i=0; imax_dependency_depth+1; i++) { - ie->target_fetch_policy[i] = strtol(s, &e, 10); - if(s == e) - fatal_exit("cannot parse fetch policy number %s", s); - s = e; - } -} - -/** Read config string that represents the target fetch policy */ -static int -read_fetch_policy(struct iter_env* ie, const char* str) -{ - int count = cfg_count_numbers(str); - if(count < 1) { - log_err("Cannot parse target fetch policy: \"%s\"", str); - return 0; - } - ie->max_dependency_depth = count - 1; - ie->target_fetch_policy = (int*)calloc( - (size_t)ie->max_dependency_depth+1, sizeof(int)); - if(!ie->target_fetch_policy) { - log_err("alloc fetch policy: out of memory"); - return 0; - } - fetch_fill(ie, str); - return 1; -} - -/** apply config caps whitelist items to name tree */ -static int -caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg) -{ - struct config_strlist* p; - for(p=cfg->caps_whitelist; p; p=p->next) { - struct name_tree_node* n; - size_t len; - uint8_t* nm = sldns_str2wire_dname(p->str, &len); - if(!nm) { - log_err("could not parse %s", p->str); - return 0; - } - n = (struct name_tree_node*)calloc(1, sizeof(*n)); - if(!n) { - log_err("out of memory"); - free(nm); - return 0; - } - n->node.key = n; - n->name = nm; - n->len = len; - n->labs = dname_count_labels(nm); - n->dclass = LDNS_RR_CLASS_IN; - if(!name_tree_insert(ntree, n, nm, len, n->labs, n->dclass)) { - /* duplicate element ignored, idempotent */ - free(n->name); - free(n); - } - } - name_tree_init_parents(ntree); - return 1; -} - -int -iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) -{ - const char *nat64_prefix; - int i; - /* target fetch policy */ - if(!read_fetch_policy(iter_env, cfg->target_fetch_policy)) - return 0; - for(i=0; imax_dependency_depth+1; i++) - verbose(VERB_QUERY, "target fetch policy for level %d is %d", - i, iter_env->target_fetch_policy[i]); - - if(!iter_env->donotq) - iter_env->donotq = donotq_create(); - if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) { - log_err("Could not set donotqueryaddresses"); - return 0; - } - if(!iter_env->priv) - iter_env->priv = priv_create(); - if(!iter_env->priv || !priv_apply_cfg(iter_env->priv, cfg)) { - log_err("Could not set private addresses"); - return 0; - } - if(cfg->caps_whitelist) { - if(!iter_env->caps_white) - iter_env->caps_white = rbtree_create(name_tree_compare); - if(!iter_env->caps_white || !caps_white_apply_cfg( - iter_env->caps_white, cfg)) { - log_err("Could not set capsforid whitelist"); - return 0; - } - - } - - nat64_prefix = cfg->nat64_prefix; - if(!nat64_prefix) - nat64_prefix = cfg->dns64_prefix; - if(!nat64_prefix) - nat64_prefix = DEFAULT_NAT64_PREFIX; - if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr, - &iter_env->nat64_prefix_addrlen, - &iter_env->nat64_prefix_net)) { - log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix); - return 0; - } - if(!addr_is_ip6(&iter_env->nat64_prefix_addr, - iter_env->nat64_prefix_addrlen)) { - log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix); - return 0; - } - if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) { - log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s", - nat64_prefix); - return 0; - } - - iter_env->supports_ipv6 = cfg->do_ip6; - iter_env->supports_ipv4 = cfg->do_ip4; - iter_env->use_nat64 = cfg->do_nat64; - iter_env->outbound_msg_retry = cfg->outbound_msg_retry; - iter_env->max_sent_count = cfg->max_sent_count; - iter_env->max_query_restarts = cfg->max_query_restarts; - return 1; -} - -/** filter out unsuitable targets - * @param iter_env: iterator environment with ipv6-support flag. - * @param env: module environment with infra cache. - * @param name: zone name - * @param namelen: length of name - * @param qtype: query type (host order). - * @param now: current time - * @param a: address in delegation point we are examining. - * @return an integer that signals the target suitability. - * as follows: - * -1: The address should be omitted from the list. - * Because: - * o The address is bogus (DNSSEC validation failure). - * o Listed as donotquery - * o is ipv6 but no ipv6 support (in operating system). - * o is ipv4 but no ipv4 support (in operating system). - * o is lame - * Otherwise, an rtt in milliseconds. - * 0 .. USEFUL_SERVER_TOP_TIMEOUT-1 - * The roundtrip time timeout estimate. less than 2 minutes. - * Note that util/rtt.c has a MIN_TIMEOUT of 50 msec, thus - * values 0 .. 49 are not used, unless that is changed. - * USEFUL_SERVER_TOP_TIMEOUT - * This value exactly is given for unresponsive blacklisted. - * USEFUL_SERVER_TOP_TIMEOUT+1 - * For non-blacklisted servers: huge timeout, but has traffic. - * USEFUL_SERVER_TOP_TIMEOUT*1 .. - * parent-side lame servers get this penalty. A dispreferential - * server. (lame in delegpt). - * USEFUL_SERVER_TOP_TIMEOUT*2 .. - * dnsseclame servers get penalty - * USEFUL_SERVER_TOP_TIMEOUT*3 .. - * recursion lame servers get penalty - * UNKNOWN_SERVER_NICENESS - * If no information is known about the server, this is - * returned. 376 msec or so. - * +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs. - * - * When a final value is chosen that is dnsseclame ; dnsseclameness checking - * is turned off (so we do not discard the reply). - * When a final value is chosen that is recursionlame; RD bit is set on query. - * Because of the numbers this means recursionlame also have dnssec lameness - * checking turned off. - */ -static int -iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, - struct delegpt_addr* a) -{ - int rtt, lame, reclame, dnsseclame; - if(a->bogus) - return -1; /* address of server is bogus */ - if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) { - log_addr(VERB_ALGO, "skip addr on the donotquery list", - &a->addr, a->addrlen); - return -1; /* server is on the donotquery list */ - } - if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) { - return -1; /* there is no ip6 available */ - } - if(!iter_env->supports_ipv4 && !iter_env->use_nat64 && - !addr_is_ip6(&a->addr, a->addrlen)) { - return -1; /* there is no ip4 available */ - } - /* check lameness - need zone , class info */ - if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, - name, namelen, qtype, &lame, &dnsseclame, &reclame, - &rtt, now)) { - log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen); - verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt, - lame?" LAME":"", - dnsseclame?" DNSSEC_LAME":"", - reclame?" REC_LAME":"", - a->lame?" ADDR_LAME":""); - if(lame) - return -1; /* server is lame */ - else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) - /* server is unresponsive, - * we used to return TOP_TIMEOUT, but fairly useless, - * because if == TOP_TIMEOUT is dropped because - * blacklisted later, instead, remove it here, so - * other choices (that are not blacklisted) can be - * tried */ - return -1; - /* select remainder from worst to best */ - else if(reclame) - return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */ - else if(dnsseclame || a->dnsseclame) - return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ - else if(a->lame) - return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */ - else return rtt; - } - /* no server information present */ - if(a->dnsseclame) - return UNKNOWN_SERVER_NICENESS+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ - else if(a->lame) - return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */ - return UNKNOWN_SERVER_NICENESS; -} - -/** lookup RTT information, and also store fastest rtt (if any) */ -static int -iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, - struct delegpt* dp, int* best_rtt, struct sock_list* blacklist, - size_t* num_suitable_results) -{ - int got_it = 0; - struct delegpt_addr* a; - *num_suitable_results = 0; - - if(dp->bogus) - return 0; /* NS bogus, all bogus, nothing found */ - for(a=dp->result_list; a; a = a->next_result) { - a->sel_rtt = iter_filter_unsuitable(iter_env, env, - name, namelen, qtype, now, a); - if(a->sel_rtt != -1) { - if(sock_list_find(blacklist, &a->addr, a->addrlen)) - a->sel_rtt += BLACKLIST_PENALTY; - - if(!got_it) { - *best_rtt = a->sel_rtt; - got_it = 1; - } else if(a->sel_rtt < *best_rtt) { - *best_rtt = a->sel_rtt; - } - (*num_suitable_results)++; - } - } - return got_it; -} - -/** compare two rtts, return -1, 0 or 1 */ -static int -rtt_compare(const void* x, const void* y) -{ - if(*(int*)x == *(int*)y) - return 0; - if(*(int*)x > *(int*)y) - return 1; - return -1; -} - -/** get RTT for the Nth fastest server */ -static int -nth_rtt(struct delegpt_addr* result_list, size_t num_results, size_t n) -{ - int rtt_band; - size_t i; - int* rtt_list, *rtt_index; - - if(num_results < 1 || n >= num_results) { - return -1; - } - - rtt_list = calloc(num_results, sizeof(int)); - if(!rtt_list) { - log_err("malloc failure: allocating rtt_list"); - return -1; - } - rtt_index = rtt_list; - - for(i=0; isel_rtt != -1) { - *rtt_index = result_list->sel_rtt; - rtt_index++; - } - result_list=result_list->next_result; - } - qsort(rtt_list, num_results, sizeof(*rtt_list), rtt_compare); - - log_assert(n > 0); - rtt_band = rtt_list[n-1]; - free(rtt_list); - - return rtt_band; -} - -/** filter the address list, putting best targets at front, - * returns number of best targets (or 0, no suitable targets) */ -static int -iter_filter_order(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, - struct delegpt* dp, int* selected_rtt, int open_target, - struct sock_list* blacklist, time_t prefetch) -{ - int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth; - int alllame = 0; - size_t num_results; - struct delegpt_addr* a, *n, *prev=NULL; - - /* fillup sel_rtt and find best rtt in the bunch */ - got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp, - &low_rtt, blacklist, &num_results); - if(got_num == 0) - return 0; - if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT && - /* If all missing (or not fully resolved) targets are lame, - * then use the remaining lame address. */ - ((delegpt_count_missing_targets(dp, &alllame) > 0 && !alllame) || - open_target > 0)) { - verbose(VERB_ALGO, "Bad choices, trying to get more choice"); - return 0; /* we want more choice. The best choice is a bad one. - return 0 to force the caller to fetch more */ - } - - if(env->cfg->fast_server_permil != 0 && prefetch == 0 && - num_results > env->cfg->fast_server_num && - ub_random_max(env->rnd, 1000) < env->cfg->fast_server_permil) { - /* the query is not prefetch, but for a downstream client, - * there are more servers available then the fastest N we want - * to choose from. Limit our choice to the fastest servers. */ - nth = nth_rtt(dp->result_list, num_results, - env->cfg->fast_server_num); - if(nth > 0) { - rtt_band = nth - low_rtt; - if(rtt_band > RTT_BAND) - rtt_band = RTT_BAND; - } - } - - got_num = 0; - a = dp->result_list; - while(a) { - /* skip unsuitable targets */ - if(a->sel_rtt == -1) { - prev = a; - a = a->next_result; - continue; - } - /* classify the server address and determine what to do */ - swap_to_front = 0; - if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) { - got_num++; - swap_to_front = 1; - } else if(a->sel_rttsel_rtt<=rtt_band) { - got_num++; - swap_to_front = 1; - } - /* swap to front if necessary, or move to next result */ - if(swap_to_front && prev) { - n = a->next_result; - prev->next_result = n; - a->next_result = dp->result_list; - dp->result_list = a; - a = n; - } else { - prev = a; - a = a->next_result; - } - } - *selected_rtt = low_rtt; - - if (env->cfg->prefer_ip6) { - int got_num6 = 0; - int low_rtt6 = 0; - int i; - int attempt = -1; /* filter to make sure addresses have - less attempts on them than the first, to force round - robin when all the IPv6 addresses fail */ - int num4ok = 0; /* number ip4 at low attempt count */ - int num4_lowrtt = 0; - prev = NULL; - a = dp->result_list; - for(i = 0; i < got_num; i++) { - if(!a) break; /* robustness */ - swap_to_front = 0; - if(a->addr.ss_family != AF_INET6 && attempt == -1) { - /* if we only have ip4 at low attempt count, - * then ip6 is failing, and we need to - * select one of the remaining IPv4 addrs */ - attempt = a->attempts; - num4ok++; - num4_lowrtt = a->sel_rtt; - } else if(a->addr.ss_family != AF_INET6 && attempt == a->attempts) { - num4ok++; - if(num4_lowrtt == 0 || a->sel_rtt < num4_lowrtt) { - num4_lowrtt = a->sel_rtt; - } - } - if(a->addr.ss_family == AF_INET6) { - if(attempt == -1) { - attempt = a->attempts; - } else if(a->attempts > attempt) { - break; - } - got_num6++; - swap_to_front = 1; - if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) { - low_rtt6 = a->sel_rtt; - } - } - /* swap to front if IPv6, or move to next result */ - if(swap_to_front && prev) { - n = a->next_result; - prev->next_result = n; - a->next_result = dp->result_list; - dp->result_list = a; - a = n; - } else { - prev = a; - a = a->next_result; - } - } - if(got_num6 > 0) { - got_num = got_num6; - *selected_rtt = low_rtt6; - } else if(num4ok > 0) { - got_num = num4ok; - *selected_rtt = num4_lowrtt; - } - } else if (env->cfg->prefer_ip4) { - int got_num4 = 0; - int low_rtt4 = 0; - int i; - int attempt = -1; /* filter to make sure addresses have - less attempts on them than the first, to force round - robin when all the IPv4 addresses fail */ - int num6ok = 0; /* number ip6 at low attempt count */ - int num6_lowrtt = 0; - prev = NULL; - a = dp->result_list; - for(i = 0; i < got_num; i++) { - if(!a) break; /* robustness */ - swap_to_front = 0; - if(a->addr.ss_family != AF_INET && attempt == -1) { - /* if we only have ip6 at low attempt count, - * then ip4 is failing, and we need to - * select one of the remaining IPv6 addrs */ - attempt = a->attempts; - num6ok++; - num6_lowrtt = a->sel_rtt; - } else if(a->addr.ss_family != AF_INET && attempt == a->attempts) { - num6ok++; - if(num6_lowrtt == 0 || a->sel_rtt < num6_lowrtt) { - num6_lowrtt = a->sel_rtt; - } - } - if(a->addr.ss_family == AF_INET) { - if(attempt == -1) { - attempt = a->attempts; - } else if(a->attempts > attempt) { - break; - } - got_num4++; - swap_to_front = 1; - if(low_rtt4 == 0 || a->sel_rtt < low_rtt4) { - low_rtt4 = a->sel_rtt; - } - } - /* swap to front if IPv4, or move to next result */ - if(swap_to_front && prev) { - n = a->next_result; - prev->next_result = n; - a->next_result = dp->result_list; - dp->result_list = a; - a = n; - } else { - prev = a; - a = a->next_result; - } - } - if(got_num4 > 0) { - got_num = got_num4; - *selected_rtt = low_rtt4; - } else if(num6ok > 0) { - got_num = num6ok; - *selected_rtt = num6_lowrtt; - } - } - return got_num; -} - -struct delegpt_addr* -iter_server_selection(struct iter_env* iter_env, - struct module_env* env, struct delegpt* dp, - uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame, - int* chase_to_rd, int open_target, struct sock_list* blacklist, - time_t prefetch) -{ - int sel; - int selrtt; - struct delegpt_addr* a, *prev; - int num = iter_filter_order(iter_env, env, name, namelen, qtype, - *env->now, dp, &selrtt, open_target, blacklist, prefetch); - - if(num == 0) - return NULL; - verbose(VERB_ALGO, "selrtt %d", selrtt); - if(selrtt > BLACKLIST_PENALTY) { - if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*3) { - verbose(VERB_ALGO, "chase to " - "blacklisted recursion lame server"); - *chase_to_rd = 1; - } - if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*2) { - verbose(VERB_ALGO, "chase to " - "blacklisted dnssec lame server"); - *dnssec_lame = 1; - } - } else { - if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*3) { - verbose(VERB_ALGO, "chase to recursion lame server"); - *chase_to_rd = 1; - } - if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) { - verbose(VERB_ALGO, "chase to dnssec lame server"); - *dnssec_lame = 1; - } - if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) { - verbose(VERB_ALGO, "chase to blacklisted lame server"); - return NULL; - } - } - - if(num == 1) { - a = dp->result_list; - if(++a->attempts < iter_env->outbound_msg_retry) - return a; - dp->result_list = a->next_result; - return a; - } - - /* randomly select a target from the list */ - log_assert(num > 1); - /* grab secure random number, to pick unexpected server. - * also we need it to be threadsafe. */ - sel = ub_random_max(env->rnd, num); - a = dp->result_list; - prev = NULL; - while(sel > 0 && a) { - prev = a; - a = a->next_result; - sel--; - } - if(!a) /* robustness */ - return NULL; - if(++a->attempts < iter_env->outbound_msg_retry) - return a; - /* remove it from the delegation point result list */ - if(prev) - prev->next_result = a->next_result; - else dp->result_list = a->next_result; - return a; -} - -struct dns_msg* -dns_alloc_msg(sldns_buffer* pkt, struct msg_parse* msg, - struct regional* region) -{ - struct dns_msg* m = (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(!m) - return NULL; - memset(m, 0, sizeof(*m)); - if(!parse_create_msg(pkt, msg, NULL, &m->qinfo, &m->rep, region)) { - log_err("malloc failure: allocating incoming dns_msg"); - return NULL; - } - return m; -} - -struct dns_msg* -dns_copy_msg(struct dns_msg* from, struct regional* region) -{ - struct dns_msg* m = (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(!m) - return NULL; - m->qinfo = from->qinfo; - if(!(m->qinfo.qname = regional_alloc_init(region, from->qinfo.qname, - from->qinfo.qname_len))) - return NULL; - if(!(m->rep = reply_info_copy(from->rep, NULL, region))) - return NULL; - return m; -} - -void -iter_dns_store(struct module_env* env, struct query_info* msgqinf, - struct reply_info* msgrep, int is_referral, time_t leeway, int pside, - struct regional* region, uint16_t flags, time_t qstarttime) -{ - if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, - pside, region, flags, qstarttime)) - log_err("out of memory: cannot store data in cache"); -} - -int -iter_ns_probability(struct ub_randstate* rnd, int n, int m) -{ - int sel; - if(n == m) /* 100% chance */ - return 1; - /* we do not need secure random numbers here, but - * we do need it to be threadsafe, so we use this */ - sel = ub_random_max(rnd, m); - return (sel < n); -} - -/** detect dependency cycle for query and target */ -static int -causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen, - uint16_t t, uint16_t c) -{ - struct query_info qinf; - qinf.qname = name; - qinf.qname_len = namelen; - qinf.qtype = t; - qinf.qclass = c; - qinf.local_alias = NULL; - fptr_ok(fptr_whitelist_modenv_detect_cycle( - qstate->env->detect_cycle)); - return (*qstate->env->detect_cycle)(qstate, &qinf, - (uint16_t)(BIT_RD|BIT_CD), qstate->is_priming, - qstate->is_valrec); -} - -void -iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) -{ - struct delegpt_ns* ns; - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->resolved) - continue; - /* see if this ns as target causes dependency cycle */ - if(causes_cycle(qstate, ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) || - causes_cycle(qstate, ns->name, ns->namelen, - LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { - log_nametypeclass(VERB_QUERY, "skipping target due " - "to dependency cycle (harden-glue: no may " - "fix some of the cycles)", - ns->name, LDNS_RR_TYPE_A, - qstate->qinfo.qclass); - ns->resolved = 1; - } - } -} - -void -iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) -{ - struct delegpt_ns* ns; - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->done_pside4 && ns->done_pside6) - continue; - /* see if this ns as target causes dependency cycle */ - if(causes_cycle(qstate, ns->name, ns->namelen, - LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { - log_nametypeclass(VERB_QUERY, "skipping target due " - "to dependency cycle", ns->name, - LDNS_RR_TYPE_A, qstate->qinfo.qclass); - ns->done_pside4 = 1; - } - if(causes_cycle(qstate, ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass)) { - log_nametypeclass(VERB_QUERY, "skipping target due " - "to dependency cycle", ns->name, - LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass); - ns->done_pside6 = 1; - } - } -} - -int -iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, - struct delegpt* dp, int supports_ipv4, int supports_ipv6, - int use_nat64) -{ - struct delegpt_ns* ns; - struct delegpt_addr* a; - - if(supports_ipv6 && use_nat64) - supports_ipv4 = 1; - - /* check: - * o RD qflag is on. - * o no addresses are provided. - * o all NS items are required glue. - * OR - * o RD qflag is on. - * o no addresses are provided. - * o the query is for one of the nameservers in dp, - * and that nameserver is a glue-name for this dp. - */ - if(!(qflags&BIT_RD)) - return 0; - /* either available or unused targets, - * if they exist, the dp is not useless. */ - for(a = dp->usable_list; a; a = a->next_usable) { - if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4) - return 0; - else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6) - return 0; - } - for(a = dp->result_list; a; a = a->next_result) { - if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4) - return 0; - else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6) - return 0; - } - - /* see if query is for one of the nameservers, which is glue */ - if( ((qinfo->qtype == LDNS_RR_TYPE_A && supports_ipv4) || - (qinfo->qtype == LDNS_RR_TYPE_AAAA && supports_ipv6)) && - dname_subdomain_c(qinfo->qname, dp->name) && - delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len)) - return 1; - - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->resolved) /* skip failed targets */ - continue; - if(!dname_subdomain_c(ns->name, dp->name)) - return 0; /* one address is not required glue */ - } - return 1; -} - -int -iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo) -{ - struct trust_anchor* a; - if(!env || !env->anchors || !qinfo || !qinfo->qname) - return 0; - /* a trust anchor exists above the name? */ - if((a=anchors_lookup(env->anchors, qinfo->qname, qinfo->qname_len, - qinfo->qclass))) { - if(a->numDS == 0 && a->numDNSKEY == 0) { - /* insecure trust point */ - lock_basic_unlock(&a->lock); - return 0; - } - lock_basic_unlock(&a->lock); - return 1; - } - /* no trust anchor above it. */ - return 0; -} - -int -iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, - struct dns_msg* msg, uint16_t dclass) -{ - struct trust_anchor* a; - /* information not available, !env->anchors can be common */ - if(!env || !env->anchors || !dp || !dp->name) - return 0; - /* a trust anchor exists with this name, RRSIGs expected */ - if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen, - dclass))) { - if(a->numDS == 0 && a->numDNSKEY == 0) { - /* insecure trust point */ - lock_basic_unlock(&a->lock); - return 0; - } - lock_basic_unlock(&a->lock); - return 1; - } - /* see if DS rrset was given, in AUTH section */ - if(msg && msg->rep && - reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_DS, dclass)) - return 1; - /* look in key cache */ - if(env->key_cache) { - struct key_entry_key* kk = key_cache_obtain(env->key_cache, - dp->name, dp->namelen, dclass, env->scratch, *env->now); - if(kk) { - if(query_dname_compare(kk->name, dp->name) == 0) { - if(key_entry_isgood(kk) || key_entry_isbad(kk)) { - regional_free_all(env->scratch); - return 1; - } else if(key_entry_isnull(kk)) { - regional_free_all(env->scratch); - return 0; - } - } - regional_free_all(env->scratch); - } - } - return 0; -} - -int -iter_msg_has_dnssec(struct dns_msg* msg) -{ - size_t i; - if(!msg || !msg->rep) - return 0; - for(i=0; irep->an_numrrsets + msg->rep->ns_numrrsets; i++) { - if(((struct packed_rrset_data*)msg->rep->rrsets[i]-> - entry.data)->rrsig_count > 0) - return 1; - } - /* empty message has no DNSSEC info, with DNSSEC the reply is - * not empty (NSEC) */ - return 0; -} - -int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, - enum response_type type, uint16_t dclass) -{ - if(!msg || !dp || !msg->rep || !dp->name) - return 0; - /* SOA RRset - always from reply zone */ - if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_SOA, dclass) || - reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_SOA, dclass)) - return 1; - if(type == RESPONSE_TYPE_REFERRAL) { - size_t i; - /* if it adds a single label, i.e. we expect .com, - * and referral to example.com. NS ... , then origin zone - * is .com. For a referral to sub.example.com. NS ... then - * we do not know, since example.com. may be in between. */ - for(i=0; irep->an_numrrsets+msg->rep->ns_numrrsets; - i++) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS && - ntohs(s->rk.rrset_class) == dclass) { - int l = dname_count_labels(s->rk.dname); - if(l == dp->namelabs + 1 && - dname_strict_subdomain(s->rk.dname, - l, dp->name, dp->namelabs)) - return 1; - } - } - return 0; - } - log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME); - /* not a referral, and not lame delegation (upwards), so, - * any NS rrset must be from the zone itself */ - if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_NS, dclass) || - reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_NS, dclass)) - return 1; - /* a DNSKEY set is expected at the zone apex as well */ - /* this is for 'minimal responses' for DNSKEYs */ - if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, - LDNS_RR_TYPE_DNSKEY, dclass)) - return 1; - return 0; -} - -/** - * check equality of two rrsets - * @param k1: rrset - * @param k2: rrset - * @return true if equal - */ -static int -rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) -{ - struct packed_rrset_data* d1 = (struct packed_rrset_data*) - k1->entry.data; - struct packed_rrset_data* d2 = (struct packed_rrset_data*) - k2->entry.data; - size_t i, t; - if(k1->rk.dname_len != k2->rk.dname_len || - k1->rk.flags != k2->rk.flags || - k1->rk.type != k2->rk.type || - k1->rk.rrset_class != k2->rk.rrset_class || - query_dname_compare(k1->rk.dname, k2->rk.dname) != 0) - return 0; - if( /* do not check ttl: d1->ttl != d2->ttl || */ - d1->count != d2->count || - d1->rrsig_count != d2->rrsig_count || - d1->trust != d2->trust || - d1->security != d2->security) - return 0; - t = d1->count + d1->rrsig_count; - for(i=0; irr_len[i] != d2->rr_len[i] || - /* no ttl check: d1->rr_ttl[i] != d2->rr_ttl[i] ||*/ - memcmp(d1->rr_data[i], d2->rr_data[i], - d1->rr_len[i]) != 0) - return 0; - } - return 1; -} - -/** compare rrsets and sort canonically. Compares rrset name, type, class. - * return 0 if equal, +1 if x > y, and -1 if x < y. - */ -static int -rrset_canonical_sort_cmp(const void* x, const void* y) -{ - struct ub_packed_rrset_key* rrx = *(struct ub_packed_rrset_key**)x; - struct ub_packed_rrset_key* rry = *(struct ub_packed_rrset_key**)y; - int r = dname_canonical_compare(rrx->rk.dname, rry->rk.dname); - if(r != 0) - return r; - if(rrx->rk.type != rry->rk.type) { - if(ntohs(rrx->rk.type) > ntohs(rry->rk.type)) - return 1; - else return -1; - } - if(rrx->rk.rrset_class != rry->rk.rrset_class) { - if(ntohs(rrx->rk.rrset_class) > ntohs(rry->rk.rrset_class)) - return 1; - else return -1; - } - return 0; -} - -int -reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region) -{ - size_t i; - struct ub_packed_rrset_key** sorted_p, **sorted_q; - if(p->flags != q->flags || - p->qdcount != q->qdcount || - /* do not check TTL, this may differ */ - /* - p->ttl != q->ttl || - p->prefetch_ttl != q->prefetch_ttl || - */ - p->security != q->security || - p->an_numrrsets != q->an_numrrsets || - p->ns_numrrsets != q->ns_numrrsets || - p->ar_numrrsets != q->ar_numrrsets || - p->rrset_count != q->rrset_count) - return 0; - /* sort the rrsets in the authority and additional sections before - * compare, the query and answer sections are ordered in the sequence - * they should have (eg. one after the other for aliases). */ - sorted_p = (struct ub_packed_rrset_key**)regional_alloc_init( - region, p->rrsets, sizeof(*sorted_p)*p->rrset_count); - if(!sorted_p) return 0; - log_assert(p->an_numrrsets + p->ns_numrrsets + p->ar_numrrsets <= - p->rrset_count); - qsort(sorted_p + p->an_numrrsets, p->ns_numrrsets, - sizeof(*sorted_p), rrset_canonical_sort_cmp); - qsort(sorted_p + p->an_numrrsets + p->ns_numrrsets, p->ar_numrrsets, - sizeof(*sorted_p), rrset_canonical_sort_cmp); - - sorted_q = (struct ub_packed_rrset_key**)regional_alloc_init( - region, q->rrsets, sizeof(*sorted_q)*q->rrset_count); - if(!sorted_q) { - regional_free_all(region); - return 0; - } - log_assert(q->an_numrrsets + q->ns_numrrsets + q->ar_numrrsets <= - q->rrset_count); - qsort(sorted_q + q->an_numrrsets, q->ns_numrrsets, - sizeof(*sorted_q), rrset_canonical_sort_cmp); - qsort(sorted_q + q->an_numrrsets + q->ns_numrrsets, q->ar_numrrsets, - sizeof(*sorted_q), rrset_canonical_sort_cmp); - - /* compare the rrsets */ - for(i=0; irrset_count; i++) { - if(!rrset_equal(sorted_p[i], sorted_q[i])) { - if(!rrset_canonical_equal(region, sorted_p[i], - sorted_q[i])) { - regional_free_all(region); - return 0; - } - } - } - regional_free_all(region); - return 1; -} - -void -caps_strip_reply(struct reply_info* rep) -{ - size_t i; - if(!rep) return; - /* see if message is a referral, in which case the additional and - * NS record cannot be removed */ - /* referrals have the AA flag unset (strict check, not elsewhere in - * unbound, but for 0x20 this is very convenient). */ - if(!(rep->flags&BIT_AA)) - return; - /* remove the additional section from the reply */ - if(rep->ar_numrrsets != 0) { - verbose(VERB_ALGO, "caps fallback: removing additional section"); - rep->rrset_count -= rep->ar_numrrsets; - rep->ar_numrrsets = 0; - } - /* is there an NS set in the authority section to remove? */ - /* the failure case (Cisco firewalls) only has one rrset in authsec */ - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) { - /* remove NS rrset and break from loop (loop limits - * have changed) */ - /* move last rrset into this position (there is no - * additional section any more) */ - verbose(VERB_ALGO, "caps fallback: removing NS rrset"); - if(i < rep->rrset_count-1) - rep->rrsets[i]=rep->rrsets[rep->rrset_count-1]; - rep->rrset_count --; - rep->ns_numrrsets --; - break; - } - } -} - -int caps_failed_rcode(struct reply_info* rep) -{ - return !(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN); -} - -void -iter_store_parentside_rrset(struct module_env* env, - struct ub_packed_rrset_key* rrset) -{ - struct rrset_ref ref; - rrset = packed_rrset_copy_alloc(rrset, env->alloc, *env->now); - if(!rrset) { - log_err("malloc failure in store_parentside_rrset"); - return; - } - rrset->rk.flags |= PACKED_RRSET_PARENT_SIDE; - rrset->entry.hash = rrset_key_hash(&rrset->rk); - ref.key = rrset; - ref.id = rrset->id; - /* ignore ret: if it was in the cache, ref updated */ - (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now); -} - -/** fetch NS record from reply, if any */ -static struct ub_packed_rrset_key* -reply_get_NS_rrset(struct reply_info* rep) -{ - size_t i; - for(i=0; irrset_count; i++) { - if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NS)) { - return rep->rrsets[i]; - } - } - return NULL; -} - -void -iter_store_parentside_NS(struct module_env* env, struct reply_info* rep) -{ - struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep); - if(rrset) { - log_rrset_key(VERB_ALGO, "store parent-side NS", rrset); - iter_store_parentside_rrset(env, rrset); - } -} - -void iter_store_parentside_neg(struct module_env* env, - struct query_info* qinfo, struct reply_info* rep) -{ - /* TTL: NS from referral in iq->deleg_msg, - * or first RR from iq->response, - * or servfail5secs if !iq->response */ - time_t ttl = NORR_TTL; - struct ub_packed_rrset_key* neg; - struct packed_rrset_data* newd; - if(rep) { - struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep); - if(!rrset && rep->rrset_count != 0) rrset = rep->rrsets[0]; - if(rrset) ttl = ub_packed_rrset_ttl(rrset); - } - /* create empty rrset to store */ - neg = (struct ub_packed_rrset_key*)regional_alloc(env->scratch, - sizeof(struct ub_packed_rrset_key)); - if(!neg) { - log_err("out of memory in store_parentside_neg"); - return; - } - memset(&neg->entry, 0, sizeof(neg->entry)); - neg->entry.key = neg; - neg->rk.type = htons(qinfo->qtype); - neg->rk.rrset_class = htons(qinfo->qclass); - neg->rk.flags = 0; - neg->rk.dname = regional_alloc_init(env->scratch, qinfo->qname, - qinfo->qname_len); - if(!neg->rk.dname) { - log_err("out of memory in store_parentside_neg"); - return; - } - neg->rk.dname_len = qinfo->qname_len; - neg->entry.hash = rrset_key_hash(&neg->rk); - newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch, - sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)); - if(!newd) { - log_err("out of memory in store_parentside_neg"); - return; - } - neg->entry.data = newd; - newd->ttl = ttl; - /* entry must have one RR, otherwise not valid in cache. - * put in one RR with empty rdata: those are ignored as nameserver */ - newd->count = 1; - newd->rrsig_count = 0; - newd->trust = rrset_trust_ans_noAA; - newd->rr_len = (size_t*)((uint8_t*)newd + - sizeof(struct packed_rrset_data)); - newd->rr_len[0] = 0 /* zero len rdata */ + sizeof(uint16_t); - packed_rrset_ptr_fixup(newd); - newd->rr_ttl[0] = newd->ttl; - sldns_write_uint16(newd->rr_data[0], 0 /* zero len rdata */); - /* store it */ - log_rrset_key(VERB_ALGO, "store parent-side negative", neg); - iter_store_parentside_rrset(env, neg); -} - -int -iter_lookup_parent_NS_from_cache(struct module_env* env, struct delegpt* dp, - struct regional* region, struct query_info* qinfo) -{ - struct ub_packed_rrset_key* akey; - akey = rrset_cache_lookup(env->rrset_cache, dp->name, - dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass, - PACKED_RRSET_PARENT_SIDE, *env->now, 0); - if(akey) { - log_rrset_key(VERB_ALGO, "found parent-side NS in cache", akey); - dp->has_parent_side_NS = 1; - /* and mark the new names as lame */ - if(!delegpt_rrset_add_ns(dp, region, akey, 1)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } - lock_rw_unlock(&akey->entry.lock); - } - return 1; -} - -int iter_lookup_parent_glue_from_cache(struct module_env* env, - struct delegpt* dp, struct regional* region, struct query_info* qinfo) -{ - struct ub_packed_rrset_key* akey; - struct delegpt_ns* ns; - size_t num = delegpt_count_targets(dp); - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE) - continue; - ns->cache_lookup_count++; - /* get cached parentside A */ - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass, - PACKED_RRSET_PARENT_SIDE, *env->now, 0); - if(akey) { - log_rrset_key(VERB_ALGO, "found parent-side", akey); - ns->done_pside4 = 1; - /* a negative-cache-element has no addresses it adds */ - if(!delegpt_add_rrset_A(dp, region, akey, 1, NULL)) - log_err("malloc failure in lookup_parent_glue"); - lock_rw_unlock(&akey->entry.lock); - } - /* get cached parentside AAAA */ - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qinfo->qclass, - PACKED_RRSET_PARENT_SIDE, *env->now, 0); - if(akey) { - log_rrset_key(VERB_ALGO, "found parent-side", akey); - ns->done_pside6 = 1; - /* a negative-cache-element has no addresses it adds */ - if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, NULL)) - log_err("malloc failure in lookup_parent_glue"); - lock_rw_unlock(&akey->entry.lock); - } - } - /* see if new (but lame) addresses have become available */ - return delegpt_count_targets(dp) != num; -} - -int -iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, - uint16_t* c) -{ - uint16_t c1 = *c, c2 = *c; - int r1 = hints_next_root(hints, &c1); - int r2 = forwards_next_root(fwd, &c2); - if(!r1 && !r2) /* got none, end of list */ - return 0; - else if(!r1) /* got one, return that */ - *c = c2; - else if(!r2) - *c = c1; - else if(c1 < c2) /* got both take smallest */ - *c = c1; - else *c = c2; - return 1; -} - -void -iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z) -{ - /* Only the DS record for the delegation itself is expected. - * We allow DS for everything between the bailiwick and the - * zonecut, thus DS records must be at or above the zonecut. - * And the DS records must be below the server authority zone. - * The answer section is already scrubbed. */ - size_t i = msg->rep->an_numrrsets; - while(i < (msg->rep->an_numrrsets + msg->rep->ns_numrrsets)) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS && - (!ns || !dname_subdomain_c(ns->rk.dname, s->rk.dname) - || query_dname_compare(z, s->rk.dname) == 0)) { - log_nametypeclass(VERB_ALGO, "removing irrelevant DS", - s->rk.dname, ntohs(s->rk.type), - ntohs(s->rk.rrset_class)); - memmove(msg->rep->rrsets+i, msg->rep->rrsets+i+1, - sizeof(struct ub_packed_rrset_key*) * - (msg->rep->rrset_count-i-1)); - msg->rep->ns_numrrsets--; - msg->rep->rrset_count--; - /* stay at same i, but new record */ - continue; - } - i++; - } -} - -void -iter_scrub_nxdomain(struct dns_msg* msg) -{ - if(msg->rep->an_numrrsets == 0) - return; - - memmove(msg->rep->rrsets, msg->rep->rrsets+msg->rep->an_numrrsets, - sizeof(struct ub_packed_rrset_key*) * - (msg->rep->rrset_count-msg->rep->an_numrrsets)); - msg->rep->rrset_count -= msg->rep->an_numrrsets; - msg->rep->an_numrrsets = 0; -} - -void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry) -{ - struct delegpt_addr* a; - for(a=dp->target_list; a; a = a->next_target) { - if(a->attempts >= outbound_msg_retry) { - /* add back to result list */ - delegpt_add_to_result_list(dp, a); - } - if(a->attempts > d) - a->attempts -= d; - else a->attempts = 0; - } -} - -void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old, - int outbound_msg_retry) -{ - struct delegpt_addr* a, *o, *prev; - for(a=dp->target_list; a; a = a->next_target) { - o = delegpt_find_addr(old, &a->addr, a->addrlen); - if(o) { - log_addr(VERB_ALGO, "copy attempt count previous dp", - &a->addr, a->addrlen); - a->attempts = o->attempts; - } - } - prev = NULL; - a = dp->usable_list; - while(a) { - if(a->attempts >= outbound_msg_retry) { - log_addr(VERB_ALGO, "remove from usable list dp", - &a->addr, a->addrlen); - /* remove from result list */ - if(prev) - prev->next_usable = a->next_usable; - else dp->usable_list = a->next_usable; - /* prev stays the same */ - a = a->next_usable; - continue; - } - prev = a; - a = a->next_usable; - } -} - -int -iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp) -{ - /* if for query example.com, there is example.com SOA or a subdomain - * of example.com, then we are too low and need to fetch NS. */ - size_t i; - /* if we have a DNAME or CNAME we are probably wrong */ - /* if we have a qtype DS in the answer section, its fine */ - for(i=0; i < msg->rep->an_numrrsets; i++) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME || - ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { - /* not the right answer, maybe too low, check the - * RRSIG signer name (if there is any) for a hint - * that it is from the dp zone anyway */ - uint8_t* sname; - size_t slen; - val_find_rrset_signer(s, &sname, &slen); - if(sname && query_dname_compare(dp->name, sname)==0) - return 0; /* it is fine, from the right dp */ - return 1; - } - if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS) - return 0; /* fine, we have a DS record */ - } - for(i=msg->rep->an_numrrsets; - i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) { - struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) { - if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname)) - return 1; /* point is too low */ - if(query_dname_compare(s->rk.dname, dp->name)==0) - return 0; /* right dp */ - } - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC || - ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - uint8_t* sname; - size_t slen; - val_find_rrset_signer(s, &sname, &slen); - if(sname && query_dname_compare(dp->name, sname)==0) - return 0; /* it is fine, from the right dp */ - return 1; - } - } - /* we do not know */ - return 1; -} - -int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp) -{ - /* no delegation point, do not see how we can go down, - * robust check, it should really exist */ - if(!dp) return 0; - - /* see if dp equals the qname, then we cannot go down further */ - if(query_dname_compare(qinfo->qname, dp->name) == 0) - return 0; - /* if dp is one label above the name we also cannot go down further */ - if(dname_count_labels(qinfo->qname) == dp->namelabs+1) - return 0; - return 1; -} - -int -iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf, - uint8_t** retdpname, size_t* retdpnamelen) -{ - struct iter_hints_stub *stub; - struct delegpt *dp; - - /* Check for stub. */ - stub = hints_lookup_stub(qstate->env->hints, qinf->qname, - qinf->qclass, NULL); - dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass); - - /* see if forward or stub is more pertinent */ - if(stub && stub->dp && dp) { - if(dname_strict_subdomain(dp->name, dp->namelabs, - stub->dp->name, stub->dp->namelabs)) { - stub = NULL; /* ignore stub, forward is lower */ - } else { - dp = NULL; /* ignore forward, stub is lower */ - } - } - - /* check stub */ - if (stub != NULL && stub->dp != NULL) { - if(stub->dp->no_cache) { - char qname[255+1]; - char dpname[255+1]; - dname_str(qinf->qname, qname); - dname_str(stub->dp->name, dpname); - verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname); - } - if(retdpname) { - *retdpname = stub->dp->name; - *retdpnamelen = stub->dp->namelen; - } - return (stub->dp->no_cache); - } - - /* Check for forward. */ - if (dp) { - if(dp->no_cache) { - char qname[255+1]; - char dpname[255+1]; - dname_str(qinf->qname, qname); - dname_str(dp->name, dpname); - verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname); - } - if(retdpname) { - *retdpname = dp->name; - *retdpnamelen = dp->namelen; - } - return (dp->no_cache); - } - if(retdpname) { - *retdpname = NULL; - *retdpnamelen = 0; - } - return 0; -} - -void iterator_set_ip46_support(struct module_stack* mods, - struct module_env* env, struct outside_network* outnet) -{ - int m = modstack_find(mods, "iterator"); - struct iter_env* ie = NULL; - if(m == -1) - return; - ie = (struct iter_env*)env->modinfo[m]; - if(outnet->pending == NULL) - return; /* we are in testbound, no rbtree for UDP */ - if(outnet->num_ip4 == 0) - ie->supports_ipv4 = 0; - if(outnet->num_ip6 == 0) - ie->supports_ipv6 = 0; -} diff --git a/crates/libunbound-sys/unbound/iterator/iter_utils.h b/crates/libunbound-sys/unbound/iterator/iter_utils.h deleted file mode 100644 index fa860fa6..00000000 --- a/crates/libunbound-sys/unbound/iterator/iter_utils.h +++ /dev/null @@ -1,427 +0,0 @@ -/* - * iterator/iter_utils.h - iterative resolver module utility functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist the iterator module. - * Configuration options. Forward zones. - */ - -#ifndef ITERATOR_ITER_UTILS_H -#define ITERATOR_ITER_UTILS_H -#include "iterator/iter_resptype.h" -struct sldns_buffer; -struct iter_env; -struct iter_hints; -struct iter_forwards; -struct config_file; -struct module_env; -struct delegpt_addr; -struct delegpt; -struct regional; -struct msg_parse; -struct ub_randstate; -struct query_info; -struct reply_info; -struct module_qstate; -struct sock_list; -struct ub_packed_rrset_key; -struct module_stack; -struct outside_network; - -/* max number of lookups in the cache for target nameserver names. - * This stops, for large delegations, N*N lookups in the cache. */ -#define ITERATOR_NAME_CACHELOOKUP_MAX 3 -/* max number of lookups in the cache for parentside glue for nameserver names - * This stops, for larger delegations, N*N lookups in the cache. - * It is a little larger than the nonpside max, so it allows a couple extra - * lookups of parent side glue. */ -#define ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE 5 - -/** - * Process config options and set iterator module state. - * Sets default values if no config is found. - * @param iter_env: iterator module state. - * @param cfg: config options. - * @return 0 on error. - */ -int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg); - -/** - * Select a valid, nice target to send query to. - * Sorting and removing unsuitable targets is combined. - * - * @param iter_env: iterator module global state, with ip6 enabled and - * do-not-query-addresses. - * @param env: environment with infra cache (lameness, rtt info). - * @param dp: delegation point with result list. - * @param name: zone name (for lameness check). - * @param namelen: length of name. - * @param qtype: query type that we want to send. - * @param dnssec_lame: set to 1, if a known dnssec-lame server is selected - * these are not preferred, but are used as a last resort. - * @param chase_to_rd: set to 1 if a known recursion lame server is selected - * these are not preferred, but are used as a last resort. - * @param open_target: number of currently outstanding target queries. - * If we wait for these, perhaps more server addresses become available. - * @param blacklist: the IP blacklist to use. - * @param prefetch: if not 0, prefetch is in use for this query. - * This means the query can have different timing, because prefetch is - * not waited upon by the downstream client, and thus a good time to - * perform exploration of other targets. - * @return best target or NULL if no target. - * if not null, that target is removed from the result list in the dp. - */ -struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, - struct module_env* env, struct delegpt* dp, uint8_t* name, - size_t namelen, uint16_t qtype, int* dnssec_lame, - int* chase_to_rd, int open_target, struct sock_list* blacklist, - time_t prefetch); - -/** - * Allocate dns_msg from parsed msg, in regional. - * @param pkt: packet. - * @param msg: parsed message (cleaned and ready for regional allocation). - * @param regional: regional to use for allocation. - * @return newly allocated dns_msg, or NULL on memory error. - */ -struct dns_msg* dns_alloc_msg(struct sldns_buffer* pkt, struct msg_parse* msg, - struct regional* regional); - -/** - * Copy a dns_msg to this regional. - * @param from: dns message, also in regional. - * @param regional: regional to use for allocation. - * @return newly allocated dns_msg, or NULL on memory error. - */ -struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional); - -/** - * Allocate a dns_msg with malloc/alloc structure and store in dns cache. - * @param env: environment, with alloc structure and dns cache. - * @param qinf: query info, the query for which answer is stored. - * @param rep: reply in dns_msg from dns_alloc_msg for example. - * @param is_referral: If true, then the given message to be stored is a - * referral. The cache implementation may use this as a hint. - * @param leeway: prefetch TTL leeway to expire old rrsets quicker. - * @param pside: true if dp is parentside, thus message is 'fresh' and NS - * can be prefetch-updates. - * @param region: to copy modified (cache is better) rrs back to. - * @param flags: with BIT_CD for dns64 AAAA translated queries. - * @param qstarttime: time of query start. - * return void, because we are not interested in alloc errors, - * the iterator and validator can operate on the results in their - * scratch space (the qstate.region) and are not dependent on the cache. - * It is useful to log the alloc failure (for the server operator), - * but the query resolution can continue without cache storage. - */ -void iter_dns_store(struct module_env* env, struct query_info* qinf, - struct reply_info* rep, int is_referral, time_t leeway, int pside, - struct regional* region, uint16_t flags, time_t qstarttime); - -/** - * Select randomly with n/m probability. - * For shuffle NS records for address fetching. - * @param rnd: random table - * @param n: probability. - * @param m: divisor for probability. - * @return true with n/m probability. - */ -int iter_ns_probability(struct ub_randstate* rnd, int n, int m); - -/** - * Mark targets that result in a dependency cycle as done, so they - * will not get selected as targets. - * @param qstate: query state. - * @param dp: delegpt to mark ns in. - */ -void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp); - -/** - * Mark targets that result in a dependency cycle as done, so they - * will not get selected as targets. For the parent-side lookups. - * @param qstate: query state. - * @param dp: delegpt to mark ns in. - */ -void iter_mark_pside_cycle_targets(struct module_qstate* qstate, - struct delegpt* dp); - -/** - * See if delegation is useful or offers immediately no targets for - * further recursion. - * @param qinfo: query name and type - * @param qflags: query flags with RD flag - * @param dp: delegpt to check. - * @param supports_ipv4: if we support ipv4 for lookups to the target. - * if not, then the IPv4 addresses are useless. - * @param supports_ipv6: if we support ipv6 for lookups to the target. - * if not, then the IPv6 addresses are useless. - * @param use_nat64: if we support NAT64 for lookups to the target. - * if yes, IPv4 addresses are useful even if we don't support IPv4. - * @return true if dp is useless. - */ -int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, - struct delegpt* dp, int supports_ipv4, int supports_ipv6, - int use_nat64); - -/** - * See if qname has DNSSEC needs. This is true if there is a trust anchor above - * it. Whether there is an insecure delegation to the data is unknown. - * @param env: environment with anchors. - * @param qinfo: query name and class. - * @return true if trust anchor above qname, false if no anchor or insecure - * point above qname. - */ -int iter_qname_indicates_dnssec(struct module_env* env, - struct query_info *qinfo); - -/** - * See if delegation is expected to have DNSSEC information (RRSIGs) in - * its answers, or not. Inspects delegation point (name), trust anchors, - * and delegation message (DS RRset) to determine this. - * @param env: module env with trust anchors. - * @param dp: delegation point. - * @param msg: delegation message, with DS if a secure referral. - * @param dclass: class of query. - * @return 1 if dnssec is expected, 0 if not or insecure point above qname. - */ -int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, - struct dns_msg* msg, uint16_t dclass); - -/** - * See if a message contains DNSSEC. - * This is examined by looking for RRSIGs. With DNSSEC a valid answer, - * nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth - * sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records. - * @param msg: message to examine. - * @return true if DNSSEC information was found. - */ -int iter_msg_has_dnssec(struct dns_msg* msg); - -/** - * See if a message is known to be from a certain zone. - * This looks for SOA or NS rrsets, for answers. - * For referrals, when one label is delegated, the zone is detected. - * Does not look at signatures. - * @param msg: the message to inspect. - * @param dp: delegation point with zone name to look for. - * @param type: type of message. - * @param dclass: class of query. - * @return true if message is certain to be from zone in dp->name. - * false if not sure (empty msg), or not from the zone. - */ -int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, - enum response_type type, uint16_t dclass); - -/** - * Check if two replies are equal - * For fallback procedures - * @param p: reply one. The reply has rrset data pointers in region. - * Does not check rrset-IDs - * @param q: reply two - * @param region: scratch buffer. - * @return if one and two are equal. - */ -int reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region); - -/** - * Remove unused bits from the reply if possible. - * So that caps-for-id (0x20) fallback is more likely to be successful. - * This removes like, the additional section, and NS record in the authority - * section if those records are gratuitous (not for a referral). - * @param rep: the reply to strip stuff out of. - */ -void caps_strip_reply(struct reply_info* rep); - -/** - * see if reply has a 'useful' rcode for capsforid comparison, so - * not SERVFAIL or REFUSED, and thus NOERROR or NXDOMAIN. - * @param rep: reply to check. - * @return true if the rcode is a bad type of message. - */ -int caps_failed_rcode(struct reply_info* rep); - -/** - * Store parent-side rrset in separate rrset cache entries for later - * last-resort * lookups in case the child-side versions of this information - * fails. - * @param env: environment with cache, time, ... - * @param rrset: the rrset to store (copied). - * Failure to store is logged, but otherwise ignored. - */ -void iter_store_parentside_rrset(struct module_env* env, - struct ub_packed_rrset_key* rrset); - -/** - * Store parent-side NS records from a referral message - * @param env: environment with cache, time, ... - * @param rep: response with NS rrset. - * Failure to store is logged, but otherwise ignored. - */ -void iter_store_parentside_NS(struct module_env* env, struct reply_info* rep); - -/** - * Store parent-side negative element, the parentside rrset does not exist, - * creates an rrset with empty rdata in the rrset cache with PARENTSIDE flag. - * @param env: environment with cache, time, ... - * @param qinfo: the identity of the rrset that is missing. - * @param rep: delegation response or answer response, to glean TTL from. - * (malloc) failure is logged but otherwise ignored. - */ -void iter_store_parentside_neg(struct module_env* env, - struct query_info* qinfo, struct reply_info* rep); - -/** - * Add parent NS record if that exists in the cache. This is both new - * information and acts like a timeout throttle on retries. - * @param env: query env with rrset cache and time. - * @param dp: delegation point to store result in. Also this dp is used to - * see which NS name is needed. - * @param region: region to alloc result in. - * @param qinfo: pertinent information, the qclass. - * @return false on malloc failure. - * if true, the routine worked and if such cached information - * existed dp->has_parent_side_NS is set true. - */ -int iter_lookup_parent_NS_from_cache(struct module_env* env, - struct delegpt* dp, struct regional* region, struct query_info* qinfo); - -/** - * Add parent-side glue if that exists in the cache. This is both new - * information and acts like a timeout throttle on retries to fetch them. - * @param env: query env with rrset cache and time. - * @param dp: delegation point to store result in. Also this dp is used to - * see which NS name is needed. - * @param region: region to alloc result in. - * @param qinfo: pertinent information, the qclass. - * @return: true, it worked, no malloc failures, and new addresses (lame) - * have been added, giving extra options as query targets. - */ -int iter_lookup_parent_glue_from_cache(struct module_env* env, - struct delegpt* dp, struct regional* region, struct query_info* qinfo); - -/** - * Lookup next root-hint or root-forward entry. - * @param hints: the hints. - * @param fwd: the forwards. - * @param c: the class to start searching at. 0 means find first one. - * @return false if no classes found, true if found and returned in c. - */ -int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, - uint16_t* c); - -/** - * Remove DS records that are inappropriate before they are cached. - * @param msg: the response to scrub. - * @param ns: RRSET that is the NS record for the referral. - * if NULL, then all DS records are removed from the authority section. - * @param z: zone name that the response is from. - */ -void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, - uint8_t* z); - -/** - * Prepare an NXDOMAIN message to be used for a subdomain answer by removing all - * RRs from the ANSWER section. - * @param msg: the response to scrub. - */ -void iter_scrub_nxdomain(struct dns_msg* msg); - -/** - * Remove query attempts from all available ips. For 0x20. - * @param dp: delegpt. - * @param d: decrease. - * @param outbound_msg_retry: number of retries of outgoing queries - */ -void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry); - -/** - * Add retry counts from older delegpt to newer delegpt. - * Does not waste time on timeout'd (or other failing) addresses. - * @param dp: new delegationpoint. - * @param old: old delegationpoint. - * @param outbound_msg_retry: number of retries of outgoing queries - */ -void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old, - int outbound_msg_retry); - -/** - * See if a DS response (type ANSWER) is too low: a nodata answer with - * a SOA record in the authority section at-or-below the qchase.qname. - * Also returns true if we are not sure (i.e. empty message, CNAME nosig). - * @param msg: the response. - * @param dp: the dp name is used to check if the RRSIG gives a clue that - * it was originated from the correct nameserver. - * @return true if too low. - */ -int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp); - -/** - * See if delegpt can go down a step to the qname or not - * @param qinfo: the query name looked up. - * @param dp: checked if the name can go lower to the qname - * @return true if can go down, false if that would not be possible. - * the current response seems to be the one and only, best possible, response. - */ -int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp); - -/** - * Lookup if no_cache is set in stub or fwd. - * @param qstate: query state with env with hints and fwds. - * @param qinf: query name to lookup for. - * @param retdpname: returns NULL or the deepest enclosing name of fwd or stub. - * This is the name under which the closest lookup is going to happen. - * Used for NXDOMAIN checks, above that it is an nxdomain from a - * different server and zone. You can pass NULL to not get it. - * @param retdpnamelen: returns the length of the dpname. - * @return true if no_cache is set in stub or fwd. - */ -int iter_stub_fwd_no_cache(struct module_qstate *qstate, - struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen); - -/** - * Set support for IP4 and IP6 depending on outgoing interfaces - * in the outside network. If none, no support, so no use to lookup - * the AAAA and then attempt to use it if there is no outgoing-interface - * for it. - * @param mods: modstack to find iterator module in. - * @param env: module env, find iterator module (if one) in there. - * @param outnet: outside network structure. - */ -void iterator_set_ip46_support(struct module_stack* mods, - struct module_env* env, struct outside_network* outnet); - -#endif /* ITERATOR_ITER_UTILS_H */ diff --git a/crates/libunbound-sys/unbound/iterator/iterator.c b/crates/libunbound-sys/unbound/iterator/iterator.c deleted file mode 100644 index 1548dfca..00000000 --- a/crates/libunbound-sys/unbound/iterator/iterator.c +++ /dev/null @@ -1,4337 +0,0 @@ -/* - * iterator/iterator.c - iterative resolver DNS query response module - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs recursive iterative DNS query - * processing. - */ - -#include "config.h" -#include "iterator/iterator.h" -#include "iterator/iter_utils.h" -#include "iterator/iter_hints.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_donotq.h" -#include "iterator/iter_delegpt.h" -#include "iterator/iter_resptype.h" -#include "iterator/iter_scrub.h" -#include "iterator/iter_priv.h" -#include "validator/val_neg.h" -#include "services/cache/dns.h" -#include "services/cache/infra.h" -#include "services/authzone.h" -#include "util/module.h" -#include "util/netevent.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/data/dname.h" -#include "util/data/msgencode.h" -#include "util/fptr_wlist.h" -#include "util/config_file.h" -#include "util/random.h" -#include "sldns/rrdef.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" -#include "sldns/parseutil.h" -#include "sldns/sbuffer.h" - -/* in msec */ -int UNKNOWN_SERVER_NICENESS = 376; -/* in msec */ -int USEFUL_SERVER_TOP_TIMEOUT = 120000; -/* Equals USEFUL_SERVER_TOP_TIMEOUT*4 */ -int BLACKLIST_PENALTY = (120000*4); - -static void target_count_increase_nx(struct iter_qstate* iq, int num); - -int -iter_init(struct module_env* env, int id) -{ - struct iter_env* iter_env = (struct iter_env*)calloc(1, - sizeof(struct iter_env)); - if(!iter_env) { - log_err("malloc failure"); - return 0; - } - env->modinfo[id] = (void*)iter_env; - - lock_basic_init(&iter_env->queries_ratelimit_lock); - lock_protect(&iter_env->queries_ratelimit_lock, - &iter_env->num_queries_ratelimited, - sizeof(iter_env->num_queries_ratelimited)); - - if(!iter_apply_cfg(iter_env, env->cfg)) { - log_err("iterator: could not apply configuration settings."); - return 0; - } - - return 1; -} - -/** delete caps_whitelist element */ -static void -caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d)) -{ - if(n) { - free(((struct name_tree_node*)n)->name); - free(n); - } -} - -void -iter_deinit(struct module_env* env, int id) -{ - struct iter_env* iter_env; - if(!env || !env->modinfo[id]) - return; - iter_env = (struct iter_env*)env->modinfo[id]; - lock_basic_destroy(&iter_env->queries_ratelimit_lock); - free(iter_env->target_fetch_policy); - priv_delete(iter_env->priv); - donotq_delete(iter_env->donotq); - if(iter_env->caps_white) { - traverse_postorder(iter_env->caps_white, caps_free, NULL); - free(iter_env->caps_white); - } - free(iter_env); - env->modinfo[id] = NULL; -} - -/** new query for iterator */ -static int -iter_new(struct module_qstate* qstate, int id) -{ - struct iter_qstate* iq = (struct iter_qstate*)regional_alloc( - qstate->region, sizeof(struct iter_qstate)); - qstate->minfo[id] = iq; - if(!iq) - return 0; - memset(iq, 0, sizeof(*iq)); - iq->state = INIT_REQUEST_STATE; - iq->final_state = FINISHED_STATE; - iq->an_prepend_list = NULL; - iq->an_prepend_last = NULL; - iq->ns_prepend_list = NULL; - iq->ns_prepend_last = NULL; - iq->dp = NULL; - iq->depth = 0; - iq->num_target_queries = 0; - iq->num_current_queries = 0; - iq->query_restart_count = 0; - iq->referral_count = 0; - iq->sent_count = 0; - iq->ratelimit_ok = 0; - iq->target_count = NULL; - iq->dp_target_count = 0; - iq->wait_priming_stub = 0; - iq->refetch_glue = 0; - iq->dnssec_expected = 0; - iq->dnssec_lame_query = 0; - iq->chase_flags = qstate->query_flags; - /* Start with the (current) qname. */ - iq->qchase = qstate->qinfo; - outbound_list_init(&iq->outlist); - iq->minimise_count = 0; - iq->timeout_count = 0; - if (qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - else - iq->minimisation_state = DONOT_MINIMISE_STATE; - - memset(&iq->qinfo_out, 0, sizeof(struct query_info)); - return 1; -} - -/** - * Transition to the next state. This can be used to advance a currently - * processing event. It cannot be used to reactivate a forEvent. - * - * @param iq: iterator query state - * @param nextstate The state to transition to. - * @return true. This is so this can be called as the return value for the - * actual process*State() methods. (Transitioning to the next state - * implies further processing). - */ -static int -next_state(struct iter_qstate* iq, enum iter_state nextstate) -{ - /* If transitioning to a "response" state, make sure that there is a - * response */ - if(iter_state_is_responsestate(nextstate)) { - if(iq->response == NULL) { - log_err("transitioning to response state sans " - "response."); - } - } - iq->state = nextstate; - return 1; -} - -/** - * Transition an event to its final state. Final states always either return - * a result up the module chain, or reactivate a dependent event. Which - * final state to transition to is set in the module state for the event when - * it was created, and depends on the original purpose of the event. - * - * The response is stored in the qstate->buf buffer. - * - * @param iq: iterator query state - * @return false. This is so this method can be used as the return value for - * the processState methods. (Transitioning to the final state - */ -static int -final_state(struct iter_qstate* iq) -{ - return next_state(iq, iq->final_state); -} - -/** - * Callback routine to handle errors in parent query states - * @param qstate: query state that failed. - * @param id: module id. - * @param super: super state. - */ -static void -error_supers(struct module_qstate* qstate, int id, struct module_qstate* super) -{ - struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id]; - - if(qstate->qinfo.qtype == LDNS_RR_TYPE_A || - qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { - /* mark address as failed. */ - struct delegpt_ns* dpns = NULL; - super_iq->num_target_queries--; - if(super_iq->dp) - dpns = delegpt_find_ns(super_iq->dp, - qstate->qinfo.qname, qstate->qinfo.qname_len); - if(!dpns) { - /* not interested */ - /* this can happen, for eg. qname minimisation asked - * for an NXDOMAIN to be validated, and used qtype - * A for that, and the error of that, the name, is - * not listed in super_iq->dp */ - verbose(VERB_ALGO, "subq error, but not interested"); - log_query_info(VERB_ALGO, "superq", &super->qinfo); - return; - } else { - /* see if the failure did get (parent-lame) info */ - if(!cache_fill_missing(super->env, super_iq->qchase.qclass, - super->region, super_iq->dp)) - log_err("out of memory adding missing"); - } - delegpt_mark_neg(dpns, qstate->qinfo.qtype); - if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) && - (dpns->got6 == 2 || !ie->supports_ipv6)) { - dpns->resolved = 1; /* mark as failed */ - target_count_increase_nx(super_iq, 1); - } - } - if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) { - /* prime failed to get delegation */ - super_iq->dp = NULL; - } - /* evaluate targets again */ - super_iq->state = QUERYTARGETS_STATE; - /* super becomes runnable, and will process this change */ -} - -/** - * Return an error to the client - * @param qstate: our query state - * @param id: module id - * @param rcode: error code (DNS errcode). - * @return: 0 for use by caller, to make notation easy, like: - * return error_response(..). - */ -static int -error_response(struct module_qstate* qstate, int id, int rcode) -{ - verbose(VERB_QUERY, "return error response %s", - sldns_lookup_by_id(sldns_rcodes, rcode)? - sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??"); - qstate->return_rcode = rcode; - qstate->return_msg = NULL; - qstate->ext_state[id] = module_finished; - return 0; -} - -/** - * Return an error to the client and cache the error code in the - * message cache (so per qname, qtype, qclass). - * @param qstate: our query state - * @param id: module id - * @param rcode: error code (DNS errcode). - * @return: 0 for use by caller, to make notation easy, like: - * return error_response(..). - */ -static int -error_response_cache(struct module_qstate* qstate, int id, int rcode) -{ - struct reply_info err; - struct msgreply_entry* msg; - if(qstate->no_cache_store) { - return error_response(qstate, id, rcode); - } - if(qstate->prefetch_leeway > NORR_TTL) { - verbose(VERB_ALGO, "error response for prefetch in cache"); - /* attempt to adjust the cache entry prefetch */ - if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo, - NORR_TTL, qstate->query_flags)) - return error_response(qstate, id, rcode); - /* if that fails (not in cache), fall through to store err */ - } - if((msg=msg_cache_lookup(qstate->env, - qstate->qinfo.qname, qstate->qinfo.qname_len, - qstate->qinfo.qtype, qstate->qinfo.qclass, - qstate->query_flags, 0, - qstate->env->cfg->serve_expired_ttl_reset)) != NULL) { - struct reply_info* rep = (struct reply_info*)msg->entry.data; - if(qstate->env->cfg->serve_expired && - qstate->env->cfg->serve_expired_ttl_reset && rep && - *qstate->env->now + qstate->env->cfg->serve_expired_ttl - > rep->serve_expired_ttl) { - verbose(VERB_ALGO, "reset serve-expired-ttl for " - "response in cache"); - rep->serve_expired_ttl = *qstate->env->now + - qstate->env->cfg->serve_expired_ttl; - } - if(rep && (FLAGS_GET_RCODE(rep->flags) == - LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(rep->flags) == - LDNS_RCODE_NXDOMAIN || - FLAGS_GET_RCODE(rep->flags) == - LDNS_RCODE_YXDOMAIN) && - (qstate->env->cfg->serve_expired || - *qstate->env->now <= rep->ttl)) { - /* we have a good entry, don't overwrite */ - lock_rw_unlock(&msg->entry.lock); - return error_response(qstate, id, rcode); - } - lock_rw_unlock(&msg->entry.lock); - /* nothing interesting is cached (already error response or - * expired good record when we don't serve expired), so this - * servfail cache entry is useful (stops waste of time on this - * servfail NORR_TTL) */ - } - /* store in cache */ - memset(&err, 0, sizeof(err)); - err.flags = (uint16_t)(BIT_QR | BIT_RA); - FLAGS_SET_RCODE(err.flags, rcode); - err.qdcount = 1; - err.ttl = NORR_TTL; - err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl); - err.serve_expired_ttl = NORR_TTL; - /* do not waste time trying to validate this servfail */ - err.security = sec_status_indeterminate; - verbose(VERB_ALGO, "store error response in message cache"); - iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL, - qstate->query_flags, qstate->qstarttime); - return error_response(qstate, id, rcode); -} - -/** check if prepend item is duplicate item */ -static int -prepend_is_duplicate(struct ub_packed_rrset_key** sets, size_t to, - struct ub_packed_rrset_key* dup) -{ - size_t i; - for(i=0; irk.type == dup->rk.type && - sets[i]->rk.rrset_class == dup->rk.rrset_class && - sets[i]->rk.dname_len == dup->rk.dname_len && - query_dname_compare(sets[i]->rk.dname, dup->rk.dname) - == 0) - return 1; - } - return 0; -} - -/** prepend the prepend list in the answer and authority section of dns_msg */ -static int -iter_prepend(struct iter_qstate* iq, struct dns_msg* msg, - struct regional* region) -{ - struct iter_prep_list* p; - struct ub_packed_rrset_key** sets; - size_t num_an = 0, num_ns = 0;; - for(p = iq->an_prepend_list; p; p = p->next) - num_an++; - for(p = iq->ns_prepend_list; p; p = p->next) - num_ns++; - if(num_an + num_ns == 0) - return 1; - verbose(VERB_ALGO, "prepending %d rrsets", (int)num_an + (int)num_ns); - if(num_an > RR_COUNT_MAX || num_ns > RR_COUNT_MAX || - msg->rep->rrset_count > RR_COUNT_MAX) return 0; /* overflow */ - sets = regional_alloc(region, (num_an+num_ns+msg->rep->rrset_count) * - sizeof(struct ub_packed_rrset_key*)); - if(!sets) - return 0; - /* ANSWER section */ - num_an = 0; - for(p = iq->an_prepend_list; p; p = p->next) { - sets[num_an++] = p->rrset; - if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl) - msg->rep->ttl = ub_packed_rrset_ttl(p->rrset); - } - memcpy(sets+num_an, msg->rep->rrsets, msg->rep->an_numrrsets * - sizeof(struct ub_packed_rrset_key*)); - /* AUTH section */ - num_ns = 0; - for(p = iq->ns_prepend_list; p; p = p->next) { - if(prepend_is_duplicate(sets+msg->rep->an_numrrsets+num_an, - num_ns, p->rrset) || prepend_is_duplicate( - msg->rep->rrsets+msg->rep->an_numrrsets, - msg->rep->ns_numrrsets, p->rrset)) - continue; - sets[msg->rep->an_numrrsets + num_an + num_ns++] = p->rrset; - if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl) - msg->rep->ttl = ub_packed_rrset_ttl(p->rrset); - } - memcpy(sets + num_an + msg->rep->an_numrrsets + num_ns, - msg->rep->rrsets + msg->rep->an_numrrsets, - (msg->rep->ns_numrrsets + msg->rep->ar_numrrsets) * - sizeof(struct ub_packed_rrset_key*)); - - /* NXDOMAIN rcode can stay if we prepended DNAME/CNAMEs, because - * this is what recursors should give. */ - msg->rep->rrset_count += num_an + num_ns; - msg->rep->an_numrrsets += num_an; - msg->rep->ns_numrrsets += num_ns; - msg->rep->rrsets = sets; - return 1; -} - -/** - * Find rrset in ANSWER prepend list. - * to avoid duplicate DNAMEs when a DNAME is traversed twice. - * @param iq: iterator query state. - * @param rrset: rrset to add. - * @return false if not found - */ -static int -iter_find_rrset_in_prepend_answer(struct iter_qstate* iq, - struct ub_packed_rrset_key* rrset) -{ - struct iter_prep_list* p = iq->an_prepend_list; - while(p) { - if(ub_rrset_compare(p->rrset, rrset) == 0 && - rrsetdata_equal((struct packed_rrset_data*)p->rrset - ->entry.data, (struct packed_rrset_data*)rrset - ->entry.data)) - return 1; - p = p->next; - } - return 0; -} - -/** - * Add rrset to ANSWER prepend list - * @param qstate: query state. - * @param iq: iterator query state. - * @param rrset: rrset to add. - * @return false on failure (malloc). - */ -static int -iter_add_prepend_answer(struct module_qstate* qstate, struct iter_qstate* iq, - struct ub_packed_rrset_key* rrset) -{ - struct iter_prep_list* p = (struct iter_prep_list*)regional_alloc( - qstate->region, sizeof(struct iter_prep_list)); - if(!p) - return 0; - p->rrset = rrset; - p->next = NULL; - /* add at end */ - if(iq->an_prepend_last) - iq->an_prepend_last->next = p; - else iq->an_prepend_list = p; - iq->an_prepend_last = p; - return 1; -} - -/** - * Add rrset to AUTHORITY prepend list - * @param qstate: query state. - * @param iq: iterator query state. - * @param rrset: rrset to add. - * @return false on failure (malloc). - */ -static int -iter_add_prepend_auth(struct module_qstate* qstate, struct iter_qstate* iq, - struct ub_packed_rrset_key* rrset) -{ - struct iter_prep_list* p = (struct iter_prep_list*)regional_alloc( - qstate->region, sizeof(struct iter_prep_list)); - if(!p) - return 0; - p->rrset = rrset; - p->next = NULL; - /* add at end */ - if(iq->ns_prepend_last) - iq->ns_prepend_last->next = p; - else iq->ns_prepend_list = p; - iq->ns_prepend_last = p; - return 1; -} - -/** - * Given a CNAME response (defined as a response containing a CNAME or DNAME - * that does not answer the request), process the response, modifying the - * state as necessary. This follows the CNAME/DNAME chain and returns the - * final query name. - * - * sets the new query name, after following the CNAME/DNAME chain. - * @param qstate: query state. - * @param iq: iterator query state. - * @param msg: the response. - * @param mname: returned target new query name. - * @param mname_len: length of mname. - * @return false on (malloc) error. - */ -static int -handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq, - struct dns_msg* msg, uint8_t** mname, size_t* mname_len) -{ - size_t i; - /* Start with the (current) qname. */ - *mname = iq->qchase.qname; - *mname_len = iq->qchase.qname_len; - - /* Iterate over the ANSWER rrsets in order, looking for CNAMEs and - * DNAMES. */ - for(i=0; irep->an_numrrsets; i++) { - struct ub_packed_rrset_key* r = msg->rep->rrsets[i]; - /* If there is a (relevant) DNAME, add it to the list. - * We always expect there to be CNAME that was generated - * by this DNAME following, so we don't process the DNAME - * directly. */ - if(ntohs(r->rk.type) == LDNS_RR_TYPE_DNAME && - dname_strict_subdomain_c(*mname, r->rk.dname) && - !iter_find_rrset_in_prepend_answer(iq, r)) { - if(!iter_add_prepend_answer(qstate, iq, r)) - return 0; - continue; - } - - if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(*mname, r->rk.dname) == 0 && - !iter_find_rrset_in_prepend_answer(iq, r)) { - /* Add this relevant CNAME rrset to the prepend list.*/ - if(!iter_add_prepend_answer(qstate, iq, r)) - return 0; - get_cname_target(r, mname, mname_len); - } - - /* Other rrsets in the section are ignored. */ - } - /* add authority rrsets to authority prepend, for wildcarded CNAMEs */ - for(i=msg->rep->an_numrrsets; irep->an_numrrsets + - msg->rep->ns_numrrsets; i++) { - struct ub_packed_rrset_key* r = msg->rep->rrsets[i]; - /* only add NSEC/NSEC3, as they may be needed for validation */ - if(ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC || - ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC3) { - if(!iter_add_prepend_auth(qstate, iq, r)) - return 0; - } - } - return 1; -} - -/** fill fail address for later recovery */ -static void -fill_fail_addr(struct iter_qstate* iq, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - if(addrlen == 0) { - iq->fail_addr_type = 0; - return; - } - if(((struct sockaddr_in*)addr)->sin_family == AF_INET) { - iq->fail_addr_type = 4; - memcpy(&iq->fail_addr.in, - &((struct sockaddr_in*)addr)->sin_addr, - sizeof(iq->fail_addr.in)); - } -#ifdef AF_INET6 - else if(((struct sockaddr_in*)addr)->sin_family == AF_INET6) { - iq->fail_addr_type = 6; - memcpy(&iq->fail_addr.in6, - &((struct sockaddr_in6*)addr)->sin6_addr, - sizeof(iq->fail_addr.in6)); - } -#endif - else { - iq->fail_addr_type = 0; - } -} - -/** print fail addr to string */ -static void -print_fail_addr(struct iter_qstate* iq, char* buf, size_t len) -{ - if(iq->fail_addr_type == 4) { - if(inet_ntop(AF_INET, &iq->fail_addr.in, buf, - (socklen_t)len) == 0) - (void)strlcpy(buf, "(inet_ntop error)", len); - } -#ifdef AF_INET6 - else if(iq->fail_addr_type == 6) { - if(inet_ntop(AF_INET6, &iq->fail_addr.in6, buf, - (socklen_t)len) == 0) - (void)strlcpy(buf, "(inet_ntop error)", len); - } -#endif - else - (void)strlcpy(buf, "", len); -} - -/** add response specific error information for log servfail */ -static void -errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq) -{ - if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) - return; - if((qstate->reply && qstate->reply->remote_addrlen != 0) || - (iq->fail_addr_type != 0)) { - char from[256], frm[512]; - if(qstate->reply && qstate->reply->remote_addrlen != 0) - addr_to_str(&qstate->reply->remote_addr, - qstate->reply->remote_addrlen, from, - sizeof(from)); - else - print_fail_addr(iq, from, sizeof(from)); - snprintf(frm, sizeof(frm), "from %s", from); - errinf(qstate, frm); - } - if(iq->scrub_failures || iq->parse_failures) { - if(iq->scrub_failures) - errinf(qstate, "upstream response failed scrub"); - if(iq->parse_failures) - errinf(qstate, "could not parse upstream response"); - } else if(iq->response == NULL && iq->timeout_count != 0) { - errinf(qstate, "upstream server timeout"); - } else if(iq->response == NULL) { - errinf(qstate, "no server to query"); - if(iq->dp) { - if(iq->dp->target_list == NULL) - errinf(qstate, "no addresses for nameservers"); - else errinf(qstate, "nameserver addresses not usable"); - if(iq->dp->nslist == NULL) - errinf(qstate, "have no nameserver names"); - if(iq->dp->bogus) - errinf(qstate, "NS record was dnssec bogus"); - } - } - if(iq->response && iq->response->rep) { - if(FLAGS_GET_RCODE(iq->response->rep->flags) != 0) { - char rcode[256], rc[32]; - (void)sldns_wire2str_rcode_buf( - FLAGS_GET_RCODE(iq->response->rep->flags), - rc, sizeof(rc)); - snprintf(rcode, sizeof(rcode), "got %s", rc); - errinf(qstate, rcode); - } else { - /* rcode NOERROR */ - if(iq->response->rep->an_numrrsets == 0) { - errinf(qstate, "nodata answer"); - } - } - } -} - -/** see if last resort is possible - does config allow queries to parent */ -static int -can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen, - uint16_t qclass, struct delegpt** retdp) -{ - struct delegpt* fwddp; - struct iter_hints_stub* stub; - int labs = dname_count_labels(nm); - /* do not process a last resort (the parent side) if a stub - * or forward is configured, because we do not want to go 'above' - * the configured servers */ - if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*) - name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) && - /* has_parent side is turned off for stub_first, where we - * are allowed to go to the parent */ - stub->dp->has_parent_side_NS) { - if(retdp) *retdp = stub->dp; - return 0; - } - if((fwddp = forwards_find(env->fwds, nm, qclass)) && - /* has_parent_side is turned off for forward_first, where - * we are allowed to go to the parent */ - fwddp->has_parent_side_NS) { - if(retdp) *retdp = fwddp; - return 0; - } - return 1; -} - -/** see if target name is caps-for-id whitelisted */ -static int -is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq) -{ - if(!ie->caps_white) return 0; /* no whitelist, or no capsforid */ - return name_tree_lookup(ie->caps_white, iq->qchase.qname, - iq->qchase.qname_len, dname_count_labels(iq->qchase.qname), - iq->qchase.qclass) != NULL; -} - -/** - * Create target count structure for this query. This is always explicitly - * created for the parent query. - */ -static void -target_count_create(struct iter_qstate* iq) -{ - if(!iq->target_count) { - iq->target_count = (int*)calloc(TARGET_COUNT_MAX, sizeof(int)); - /* if calloc fails we simply do not track this number */ - if(iq->target_count) { - iq->target_count[TARGET_COUNT_REF] = 1; - iq->nxns_dp = (uint8_t**)calloc(1, sizeof(uint8_t*)); - } - } -} - -static void -target_count_increase(struct iter_qstate* iq, int num) -{ - target_count_create(iq); - if(iq->target_count) - iq->target_count[TARGET_COUNT_QUERIES] += num; - iq->dp_target_count++; -} - -static void -target_count_increase_nx(struct iter_qstate* iq, int num) -{ - target_count_create(iq); - if(iq->target_count) - iq->target_count[TARGET_COUNT_NX] += num; -} - -/** - * Generate a subrequest. - * Generate a local request event. Local events are tied to this module, and - * have a corresponding (first tier) event that is waiting for this event to - * resolve to continue. - * - * @param qname The query name for this request. - * @param qnamelen length of qname - * @param qtype The query type for this request. - * @param qclass The query class for this request. - * @param qstate The event that is generating this event. - * @param id: module id. - * @param iq: The iterator state that is generating this event. - * @param initial_state The initial response state (normally this - * is QUERY_RESP_STATE, unless it is known that the request won't - * need iterative processing - * @param finalstate The final state for the response to this request. - * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does - * not need initialisation. - * @param v: if true, validation is done on the subquery. - * @param detached: true if this qstate should not attach to the subquery - * @return false on error (malloc). - */ -static int -generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, - uint16_t qclass, struct module_qstate* qstate, int id, - struct iter_qstate* iq, enum iter_state initial_state, - enum iter_state finalstate, struct module_qstate** subq_ret, int v, - int detached) -{ - struct module_qstate* subq = NULL; - struct iter_qstate* subiq = NULL; - uint16_t qflags = 0; /* OPCODE QUERY, no flags */ - struct query_info qinf; - int prime = (finalstate == PRIME_RESP_STATE)?1:0; - int valrec = 0; - qinf.qname = qname; - qinf.qname_len = qnamelen; - qinf.qtype = qtype; - qinf.qclass = qclass; - qinf.local_alias = NULL; - - /* RD should be set only when sending the query back through the INIT - * state. */ - if(initial_state == INIT_REQUEST_STATE) - qflags |= BIT_RD; - /* We set the CD flag so we can send this through the "head" of - * the resolution chain, which might have a validator. We are - * uninterested in validating things not on the direct resolution - * path. */ - if(!v) { - qflags |= BIT_CD; - valrec = 1; - } - - if(detached) { - struct mesh_state* sub = NULL; - fptr_ok(fptr_whitelist_modenv_add_sub( - qstate->env->add_sub)); - if(!(*qstate->env->add_sub)(qstate, &qinf, - qflags, prime, valrec, &subq, &sub)){ - return 0; - } - } - else { - /* attach subquery, lookup existing or make a new one */ - fptr_ok(fptr_whitelist_modenv_attach_sub( - qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, - valrec, &subq)) { - return 0; - } - } - *subq_ret = subq; - if(subq) { - /* initialise the new subquery */ - subq->curmod = id; - subq->ext_state[id] = module_state_initial; - subq->minfo[id] = regional_alloc(subq->region, - sizeof(struct iter_qstate)); - if(!subq->minfo[id]) { - log_err("init subq: out of memory"); - fptr_ok(fptr_whitelist_modenv_kill_sub( - qstate->env->kill_sub)); - (*qstate->env->kill_sub)(subq); - return 0; - } - subiq = (struct iter_qstate*)subq->minfo[id]; - memset(subiq, 0, sizeof(*subiq)); - subiq->num_target_queries = 0; - target_count_create(iq); - subiq->target_count = iq->target_count; - if(iq->target_count) { - iq->target_count[TARGET_COUNT_REF] ++; /* extra reference */ - subiq->nxns_dp = iq->nxns_dp; - } - subiq->dp_target_count = 0; - subiq->num_current_queries = 0; - subiq->depth = iq->depth+1; - outbound_list_init(&subiq->outlist); - subiq->state = initial_state; - subiq->final_state = finalstate; - subiq->qchase = subq->qinfo; - subiq->chase_flags = subq->query_flags; - subiq->refetch_glue = 0; - if(qstate->env->cfg->qname_minimisation) - subiq->minimisation_state = INIT_MINIMISE_STATE; - else - subiq->minimisation_state = DONOT_MINIMISE_STATE; - memset(&subiq->qinfo_out, 0, sizeof(struct query_info)); - } - return 1; -} - -/** - * Generate and send a root priming request. - * @param qstate: the qtstate that triggered the need to prime. - * @param iq: iterator query state. - * @param id: module id. - * @param qclass: the class to prime. - * @return 0 on failure - */ -static int -prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id, - uint16_t qclass) -{ - struct delegpt* dp; - struct module_qstate* subq; - verbose(VERB_DETAIL, "priming . %s NS", - sldns_lookup_by_id(sldns_rr_classes, (int)qclass)? - sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??"); - dp = hints_lookup_root(qstate->env->hints, qclass); - if(!dp) { - verbose(VERB_ALGO, "Cannot prime due to lack of hints"); - return 0; - } - /* Priming requests start at the QUERYTARGETS state, skipping - * the normal INIT state logic (which would cause an infloop). */ - if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, - qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE, - &subq, 0, 0)) { - verbose(VERB_ALGO, "could not prime root"); - return 0; - } - if(subq) { - struct iter_qstate* subiq = - (struct iter_qstate*)subq->minfo[id]; - /* Set the initial delegation point to the hint. - * copy dp, it is now part of the root prime query. - * dp was part of in the fixed hints structure. */ - subiq->dp = delegpt_copy(dp, subq->region); - if(!subiq->dp) { - log_err("out of memory priming root, copydp"); - fptr_ok(fptr_whitelist_modenv_kill_sub( - qstate->env->kill_sub)); - (*qstate->env->kill_sub)(subq); - return 0; - } - /* there should not be any target queries. */ - subiq->num_target_queries = 0; - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, subq->qinfo.qclass); - } - - /* this module stops, our submodule starts, and does the query. */ - qstate->ext_state[id] = module_wait_subquery; - return 1; -} - -/** - * Generate and process a stub priming request. This method tests for the - * need to prime a stub zone, so it is safe to call for every request. - * - * @param qstate: the qtstate that triggered the need to prime. - * @param iq: iterator query state. - * @param id: module id. - * @param qname: request name. - * @param qclass: request class. - * @return true if a priming subrequest was made, false if not. The will only - * issue a priming request if it detects an unprimed stub. - * Uses value of 2 to signal during stub-prime in root-prime situation - * that a noprime-stub is available and resolution can continue. - */ -static int -prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id, - uint8_t* qname, uint16_t qclass) -{ - /* Lookup the stub hint. This will return null if the stub doesn't - * need to be re-primed. */ - struct iter_hints_stub* stub; - struct delegpt* stub_dp; - struct module_qstate* subq; - - if(!qname) return 0; - stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp); - /* The stub (if there is one) does not need priming. */ - if(!stub) - return 0; - stub_dp = stub->dp; - /* if we have an auth_zone dp, and stub is equal, don't prime stub - * yet, unless we want to fallback and avoid the auth_zone */ - if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp && - query_dname_compare(iq->dp->name, stub_dp->name) == 0) - return 0; - - /* is it a noprime stub (always use) */ - if(stub->noprime) { - int r = 0; - if(iq->dp == NULL) r = 2; - /* copy the dp out of the fixed hints structure, so that - * it can be changed when servicing this query */ - iq->dp = delegpt_copy(stub_dp, qstate->region); - if(!iq->dp) { - log_err("out of memory priming stub"); - errinf(qstate, "malloc failure, priming stub"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return 1; /* return 1 to make module stop, with error */ - } - log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name, - LDNS_RR_TYPE_NS, qclass); - return r; - } - - /* Otherwise, we need to (re)prime the stub. */ - log_nametypeclass(VERB_DETAIL, "priming stub", stub_dp->name, - LDNS_RR_TYPE_NS, qclass); - - /* Stub priming events start at the QUERYTARGETS state to avoid the - * redundant INIT state processing. */ - if(!generate_sub_request(stub_dp->name, stub_dp->namelen, - LDNS_RR_TYPE_NS, qclass, qstate, id, iq, - QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) { - verbose(VERB_ALGO, "could not prime stub"); - errinf(qstate, "could not generate lookup for stub prime"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return 1; /* return 1 to make module stop, with error */ - } - if(subq) { - struct iter_qstate* subiq = - (struct iter_qstate*)subq->minfo[id]; - - /* Set the initial delegation point to the hint. */ - /* make copy to avoid use of stub dp by different qs/threads */ - subiq->dp = delegpt_copy(stub_dp, subq->region); - if(!subiq->dp) { - log_err("out of memory priming stub, copydp"); - fptr_ok(fptr_whitelist_modenv_kill_sub( - qstate->env->kill_sub)); - (*qstate->env->kill_sub)(subq); - errinf(qstate, "malloc failure, in stub prime"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return 1; /* return 1 to make module stop, with error */ - } - /* there should not be any target queries -- although there - * wouldn't be anyway, since stub hints never have - * missing targets. */ - subiq->num_target_queries = 0; - subiq->wait_priming_stub = 1; - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, subq->qinfo.qclass); - } - - /* this module stops, our submodule starts, and does the query. */ - qstate->ext_state[id] = module_wait_subquery; - return 1; -} - -/** - * Generate a delegation point for an auth zone (unless cached dp is better) - * false on alloc failure. - */ -static int -auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq, - uint8_t* delname, size_t delnamelen) -{ - struct auth_zone* z; - if(iq->auth_zone_avoid) - return 1; - if(!delname) { - delname = iq->qchase.qname; - delnamelen = iq->qchase.qname_len; - } - lock_rw_rdlock(&qstate->env->auth_zones->lock); - z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen, - qstate->qinfo.qclass); - if(!z) { - lock_rw_unlock(&qstate->env->auth_zones->lock); - return 1; - } - lock_rw_rdlock(&z->lock); - lock_rw_unlock(&qstate->env->auth_zones->lock); - if(z->for_upstream) { - if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0 - && iq->dp->auth_dp && qstate->blacklist && - z->fallback_enabled) { - /* cache is blacklisted and fallback, and we - * already have an auth_zone dp */ - if(verbosity>=VERB_ALGO) { - char buf[255+1]; - dname_str(z->name, buf); - verbose(VERB_ALGO, "auth_zone %s " - "fallback because cache blacklisted", - buf); - } - lock_rw_unlock(&z->lock); - iq->dp = NULL; - return 1; - } - if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) { - struct delegpt* dp; - if(qstate->blacklist && z->fallback_enabled) { - /* cache is blacklisted because of a DNSSEC - * validation failure, and the zone allows - * fallback to the internet, query there. */ - if(verbosity>=VERB_ALGO) { - char buf[255+1]; - dname_str(z->name, buf); - verbose(VERB_ALGO, "auth_zone %s " - "fallback because cache blacklisted", - buf); - } - lock_rw_unlock(&z->lock); - return 1; - } - dp = (struct delegpt*)regional_alloc_zero( - qstate->region, sizeof(*dp)); - if(!dp) { - log_err("alloc failure"); - if(z->fallback_enabled) { - lock_rw_unlock(&z->lock); - return 1; /* just fallback */ - } - lock_rw_unlock(&z->lock); - errinf(qstate, "malloc failure"); - return 0; - } - dp->name = regional_alloc_init(qstate->region, - z->name, z->namelen); - if(!dp->name) { - log_err("alloc failure"); - if(z->fallback_enabled) { - lock_rw_unlock(&z->lock); - return 1; /* just fallback */ - } - lock_rw_unlock(&z->lock); - errinf(qstate, "malloc failure"); - return 0; - } - dp->namelen = z->namelen; - dp->namelabs = z->namelabs; - dp->auth_dp = 1; - iq->dp = dp; - } - } - - lock_rw_unlock(&z->lock); - return 1; -} - -/** - * Generate A and AAAA checks for glue that is in-zone for the referral - * we just got to obtain authoritative information on the addresses. - * - * @param qstate: the qtstate that triggered the need to prime. - * @param iq: iterator query state. - * @param id: module id. - */ -static void -generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq, - int id) -{ - struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct module_qstate* subq; - size_t i; - struct reply_info* rep = iq->response->rep; - struct ub_packed_rrset_key* s; - log_assert(iq->dp); - - if(iq->depth == ie->max_dependency_depth) - return; - /* walk through additional, and check if in-zone, - * only relevant A, AAAA are left after scrub anyway */ - for(i=rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { - s = rep->rrsets[i]; - /* check *ALL* addresses that are transmitted in additional*/ - /* is it an address ? */ - if( !(ntohs(s->rk.type)==LDNS_RR_TYPE_A || - ntohs(s->rk.type)==LDNS_RR_TYPE_AAAA)) { - continue; - } - /* is this query the same as the A/AAAA check for it */ - if(qstate->qinfo.qtype == ntohs(s->rk.type) && - qstate->qinfo.qclass == ntohs(s->rk.rrset_class) && - query_dname_compare(qstate->qinfo.qname, - s->rk.dname)==0 && - (qstate->query_flags&BIT_RD) && - !(qstate->query_flags&BIT_CD)) - continue; - - /* generate subrequest for it */ - log_nametypeclass(VERB_ALGO, "schedule addr fetch", - s->rk.dname, ntohs(s->rk.type), - ntohs(s->rk.rrset_class)); - if(!generate_sub_request(s->rk.dname, s->rk.dname_len, - ntohs(s->rk.type), ntohs(s->rk.rrset_class), - qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate addr check"); - return; - } - /* ignore subq - not need for more init */ - } -} - -/** - * Generate a NS check request to obtain authoritative information - * on an NS rrset. - * - * @param qstate: the qstate that triggered the need to prime. - * @param iq: iterator query state. - * @param id: module id. - */ -static void -generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) -{ - struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct module_qstate* subq; - log_assert(iq->dp); - - if(iq->depth == ie->max_dependency_depth) - return; - if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, - iq->qchase.qclass, NULL)) - return; - /* is this query the same as the nscheck? */ - if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS && - query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 && - (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){ - /* spawn off A, AAAA queries for in-zone glue to check */ - generate_a_aaaa_check(qstate, iq, id); - return; - } - /* no need to get the NS record for DS, it is above the zonecut */ - if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) - return; - - log_nametypeclass(VERB_ALGO, "schedule ns fetch", - iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); - if(!generate_sub_request(iq->dp->name, iq->dp->namelen, - LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate ns check"); - return; - } - if(subq) { - struct iter_qstate* subiq = - (struct iter_qstate*)subq->minfo[id]; - - /* make copy to avoid use of stub dp by different qs/threads */ - /* refetch glue to start higher up the tree */ - subiq->refetch_glue = 1; - subiq->dp = delegpt_copy(iq->dp, subq->region); - if(!subiq->dp) { - log_err("out of memory generating ns check, copydp"); - fptr_ok(fptr_whitelist_modenv_kill_sub( - qstate->env->kill_sub)); - (*qstate->env->kill_sub)(subq); - return; - } - } -} - -/** - * Generate a DNSKEY prefetch query to get the DNSKEY for the DS record we - * just got in a referral (where we have dnssec_expected, thus have trust - * anchors above it). Note that right after calling this routine the - * iterator detached subqueries (because of following the referral), and thus - * the DNSKEY query becomes detached, its return stored in the cache for - * later lookup by the validator. This cache lookup by the validator avoids - * the roundtrip incurred by the DNSKEY query. The DNSKEY query is now - * performed at about the same time the original query is sent to the domain, - * thus the two answers are likely to be returned at about the same time, - * saving a roundtrip from the validated lookup. - * - * @param qstate: the qtstate that triggered the need to prime. - * @param iq: iterator query state. - * @param id: module id. - */ -static void -generate_dnskey_prefetch(struct module_qstate* qstate, - struct iter_qstate* iq, int id) -{ - struct module_qstate* subq; - log_assert(iq->dp); - - /* is this query the same as the prefetch? */ - if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY && - query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 && - (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){ - return; - } - /* we do not generate this prefetch when the query list is full, - * the query is fetched, if needed, when the validator wants it. - * At that time the validator waits for it, after spawning it. - * This means there is one state that uses cpu and a socket, the - * spawned while this one waits, and not several at the same time, - * if we had created the lookup here. And this helps to keep - * the total load down, but the query still succeeds to resolve. */ - if(mesh_jostle_exceeded(qstate->env->mesh)) - return; - - /* if the DNSKEY is in the cache this lookup will stop quickly */ - log_nametypeclass(VERB_ALGO, "schedule dnskey prefetch", - iq->dp->name, LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass); - if(!generate_sub_request(iq->dp->name, iq->dp->namelen, - LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) { - /* we'll be slower, but it'll work */ - verbose(VERB_ALGO, "could not generate dnskey prefetch"); - return; - } - if(subq) { - struct iter_qstate* subiq = - (struct iter_qstate*)subq->minfo[id]; - /* this qstate has the right delegation for the dnskey lookup*/ - /* make copy to avoid use of stub dp by different qs/threads */ - subiq->dp = delegpt_copy(iq->dp, subq->region); - /* if !subiq->dp, it'll start from the cache, no problem */ - } -} - -/** - * See if the query needs forwarding. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @return true if the request is forwarded, false if not. - * If returns true but, iq->dp is NULL then a malloc failure occurred. - */ -static int -forward_request(struct module_qstate* qstate, struct iter_qstate* iq) -{ - struct delegpt* dp; - uint8_t* delname = iq->qchase.qname; - size_t delnamelen = iq->qchase.qname_len; - if(iq->refetch_glue && iq->dp) { - delname = iq->dp->name; - delnamelen = iq->dp->namelen; - } - /* strip one label off of DS query to lookup higher for it */ - if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) - && !dname_is_root(iq->qchase.qname)) - dname_remove_label(&delname, &delnamelen); - dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass); - if(!dp) - return 0; - /* send recursion desired to forward addr */ - iq->chase_flags |= BIT_RD; - iq->dp = delegpt_copy(dp, qstate->region); - /* iq->dp checked by caller */ - verbose(VERB_ALGO, "forwarding request"); - return 1; -} - -/** - * Process the initial part of the request handling. This state roughly - * corresponds to resolver algorithms steps 1 (find answer in cache) and 2 - * (find the best servers to ask). - * - * Note that all requests start here, and query restarts revisit this state. - * - * This state either generates: 1) a response, from cache or error, 2) a - * priming event, or 3) forwards the request to the next state (init2, - * generally). - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param ie: iterator shared global environment. - * @param id: module id. - * @return true if the event needs more request processing immediately, - * false if not. - */ -static int -processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - uint8_t* delname, *dpname=NULL; - size_t delnamelen, dpnamelen=0; - struct dns_msg* msg = NULL; - - log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo); - /* check effort */ - - /* We enforce a maximum number of query restarts. This is primarily a - * cheap way to prevent CNAME loops. */ - if(iq->query_restart_count > ie->max_query_restarts) { - verbose(VERB_QUERY, "request has exceeded the maximum number" - " of query restarts with %d", iq->query_restart_count); - errinf(qstate, "request has exceeded the maximum number " - "restarts (eg. indirections)"); - if(iq->qchase.qname) - errinf_dname(qstate, "stop at", iq->qchase.qname); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - /* We enforce a maximum recursion/dependency depth -- in general, - * this is unnecessary for dependency loops (although it will - * catch those), but it provides a sensible limit to the amount - * of work required to answer a given query. */ - verbose(VERB_ALGO, "request has dependency depth of %d", iq->depth); - if(iq->depth > ie->max_dependency_depth) { - verbose(VERB_QUERY, "request has exceeded the maximum " - "dependency depth with depth of %d", iq->depth); - errinf(qstate, "request has exceeded the maximum dependency " - "depth (eg. nameserver lookup recursion)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - /* If the request is qclass=ANY, setup to generate each class */ - if(qstate->qinfo.qclass == LDNS_RR_CLASS_ANY) { - iq->qchase.qclass = 0; - return next_state(iq, COLLECT_CLASS_STATE); - } - - /* - * If we are restricted by a forward-zone or a stub-zone, we - * can't re-fetch glue for this delegation point. - * we won’t try to re-fetch glue if the iq->dp is null. - */ - if (iq->refetch_glue && - iq->dp && - !can_have_last_resort(qstate->env, iq->dp->name, - iq->dp->namelen, iq->qchase.qclass, NULL)) { - iq->refetch_glue = 0; - } - - /* Resolver Algorithm Step 1 -- Look for the answer in local data. */ - - /* This either results in a query restart (CNAME cache response), a - * terminating response (ANSWER), or a cache miss (null). */ - - if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) { - /* Asked to not query cache. */ - verbose(VERB_ALGO, "no-cache set, going to the network"); - qstate->no_cache_lookup = 1; - qstate->no_cache_store = 1; - msg = NULL; - } else if(qstate->blacklist) { - /* if cache, or anything else, was blacklisted then - * getting older results from cache is a bad idea, no cache */ - verbose(VERB_ALGO, "cache blacklisted, going to the network"); - msg = NULL; - } else if(!qstate->no_cache_lookup) { - msg = dns_cache_lookup(qstate->env, iq->qchase.qname, - iq->qchase.qname_len, iq->qchase.qtype, - iq->qchase.qclass, qstate->query_flags, - qstate->region, qstate->env->scratch, 0, dpname, - dpnamelen); - if(!msg && qstate->env->neg_cache && - iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) { - /* lookup in negative cache; may result in - * NOERROR/NODATA or NXDOMAIN answers that need validation */ - msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase, - qstate->region, qstate->env->rrset_cache, - qstate->env->scratch_buffer, - *qstate->env->now, 1/*add SOA*/, NULL, - qstate->env->cfg); - } - /* item taken from cache does not match our query name, thus - * security needs to be re-examined later */ - if(msg && query_dname_compare(qstate->qinfo.qname, - iq->qchase.qname) != 0) - msg->rep->security = sec_status_unchecked; - } - if(msg) { - /* handle positive cache response */ - enum response_type type = response_type_from_cache(msg, - &iq->qchase); - if(verbosity >= VERB_ALGO) { - log_dns_msg("msg from cache lookup", &msg->qinfo, - msg->rep); - verbose(VERB_ALGO, "msg ttl is %d, prefetch ttl %d", - (int)msg->rep->ttl, - (int)msg->rep->prefetch_ttl); - } - - if(type == RESPONSE_TYPE_CNAME) { - uint8_t* sname = 0; - size_t slen = 0; - verbose(VERB_ALGO, "returning CNAME response from " - "cache"); - if(!handle_cname_response(qstate, iq, msg, - &sname, &slen)) { - errinf(qstate, "failed to prepend CNAME " - "components, malloc failure"); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - iq->qchase.qname = sname; - iq->qchase.qname_len = slen; - /* This *is* a query restart, even if it is a cheap - * one. */ - iq->dp = NULL; - iq->refetch_glue = 0; - iq->query_restart_count++; - iq->sent_count = 0; - iq->dp_target_count = 0; - sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - return next_state(iq, INIT_REQUEST_STATE); - } - - /* if from cache, NULL, else insert 'cache IP' len=0 */ - if(qstate->reply_origin) - sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); - if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_SERVFAIL) - errinf(qstate, "SERVFAIL in cache"); - /* it is an answer, response, to final state */ - verbose(VERB_ALGO, "returning answer from cache."); - iq->response = msg; - return final_state(iq); - } - - /* attempt to forward the request */ - if(forward_request(qstate, iq)) - { - if(!iq->dp) { - log_err("alloc failure for forward dp"); - errinf(qstate, "malloc failure for forward zone"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if((qstate->query_flags&BIT_RD)==0) { - /* If the server accepts RD=0 queries and forwards - * with RD=1, then if the server is listed as an NS - * entry, it starts query loops. Stop that loop by - * disallowing the query. The RD=0 was previously used - * to check the cache with allow_snoop. For stubs, - * the iterator pass would have primed the stub and - * then cached information can be used for further - * queries. */ - verbose(VERB_ALGO, "cannot forward RD=0 query, to stop query loops"); - errinf(qstate, "cannot forward RD=0 query"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - iq->refetch_glue = 0; - iq->minimisation_state = DONOT_MINIMISE_STATE; - /* the request has been forwarded. - * forwarded requests need to be immediately sent to the - * next state, QUERYTARGETS. */ - return next_state(iq, QUERYTARGETS_STATE); - } - - /* Resolver Algorithm Step 2 -- find the "best" servers. */ - - /* first, adjust for DS queries. To avoid the grandparent problem, - * we just look for the closest set of server to the parent of qname. - * When re-fetching glue we also need to ask the parent. - */ - if(iq->refetch_glue) { - if(!iq->dp) { - log_err("internal or malloc fail: no dp for refetch"); - errinf(qstate, "malloc failure, for delegation info"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - delname = iq->dp->name; - delnamelen = iq->dp->namelen; - } else { - delname = iq->qchase.qname; - delnamelen = iq->qchase.qname_len; - } - if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue || - (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway - && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) { - /* remove first label from delname, root goes to hints, - * but only to fetch glue, not for qtype=DS. */ - /* also when prefetching an NS record, fetch it again from - * its parent, just as if it expired, so that you do not - * get stuck on an older nameserver that gives old NSrecords */ - if(dname_is_root(delname) && (iq->refetch_glue || - (iq->qchase.qtype == LDNS_RR_TYPE_NS && - qstate->prefetch_leeway))) - delname = NULL; /* go to root priming */ - else dname_remove_label(&delname, &delnamelen); - } - /* delname is the name to lookup a delegation for. If NULL rootprime */ - while(1) { - - /* Lookup the delegation in the cache. If null, then the - * cache needs to be primed for the qclass. */ - if(delname) - iq->dp = dns_cache_find_delegation(qstate->env, delname, - delnamelen, iq->qchase.qtype, iq->qchase.qclass, - qstate->region, &iq->deleg_msg, - *qstate->env->now+qstate->prefetch_leeway, 1, - dpname, dpnamelen); - else iq->dp = NULL; - - /* If the cache has returned nothing, then we have a - * root priming situation. */ - if(iq->dp == NULL) { - int r; - /* if under auth zone, no prime needed */ - if(!auth_zone_delegpt(qstate, iq, delname, delnamelen)) - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - if(iq->dp) /* use auth zone dp */ - return next_state(iq, INIT_REQUEST_2_STATE); - /* if there is a stub, then no root prime needed */ - r = prime_stub(qstate, iq, id, delname, - iq->qchase.qclass); - if(r == 2) - break; /* got noprime-stub-zone, continue */ - else if(r) - return 0; /* stub prime request made */ - if(forwards_lookup_root(qstate->env->fwds, - iq->qchase.qclass)) { - /* forward zone root, no root prime needed */ - /* fill in some dp - safety belt */ - iq->dp = hints_lookup_root(qstate->env->hints, - iq->qchase.qclass); - if(!iq->dp) { - log_err("internal error: no hints dp"); - errinf(qstate, "no hints for this class"); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - iq->dp = delegpt_copy(iq->dp, qstate->region); - if(!iq->dp) { - log_err("out of memory in safety belt"); - errinf(qstate, "malloc failure, in safety belt"); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - return next_state(iq, INIT_REQUEST_2_STATE); - } - /* Note that the result of this will set a new - * DelegationPoint based on the result of priming. */ - if(!prime_root(qstate, iq, id, iq->qchase.qclass)) - return error_response(qstate, id, - LDNS_RCODE_REFUSED); - - /* priming creates and sends a subordinate query, with - * this query as the parent. So further processing for - * this event will stop until reactivated by the - * results of priming. */ - return 0; - } - if(!iq->ratelimit_ok && qstate->prefetch_leeway) - iq->ratelimit_ok = 1; /* allow prefetches, this keeps - otherwise valid data in the cache */ - - /* see if this dp not useless. - * It is useless if: - * o all NS items are required glue. - * or the query is for NS item that is required glue. - * o no addresses are provided. - * o RD qflag is on. - * Instead, go up one level, and try to get even further - * If the root was useless, use safety belt information. - * Only check cache returns, because replies for servers - * could be useless but lead to loops (bumping into the - * same server reply) if useless-checked. - */ - if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags, - iq->dp, ie->supports_ipv4, ie->supports_ipv6, - ie->use_nat64)) { - struct delegpt* retdp = NULL; - if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) { - if(retdp) { - verbose(VERB_QUERY, "cache has stub " - "or fwd but no addresses, " - "fallback to config"); - iq->dp = delegpt_copy(retdp, - qstate->region); - if(!iq->dp) { - log_err("out of memory in " - "stub/fwd fallback"); - errinf(qstate, "malloc failure, for fallback to config"); - return error_response(qstate, - id, LDNS_RCODE_SERVFAIL); - } - break; - } - verbose(VERB_ALGO, "useless dp " - "but cannot go up, servfail"); - delegpt_log(VERB_ALGO, iq->dp); - errinf(qstate, "no useful nameservers, " - "and cannot go up"); - errinf_dname(qstate, "for zone", iq->dp->name); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - if(dname_is_root(iq->dp->name)) { - /* use safety belt */ - verbose(VERB_QUERY, "Cache has root NS but " - "no addresses. Fallback to the safety belt."); - iq->dp = hints_lookup_root(qstate->env->hints, - iq->qchase.qclass); - /* note deleg_msg is from previous lookup, - * but RD is on, so it is not used */ - if(!iq->dp) { - log_err("internal error: no hints dp"); - return error_response(qstate, id, - LDNS_RCODE_REFUSED); - } - iq->dp = delegpt_copy(iq->dp, qstate->region); - if(!iq->dp) { - log_err("out of memory in safety belt"); - errinf(qstate, "malloc failure, in safety belt, for root"); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - break; - } else { - verbose(VERB_ALGO, - "cache delegation was useless:"); - delegpt_log(VERB_ALGO, iq->dp); - /* go up */ - delname = iq->dp->name; - delnamelen = iq->dp->namelen; - dname_remove_label(&delname, &delnamelen); - } - } else break; - } - - verbose(VERB_ALGO, "cache delegation returns delegpt"); - delegpt_log(VERB_ALGO, iq->dp); - - /* Otherwise, set the current delegation point and move on to the - * next state. */ - return next_state(iq, INIT_REQUEST_2_STATE); -} - -/** - * Process the second part of the initial request handling. This state - * basically exists so that queries that generate root priming events have - * the same init processing as ones that do not. Request events that reach - * this state must have a valid currentDelegationPoint set. - * - * This part is primarily handling stub zone priming. Events that reach this - * state must have a current delegation point. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @return true if the event needs more request processing immediately, - * false if not. - */ -static int -processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq, - int id) -{ - uint8_t* delname; - size_t delnamelen; - log_query_info(VERB_QUERY, "resolving (init part 2): ", - &qstate->qinfo); - - delname = iq->qchase.qname; - delnamelen = iq->qchase.qname_len; - if(iq->refetch_glue) { - struct iter_hints_stub* stub; - if(!iq->dp) { - log_err("internal or malloc fail: no dp for refetch"); - errinf(qstate, "malloc failure, no delegation info"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - /* Do not send queries above stub, do not set delname to dp if - * this is above stub without stub-first. */ - stub = hints_lookup_stub( - qstate->env->hints, iq->qchase.qname, iq->qchase.qclass, - iq->dp); - if(!stub || !stub->dp->has_parent_side_NS || - dname_subdomain_c(iq->dp->name, stub->dp->name)) { - delname = iq->dp->name; - delnamelen = iq->dp->namelen; - } - } - if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) { - if(!dname_is_root(delname)) - dname_remove_label(&delname, &delnamelen); - iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */ - } - - /* see if we have an auth zone to answer from, improves dp from cache - * (if any dp from cache) with auth zone dp, if that is lower */ - if(!auth_zone_delegpt(qstate, iq, delname, delnamelen)) - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - - /* Check to see if we need to prime a stub zone. */ - if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) { - /* A priming sub request was made */ - return 0; - } - - /* most events just get forwarded to the next state. */ - return next_state(iq, INIT_REQUEST_3_STATE); -} - -/** - * Process the third part of the initial request handling. This state exists - * as a separate state so that queries that generate stub priming events - * will get the tail end of the init process but not repeat the stub priming - * check. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @return true, advancing the event to the QUERYTARGETS_STATE. - */ -static int -processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq, - int id) -{ - log_query_info(VERB_QUERY, "resolving (init part 3): ", - &qstate->qinfo); - /* if the cache reply dp equals a validation anchor or msg has DS, - * then DNSSEC RRSIGs are expected in the reply */ - iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp, - iq->deleg_msg, iq->qchase.qclass); - - /* If the RD flag wasn't set, then we just finish with the - * cached referral as the response. */ - if(!(qstate->query_flags & BIT_RD) && iq->deleg_msg) { - iq->response = iq->deleg_msg; - if(verbosity >= VERB_ALGO && iq->response) - log_dns_msg("no RD requested, using delegation msg", - &iq->response->qinfo, iq->response->rep); - if(qstate->reply_origin) - sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); - return final_state(iq); - } - /* After this point, unset the RD flag -- this query is going to - * be sent to an auth. server. */ - iq->chase_flags &= ~BIT_RD; - - /* if dnssec expected, fetch key for the trust-anchor or cached-DS */ - if(iq->dnssec_expected && qstate->env->cfg->prefetch_key && - !(qstate->query_flags&BIT_CD)) { - generate_dnskey_prefetch(qstate, iq, id); - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - } - - /* Jump to the next state. */ - return next_state(iq, QUERYTARGETS_STATE); -} - -/** - * Given a basic query, generate a parent-side "target" query. - * These are subordinate queries for missing delegation point target addresses, - * for which only the parent of the delegation provides correct IP addresses. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @param name: target qname. - * @param namelen: target qname length. - * @param qtype: target qtype (either A or AAAA). - * @param qclass: target qclass. - * @return true on success, false on failure. - */ -static int -generate_parentside_target_query(struct module_qstate* qstate, - struct iter_qstate* iq, int id, uint8_t* name, size_t namelen, - uint16_t qtype, uint16_t qclass) -{ - struct module_qstate* subq; - if(!generate_sub_request(name, namelen, qtype, qclass, qstate, - id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) - return 0; - if(subq) { - struct iter_qstate* subiq = - (struct iter_qstate*)subq->minfo[id]; - /* blacklist the cache - we want to fetch parent stuff */ - sock_list_insert(&subq->blacklist, NULL, 0, subq->region); - subiq->query_for_pside_glue = 1; - if(dname_subdomain_c(name, iq->dp->name)) { - subiq->dp = delegpt_copy(iq->dp, subq->region); - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, - subq->qinfo.qclass); - subiq->refetch_glue = 1; - } else { - subiq->dp = dns_cache_find_delegation(qstate->env, - name, namelen, qtype, qclass, subq->region, - &subiq->deleg_msg, - *qstate->env->now+subq->prefetch_leeway, - 1, NULL, 0); - /* if no dp, then it's from root, refetch unneeded */ - if(subiq->dp) { - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, - subq->qinfo.qclass); - subiq->refetch_glue = 1; - } - } - } - log_nametypeclass(VERB_QUERY, "new pside target", name, qtype, qclass); - return 1; -} - -/** - * Given a basic query, generate a "target" query. These are subordinate - * queries for missing delegation point target addresses. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @param name: target qname. - * @param namelen: target qname length. - * @param qtype: target qtype (either A or AAAA). - * @param qclass: target qclass. - * @return true on success, false on failure. - */ -static int -generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq, - int id, uint8_t* name, size_t namelen, uint16_t qtype, uint16_t qclass) -{ - struct module_qstate* subq; - if(!generate_sub_request(name, namelen, qtype, qclass, qstate, - id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) - return 0; - log_nametypeclass(VERB_QUERY, "new target", name, qtype, qclass); - return 1; -} - -/** - * Given an event at a certain state, generate zero or more target queries - * for it's current delegation point. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param ie: iterator shared global environment. - * @param id: module id. - * @param maxtargets: The maximum number of targets to query for. - * if it is negative, there is no maximum number of targets. - * @param num: returns the number of queries generated and processed, - * which may be zero if there were no missing targets. - * @return false on error. - */ -static int -query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id, int maxtargets, int* num) -{ - int query_count = 0; - struct delegpt_ns* ns; - int missing; - int toget = 0; - - iter_mark_cycle_targets(qstate, iq->dp); - missing = (int)delegpt_count_missing_targets(iq->dp, NULL); - log_assert(maxtargets != 0); /* that would not be useful */ - - /* Generate target requests. Basically, any missing targets - * are queried for here, regardless if it is necessary to do - * so to continue processing. */ - if(maxtargets < 0 || maxtargets > missing) - toget = missing; - else toget = maxtargets; - if(toget == 0) { - *num = 0; - return 1; - } - - /* now that we are sure that a target query is going to be made, - * check the limits. */ - if(iq->depth == ie->max_dependency_depth) - return 0; - if(iq->depth > 0 && iq->target_count && - iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) { - char s[LDNS_MAX_DOMAINLEN+1]; - dname_str(qstate->qinfo.qname, s); - verbose(VERB_QUERY, "request %s has exceeded the maximum " - "number of glue fetches %d", s, - iq->target_count[TARGET_COUNT_QUERIES]); - return 0; - } - if(iq->dp_target_count > MAX_DP_TARGET_COUNT) { - char s[LDNS_MAX_DOMAINLEN+1]; - dname_str(qstate->qinfo.qname, s); - verbose(VERB_QUERY, "request %s has exceeded the maximum " - "number of glue fetches %d to a single delegation point", - s, iq->dp_target_count); - return 0; - } - - /* select 'toget' items from the total of 'missing' items */ - log_assert(toget <= missing); - - /* loop over missing targets */ - for(ns = iq->dp->nslist; ns; ns = ns->next) { - if(ns->resolved) - continue; - - /* randomly select this item with probability toget/missing */ - if(!iter_ns_probability(qstate->env->rnd, toget, missing)) { - /* do not select this one, next; select toget number - * of items from a list one less in size */ - missing --; - continue; - } - - if(ie->supports_ipv6 && - ((ns->lame && !ns->done_pside6) || - (!ns->lame && !ns->got6))) { - /* Send the AAAA request. */ - if(!generate_target_query(qstate, iq, id, - ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, iq->qchase.qclass)) { - *num = query_count; - if(query_count > 0) - qstate->ext_state[id] = module_wait_subquery; - return 0; - } - query_count++; - /* If the mesh query list is full, exit the loop here. - * This makes the routine spawn one query at a time, - * and this means there is no query state load - * increase, because the spawned state uses cpu and a - * socket while this state waits for that spawned - * state. Next time we can look up further targets */ - if(mesh_jostle_exceeded(qstate->env->mesh)) - break; - } - /* Send the A request. */ - if((ie->supports_ipv4 || ie->use_nat64) && - ((ns->lame && !ns->done_pside4) || - (!ns->lame && !ns->got4))) { - if(!generate_target_query(qstate, iq, id, - ns->name, ns->namelen, - LDNS_RR_TYPE_A, iq->qchase.qclass)) { - *num = query_count; - if(query_count > 0) - qstate->ext_state[id] = module_wait_subquery; - return 0; - } - query_count++; - /* If the mesh query list is full, exit the loop. */ - if(mesh_jostle_exceeded(qstate->env->mesh)) - break; - } - - /* mark this target as in progress. */ - ns->resolved = 1; - missing--; - toget--; - if(toget == 0) - break; - } - *num = query_count; - if(query_count > 0) - qstate->ext_state[id] = module_wait_subquery; - - return 1; -} - -/** - * Called by processQueryTargets when it would like extra targets to query - * but it seems to be out of options. At last resort some less appealing - * options are explored. If there are no more options, the result is SERVFAIL - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param ie: iterator shared global environment. - * @param id: module id. - * @return true if the event requires more request processing immediately, - * false if not. - */ -static int -processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - struct delegpt_ns* ns; - int query_count = 0; - verbose(VERB_ALGO, "No more query targets, attempting last resort"); - log_assert(iq->dp); - - if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, - iq->qchase.qclass, NULL)) { - /* fail -- no more targets, no more hope of targets, no hope - * of a response. */ - errinf(qstate, "all the configured stub or forward servers failed,"); - errinf_dname(qstate, "at zone", iq->dp->name); - errinf_reply(qstate, iq); - verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL"); - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) { - struct delegpt* p = hints_lookup_root(qstate->env->hints, - iq->qchase.qclass); - if(p) { - struct delegpt_addr* a; - iq->chase_flags &= ~BIT_RD; /* go to authorities */ - for(ns = p->nslist; ns; ns=ns->next) { - (void)delegpt_add_ns(iq->dp, qstate->region, - ns->name, ns->lame, ns->tls_auth_name, - ns->port); - } - for(a = p->target_list; a; a=a->next_target) { - (void)delegpt_add_addr(iq->dp, qstate->region, - &a->addr, a->addrlen, a->bogus, - a->lame, a->tls_auth_name, -1, NULL); - } - } - iq->dp->has_parent_side_NS = 1; - } else if(!iq->dp->has_parent_side_NS) { - if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp, - qstate->region, &qstate->qinfo) - || !iq->dp->has_parent_side_NS) { - /* if: malloc failure in lookup go up to try */ - /* if: no parent NS in cache - go up one level */ - verbose(VERB_ALGO, "try to grab parent NS"); - iq->store_parent_NS = iq->dp; - iq->chase_flags &= ~BIT_RD; /* go to authorities */ - iq->deleg_msg = NULL; - iq->refetch_glue = 1; - iq->query_restart_count++; - iq->sent_count = 0; - iq->dp_target_count = 0; - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - return next_state(iq, INIT_REQUEST_STATE); - } - } - /* see if that makes new names available */ - if(!cache_fill_missing(qstate->env, iq->qchase.qclass, - qstate->region, iq->dp)) - log_err("out of memory in cache_fill_missing"); - if(iq->dp->usable_list) { - verbose(VERB_ALGO, "try parent-side-name, w. glue from cache"); - return next_state(iq, QUERYTARGETS_STATE); - } - /* try to fill out parent glue from cache */ - if(iter_lookup_parent_glue_from_cache(qstate->env, iq->dp, - qstate->region, &qstate->qinfo)) { - /* got parent stuff from cache, see if we can continue */ - verbose(VERB_ALGO, "try parent-side glue from cache"); - return next_state(iq, QUERYTARGETS_STATE); - } - /* query for an extra name added by the parent-NS record */ - if(delegpt_count_missing_targets(iq->dp, NULL) > 0) { - int qs = 0; - verbose(VERB_ALGO, "try parent-side target name"); - if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) { - errinf(qstate, "could not fetch nameserver"); - errinf_dname(qstate, "at zone", iq->dp->name); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - iq->num_target_queries += qs; - target_count_increase(iq, qs); - if(qs != 0) { - qstate->ext_state[id] = module_wait_subquery; - return 0; /* and wait for them */ - } - } - if(iq->depth == ie->max_dependency_depth) { - verbose(VERB_QUERY, "maxdepth and need more nameservers, fail"); - errinf(qstate, "cannot fetch more nameservers because at max dependency depth"); - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(iq->depth > 0 && iq->target_count && - iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) { - char s[LDNS_MAX_DOMAINLEN+1]; - dname_str(qstate->qinfo.qname, s); - verbose(VERB_QUERY, "request %s has exceeded the maximum " - "number of glue fetches %d", s, - iq->target_count[TARGET_COUNT_QUERIES]); - errinf(qstate, "exceeded the maximum number of glue fetches"); - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - /* mark cycle targets for parent-side lookups */ - iter_mark_pside_cycle_targets(qstate, iq->dp); - /* see if we can issue queries to get nameserver addresses */ - /* this lookup is not randomized, but sequential. */ - for(ns = iq->dp->nslist; ns; ns = ns->next) { - /* if this nameserver is at a delegation point, but that - * delegation point is a stub and we cannot go higher, skip*/ - if( ((ie->supports_ipv6 && !ns->done_pside6) || - ((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) && - !can_have_last_resort(qstate->env, ns->name, ns->namelen, - iq->qchase.qclass, NULL)) { - log_nametypeclass(VERB_ALGO, "cannot pside lookup ns " - "because it is also a stub/forward,", - ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); - if(ie->supports_ipv6) ns->done_pside6 = 1; - if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1; - continue; - } - /* query for parent-side A and AAAA for nameservers */ - if(ie->supports_ipv6 && !ns->done_pside6) { - /* Send the AAAA request. */ - if(!generate_parentside_target_query(qstate, iq, id, - ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, iq->qchase.qclass)) { - errinf_dname(qstate, "could not generate nameserver AAAA lookup for", ns->name); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - ns->done_pside6 = 1; - query_count++; - if(mesh_jostle_exceeded(qstate->env->mesh)) { - /* Wait for the lookup; do not spawn multiple - * lookups at a time. */ - verbose(VERB_ALGO, "try parent-side glue lookup"); - iq->num_target_queries += query_count; - target_count_increase(iq, query_count); - qstate->ext_state[id] = module_wait_subquery; - return 0; - } - } - if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) { - /* Send the A request. */ - if(!generate_parentside_target_query(qstate, iq, id, - ns->name, ns->namelen, - LDNS_RR_TYPE_A, iq->qchase.qclass)) { - errinf_dname(qstate, "could not generate nameserver A lookup for", ns->name); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - ns->done_pside4 = 1; - query_count++; - } - if(query_count != 0) { /* suspend to await results */ - verbose(VERB_ALGO, "try parent-side glue lookup"); - iq->num_target_queries += query_count; - target_count_increase(iq, query_count); - qstate->ext_state[id] = module_wait_subquery; - return 0; - } - } - - /* if this was a parent-side glue query itself, then store that - * failure in cache. */ - if(!qstate->no_cache_store && iq->query_for_pside_glue - && !iq->pside_glue) - iter_store_parentside_neg(qstate->env, &qstate->qinfo, - iq->deleg_msg?iq->deleg_msg->rep: - (iq->response?iq->response->rep:NULL)); - - errinf(qstate, "all servers for this domain failed,"); - errinf_dname(qstate, "at zone", iq->dp->name); - errinf_reply(qstate, iq); - verbose(VERB_QUERY, "out of query targets -- returning SERVFAIL"); - /* fail -- no more targets, no more hope of targets, no hope - * of a response. */ - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); -} - -/** - * Try to find the NS record set that will resolve a qtype DS query. Due - * to grandparent/grandchild reasons we did not get a proper lookup right - * away. We need to create type NS queries until we get the right parent - * for this lookup. We remove labels from the query to find the right point. - * If we end up at the old dp name, then there is no solution. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @return true if the event requires more immediate processing, false if - * not. This is generally only true when forwarding the request to - * the final state (i.e., on answer). - */ -static int -processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id) -{ - struct module_qstate* subq = NULL; - verbose(VERB_ALGO, "processDSNSFind"); - - if(!iq->dsns_point) { - /* initialize */ - iq->dsns_point = iq->qchase.qname; - iq->dsns_point_len = iq->qchase.qname_len; - } - /* robustcheck for internal error: we are not underneath the dp */ - if(!dname_subdomain_c(iq->dsns_point, iq->dp->name)) { - errinf_dname(qstate, "for DS query parent-child nameserver search the query is not under the zone", iq->dp->name); - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - - /* go up one (more) step, until we hit the dp, if so, end */ - dname_remove_label(&iq->dsns_point, &iq->dsns_point_len); - if(query_dname_compare(iq->dsns_point, iq->dp->name) == 0) { - /* there was no inbetween nameserver, use the old delegation - * point again. And this time, because dsns_point is nonNULL - * we are going to accept the (bad) result */ - iq->state = QUERYTARGETS_STATE; - return 1; - } - iq->state = DSNS_FIND_STATE; - - /* spawn NS lookup (validation not needed, this is for DS lookup) */ - log_nametypeclass(VERB_ALGO, "fetch nameservers", - iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass); - if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len, - LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) { - errinf_dname(qstate, "for DS query parent-child nameserver search, could not generate NS lookup for", iq->dsns_point); - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - - return 0; -} - -/** - * Check if we wait responses for sent queries and update the iterator's - * external state. - */ -static void -check_waiting_queries(struct iter_qstate* iq, struct module_qstate* qstate, - int id) -{ - if(iq->num_target_queries>0 && iq->num_current_queries>0) { - verbose(VERB_ALGO, "waiting for %d targets to " - "resolve or %d outstanding queries to " - "respond", iq->num_target_queries, - iq->num_current_queries); - qstate->ext_state[id] = module_wait_reply; - } else if(iq->num_target_queries>0) { - verbose(VERB_ALGO, "waiting for %d targets to " - "resolve", iq->num_target_queries); - qstate->ext_state[id] = module_wait_subquery; - } else { - verbose(VERB_ALGO, "waiting for %d " - "outstanding queries to respond", - iq->num_current_queries); - qstate->ext_state[id] = module_wait_reply; - } -} - -/** - * This is the request event state where the request will be sent to one of - * its current query targets. This state also handles issuing target lookup - * queries for missing target IP addresses. Queries typically iterate on - * this state, both when they are just trying different targets for a given - * delegation point, and when they change delegation points. This state - * roughly corresponds to RFC 1034 algorithm steps 3 and 4. - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param ie: iterator shared global environment. - * @param id: module id. - * @return true if the event requires more request processing immediately, - * false if not. This state only returns true when it is generating - * a SERVFAIL response because the query has hit a dead end. - */ -static int -processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - int tf_policy; - struct delegpt_addr* target; - struct outbound_entry* outq; - struct sockaddr_storage real_addr; - socklen_t real_addrlen; - int auth_fallback = 0; - uint8_t* qout_orig = NULL; - size_t qout_orig_len = 0; - int sq_check_ratelimit = 1; - int sq_was_ratelimited = 0; - int can_do_promisc = 0; - - /* NOTE: a request will encounter this state for each target it - * needs to send a query to. That is, at least one per referral, - * more if some targets timeout or return throwaway answers. */ - - log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo); - verbose(VERB_ALGO, "processQueryTargets: targetqueries %d, " - "currentqueries %d sentcount %d", iq->num_target_queries, - iq->num_current_queries, iq->sent_count); - - /* Make sure that we haven't run away */ - if(iq->referral_count > MAX_REFERRAL_COUNT) { - verbose(VERB_QUERY, "request has exceeded the maximum " - "number of referrrals with %d", iq->referral_count); - errinf(qstate, "exceeded the maximum of referrals"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(iq->sent_count > ie->max_sent_count) { - verbose(VERB_QUERY, "request has exceeded the maximum " - "number of sends with %d", iq->sent_count); - errinf(qstate, "exceeded the maximum number of sends"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - /* Check if we reached MAX_TARGET_NX limit without a fallback activation. */ - if(iq->target_count && !*iq->nxns_dp && - iq->target_count[TARGET_COUNT_NX] > MAX_TARGET_NX) { - struct delegpt_ns* ns; - /* If we can wait for resolution, do so. */ - if(iq->num_target_queries>0 || iq->num_current_queries>0) { - check_waiting_queries(iq, qstate, id); - return 0; - } - verbose(VERB_ALGO, "request has exceeded the maximum " - "number of nxdomain nameserver lookups (%d) with %d", - MAX_TARGET_NX, iq->target_count[TARGET_COUNT_NX]); - /* Check for dp because we require one below */ - if(!iq->dp) { - verbose(VERB_QUERY, "Failed to get a delegation, " - "giving up"); - errinf(qstate, "failed to get a delegation (eg. prime " - "failure)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - /* We reached the limit but we already have parent side - * information; stop resolution */ - if(iq->dp->has_parent_side_NS) { - verbose(VERB_ALGO, "parent-side information is " - "already present for the delegation point, no " - "fallback possible"); - errinf(qstate, "exceeded the maximum nameserver nxdomains"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - verbose(VERB_ALGO, "initiating parent-side fallback for " - "nxdomain nameserver lookups"); - /* Mark all the current NSes as resolved to allow for parent - * fallback */ - for(ns=iq->dp->nslist; ns; ns=ns->next) { - ns->resolved = 1; - } - /* Note the delegation point that triggered the NXNS fallback; - * no reason for shared queries to keep trying there. - * This also marks the fallback activation. */ - *iq->nxns_dp = malloc(iq->dp->namelen); - if(!*iq->nxns_dp) { - verbose(VERB_ALGO, "out of memory while initiating " - "fallback"); - errinf(qstate, "exceeded the maximum nameserver " - "nxdomains (malloc)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - memcpy(*iq->nxns_dp, iq->dp->name, iq->dp->namelen); - } else if(iq->target_count && *iq->nxns_dp) { - /* Handle the NXNS fallback case. */ - /* If we can wait for resolution, do so. */ - if(iq->num_target_queries>0 || iq->num_current_queries>0) { - check_waiting_queries(iq, qstate, id); - return 0; - } - /* Check for dp because we require one below */ - if(!iq->dp) { - verbose(VERB_QUERY, "Failed to get a delegation, " - "giving up"); - errinf(qstate, "failed to get a delegation (eg. prime " - "failure)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - if(iq->target_count[TARGET_COUNT_NX] > MAX_TARGET_NX_FALLBACK) { - verbose(VERB_ALGO, "request has exceeded the maximum " - "number of fallback nxdomain nameserver " - "lookups (%d) with %d", MAX_TARGET_NX_FALLBACK, - iq->target_count[TARGET_COUNT_NX]); - errinf(qstate, "exceeded the maximum nameserver nxdomains"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - if(!iq->dp->has_parent_side_NS) { - struct delegpt_ns* ns; - if(!dname_canonical_compare(*iq->nxns_dp, iq->dp->name)) { - verbose(VERB_ALGO, "this delegation point " - "initiated the fallback, marking the " - "nslist as resolved"); - for(ns=iq->dp->nslist; ns; ns=ns->next) { - ns->resolved = 1; - } - } - } - } - - /* Make sure we have a delegation point, otherwise priming failed - * or another failure occurred */ - if(!iq->dp) { - verbose(VERB_QUERY, "Failed to get a delegation, giving up"); - errinf(qstate, "failed to get a delegation (eg. prime failure)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(!ie->supports_ipv6) - delegpt_no_ipv6(iq->dp); - if(!ie->supports_ipv4 && !ie->use_nat64) - delegpt_no_ipv4(iq->dp); - delegpt_log(VERB_ALGO, iq->dp); - - if(iq->num_current_queries>0) { - /* already busy answering a query, this restart is because - * more delegpt addrs became available, wait for existing - * query. */ - verbose(VERB_ALGO, "woke up, but wait for outstanding query"); - qstate->ext_state[id] = module_wait_reply; - return 0; - } - - if(iq->minimisation_state == INIT_MINIMISE_STATE - && !(iq->chase_flags & BIT_RD)) { - /* (Re)set qinfo_out to (new) delegation point, except when - * qinfo_out is already a subdomain of dp. This happens when - * increasing by more than one label at once (QNAMEs with more - * than MAX_MINIMISE_COUNT labels). */ - if(!(iq->qinfo_out.qname_len - && dname_subdomain_c(iq->qchase.qname, - iq->qinfo_out.qname) - && dname_subdomain_c(iq->qinfo_out.qname, - iq->dp->name))) { - iq->qinfo_out.qname = iq->dp->name; - iq->qinfo_out.qname_len = iq->dp->namelen; - iq->qinfo_out.qtype = LDNS_RR_TYPE_A; - iq->qinfo_out.qclass = iq->qchase.qclass; - iq->qinfo_out.local_alias = NULL; - iq->minimise_count = 0; - } - - iq->minimisation_state = MINIMISE_STATE; - } - if(iq->minimisation_state == MINIMISE_STATE) { - int qchaselabs = dname_count_labels(iq->qchase.qname); - int labdiff = qchaselabs - - dname_count_labels(iq->qinfo_out.qname); - - qout_orig = iq->qinfo_out.qname; - qout_orig_len = iq->qinfo_out.qname_len; - iq->qinfo_out.qname = iq->qchase.qname; - iq->qinfo_out.qname_len = iq->qchase.qname_len; - iq->minimise_count++; - iq->timeout_count = 0; - - iter_dec_attempts(iq->dp, 1, ie->outbound_msg_retry); - - /* Limit number of iterations for QNAMEs with more - * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB - * labels of QNAME always individually. - */ - if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 && - iq->minimise_count > MINIMISE_ONE_LAB) { - if(iq->minimise_count < MAX_MINIMISE_COUNT) { - int multilabs = qchaselabs - 1 - - MINIMISE_ONE_LAB; - int extralabs = multilabs / - MINIMISE_MULTIPLE_LABS; - - if (MAX_MINIMISE_COUNT - iq->minimise_count >= - multilabs % MINIMISE_MULTIPLE_LABS) - /* Default behaviour is to add 1 label - * every iteration. Therefore, decrement - * the extralabs by 1 */ - extralabs--; - if (extralabs < labdiff) - labdiff -= extralabs; - else - labdiff = 1; - } - /* Last minimised iteration, send all labels with - * QTYPE=NS */ - else - labdiff = 1; - } - - if(labdiff > 1) { - verbose(VERB_QUERY, "removing %d labels", labdiff-1); - dname_remove_labels(&iq->qinfo_out.qname, - &iq->qinfo_out.qname_len, - labdiff-1); - } - if(labdiff < 1 || (labdiff < 2 - && (iq->qchase.qtype == LDNS_RR_TYPE_DS - || iq->qchase.qtype == LDNS_RR_TYPE_A))) - /* Stop minimising this query, resolve "as usual" */ - iq->minimisation_state = DONOT_MINIMISE_STATE; - else if(!qstate->no_cache_lookup) { - struct dns_msg* msg = dns_cache_lookup(qstate->env, - iq->qinfo_out.qname, iq->qinfo_out.qname_len, - iq->qinfo_out.qtype, iq->qinfo_out.qclass, - qstate->query_flags, qstate->region, - qstate->env->scratch, 0, iq->dp->name, - iq->dp->namelen); - if(msg && FLAGS_GET_RCODE(msg->rep->flags) == - LDNS_RCODE_NOERROR) - /* no need to send query if it is already - * cached as NOERROR */ - return 1; - if(msg && FLAGS_GET_RCODE(msg->rep->flags) == - LDNS_RCODE_NXDOMAIN && - qstate->env->need_to_validate && - qstate->env->cfg->harden_below_nxdomain) { - if(msg->rep->security == sec_status_secure) { - iq->response = msg; - return final_state(iq); - } - if(msg->rep->security == sec_status_unchecked) { - struct module_qstate* subq = NULL; - if(!generate_sub_request( - iq->qinfo_out.qname, - iq->qinfo_out.qname_len, - iq->qinfo_out.qtype, - iq->qinfo_out.qclass, - qstate, id, iq, - INIT_REQUEST_STATE, - FINISHED_STATE, &subq, 1, 1)) - verbose(VERB_ALGO, - "could not validate NXDOMAIN " - "response"); - } - } - if(msg && FLAGS_GET_RCODE(msg->rep->flags) == - LDNS_RCODE_NXDOMAIN) { - /* return and add a label in the next - * minimisation iteration. - */ - return 1; - } - } - } - if(iq->minimisation_state == SKIP_MINIMISE_STATE) { - if(iq->timeout_count < MAX_MINIMISE_TIMEOUT_COUNT) - /* Do not increment qname, continue incrementing next - * iteration */ - iq->minimisation_state = MINIMISE_STATE; - else if(!qstate->env->cfg->qname_minimisation_strict) - /* Too many time-outs detected for this QNAME and QTYPE. - * We give up, disable QNAME minimisation. */ - iq->minimisation_state = DONOT_MINIMISE_STATE; - } - if(iq->minimisation_state == DONOT_MINIMISE_STATE) - iq->qinfo_out = iq->qchase; - - /* now find an answer to this query */ - /* see if authority zones have an answer */ - /* now we know the dp, we can check the auth zone for locally hosted - * contents */ - if(!iq->auth_zone_avoid && qstate->blacklist) { - if(auth_zones_can_fallback(qstate->env->auth_zones, - iq->dp->name, iq->dp->namelen, iq->qinfo_out.qclass)) { - /* if cache is blacklisted and this zone allows us - * to fallback to the internet, then do so, and - * fetch results from the internet servers */ - iq->auth_zone_avoid = 1; - } - } - if(iq->auth_zone_avoid) { - iq->auth_zone_avoid = 0; - auth_fallback = 1; - } else if(auth_zones_lookup(qstate->env->auth_zones, &iq->qinfo_out, - qstate->region, &iq->response, &auth_fallback, iq->dp->name, - iq->dp->namelen)) { - /* use this as a response to be processed by the iterator */ - if(verbosity >= VERB_ALGO) { - log_dns_msg("msg from auth zone", - &iq->response->qinfo, iq->response->rep); - } - if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) { - verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone"); - } else { - lock_rw_wrlock(&qstate->env->auth_zones->lock); - qstate->env->auth_zones->num_query_up++; - lock_rw_unlock(&qstate->env->auth_zones->lock); - iq->num_current_queries++; - iq->chase_to_rd = 0; - iq->dnssec_lame_query = 0; - iq->auth_zone_response = 1; - return next_state(iq, QUERY_RESP_STATE); - } - } - iq->auth_zone_response = 0; - if(auth_fallback == 0) { - /* like we got servfail from the auth zone lookup, and - * no internet fallback */ - verbose(VERB_ALGO, "auth zone lookup failed, no fallback," - " servfail"); - errinf(qstate, "auth zone lookup failed, fallback is off"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(iq->dp->auth_dp) { - /* we wanted to fallback, but had no delegpt, only the - * auth zone generated delegpt, create an actual one */ - iq->auth_zone_avoid = 1; - return next_state(iq, INIT_REQUEST_STATE); - } - /* but mostly, fallback==1 (like, when no such auth zone exists) - * and we continue with lookups */ - - tf_policy = 0; - /* < not <=, because although the array is large enough for <=, the - * generated query will immediately be discarded due to depth and - * that servfail is cached, which is not good as opportunism goes. */ - if(iq->depth < ie->max_dependency_depth - && iq->num_target_queries == 0 - && (!iq->target_count || iq->target_count[TARGET_COUNT_NX]==0) - && iq->sent_count < TARGET_FETCH_STOP) { - can_do_promisc = 1; - } - /* if the mesh query list is full, then do not waste cpu and sockets to - * fetch promiscuous targets. They can be looked up when needed. */ - if(can_do_promisc && !mesh_jostle_exceeded(qstate->env->mesh)) { - tf_policy = ie->target_fetch_policy[iq->depth]; - } - - /* if in 0x20 fallback get as many targets as possible */ - if(iq->caps_fallback) { - int extra = 0; - size_t naddr, nres, navail; - if(!query_for_targets(qstate, iq, ie, id, -1, &extra)) { - errinf(qstate, "could not fetch nameservers for 0x20 fallback"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - iq->num_target_queries += extra; - target_count_increase(iq, extra); - if(iq->num_target_queries > 0) { - /* wait to get all targets, we want to try em */ - verbose(VERB_ALGO, "wait for all targets for fallback"); - qstate->ext_state[id] = module_wait_reply; - /* undo qname minimise step because we'll get back here - * to do it again */ - if(qout_orig && iq->minimise_count > 0) { - iq->minimise_count--; - iq->qinfo_out.qname = qout_orig; - iq->qinfo_out.qname_len = qout_orig_len; - } - return 0; - } - /* did we do enough fallback queries already? */ - delegpt_count_addr(iq->dp, &naddr, &nres, &navail); - /* the current caps_server is the number of fallbacks sent. - * the original query is one that matched too, so we have - * caps_server+1 number of matching queries now */ - if(iq->caps_server+1 >= naddr*3 || - iq->caps_server*2+2 >= (size_t)ie->max_sent_count) { - /* *2 on sentcount check because ipv6 may fail */ - /* we're done, process the response */ - verbose(VERB_ALGO, "0x20 fallback had %d responses " - "match for %d wanted, done.", - (int)iq->caps_server+1, (int)naddr*3); - iq->response = iq->caps_response; - iq->caps_fallback = 0; - iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); /* space for fallback */ - iq->num_current_queries++; /* RespState decrements it*/ - iq->referral_count++; /* make sure we don't loop */ - iq->sent_count = 0; - iq->dp_target_count = 0; - iq->state = QUERY_RESP_STATE; - return 1; - } - verbose(VERB_ALGO, "0x20 fallback number %d", - (int)iq->caps_server); - - /* if there is a policy to fetch missing targets - * opportunistically, do it. we rely on the fact that once a - * query (or queries) for a missing name have been issued, - * they will not show up again. */ - } else if(tf_policy != 0) { - int extra = 0; - verbose(VERB_ALGO, "attempt to get extra %d targets", - tf_policy); - (void)query_for_targets(qstate, iq, ie, id, tf_policy, &extra); - /* errors ignored, these targets are not strictly necessary for - * this result, we do not have to reply with SERVFAIL */ - iq->num_target_queries += extra; - target_count_increase(iq, extra); - } - - /* Add the current set of unused targets to our queue. */ - delegpt_add_unused_targets(iq->dp); - - if(qstate->env->auth_zones) { - /* apply rpz triggers at query time */ - struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq); - if(forged_response != NULL) { - qstate->ext_state[id] = module_finished; - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = forged_response; - iq->response = forged_response; - next_state(iq, FINISHED_STATE); - if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { - log_err("rpz: prepend rrsets: out of memory"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - return 0; - } - } - - /* Select the next usable target, filtering out unsuitable targets. */ - target = iter_server_selection(ie, qstate->env, iq->dp, - iq->dp->name, iq->dp->namelen, iq->qchase.qtype, - &iq->dnssec_lame_query, &iq->chase_to_rd, - iq->num_target_queries, qstate->blacklist, - qstate->prefetch_leeway); - - /* If no usable target was selected... */ - if(!target) { - /* Here we distinguish between three states: generate a new - * target query, just wait, or quit (with a SERVFAIL). - * We have the following information: number of active - * target queries, number of active current queries, - * the presence of missing targets at this delegation - * point, and the given query target policy. */ - - /* Check for the wait condition. If this is true, then - * an action must be taken. */ - if(iq->num_target_queries==0 && iq->num_current_queries==0) { - /* If there is nothing to wait for, then we need - * to distinguish between generating (a) new target - * query, or failing. */ - if(delegpt_count_missing_targets(iq->dp, NULL) > 0) { - int qs = 0; - verbose(VERB_ALGO, "querying for next " - "missing target"); - if(!query_for_targets(qstate, iq, ie, id, - 1, &qs)) { - errinf(qstate, "could not fetch nameserver"); - errinf_dname(qstate, "at zone", iq->dp->name); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - if(qs == 0 && - delegpt_count_missing_targets(iq->dp, NULL) == 0){ - /* it looked like there were missing - * targets, but they did not turn up. - * Try the bad choices again (if any), - * when we get back here missing==0, - * so this is not a loop. */ - return 1; - } - iq->num_target_queries += qs; - target_count_increase(iq, qs); - } - /* Since a target query might have been made, we - * need to check again. */ - if(iq->num_target_queries == 0) { - /* if in capsforid fallback, instead of last - * resort, we agree with the current reply - * we have (if any) (our count of addrs bad)*/ - if(iq->caps_fallback && iq->caps_reply) { - /* we're done, process the response */ - verbose(VERB_ALGO, "0x20 fallback had %d responses, " - "but no more servers except " - "last resort, done.", - (int)iq->caps_server+1); - iq->response = iq->caps_response; - iq->caps_fallback = 0; - iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); /* space for fallback */ - iq->num_current_queries++; /* RespState decrements it*/ - iq->referral_count++; /* make sure we don't loop */ - iq->sent_count = 0; - iq->dp_target_count = 0; - iq->state = QUERY_RESP_STATE; - return 1; - } - return processLastResort(qstate, iq, ie, id); - } - } - - /* otherwise, we have no current targets, so submerge - * until one of the target or direct queries return. */ - verbose(VERB_ALGO, "no current targets"); - check_waiting_queries(iq, qstate, id); - /* undo qname minimise step because we'll get back here - * to do it again */ - if(qout_orig && iq->minimise_count > 0) { - iq->minimise_count--; - iq->qinfo_out.qname = qout_orig; - iq->qinfo_out.qname_len = qout_orig_len; - } - return 0; - } - - /* We have a target. We could have created promiscuous target - * queries but we are currently under pressure (mesh_jostle_exceeded). - * If we are configured to allow promiscuous target queries and haven't - * gone out to the network for a target query for this delegation, then - * it is possible to slip in a promiscuous one with a 1/10 chance. */ - if(can_do_promisc && tf_policy == 0 && iq->depth == 0 - && iq->depth < ie->max_dependency_depth - && ie->target_fetch_policy[iq->depth] != 0 - && iq->dp_target_count == 0 - && !ub_random_max(qstate->env->rnd, 10)) { - int extra = 0; - verbose(VERB_ALGO, "available target exists in cache but " - "attempt to get extra 1 target"); - (void)query_for_targets(qstate, iq, ie, id, 1, &extra); - /* errors ignored, these targets are not strictly necessary for - * this result, we do not have to reply with SERVFAIL */ - if(extra > 0) { - iq->num_target_queries += extra; - target_count_increase(iq, extra); - check_waiting_queries(iq, qstate, id); - /* undo qname minimise step because we'll get back here - * to do it again */ - if(qout_orig && iq->minimise_count > 0) { - iq->minimise_count--; - iq->qinfo_out.qname = qout_orig; - iq->qinfo_out.qname_len = qout_orig_len; - } - return 0; - } - } - - /* Do not check ratelimit for forwarding queries or if we already got a - * pass. */ - sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok); - /* We have a valid target. */ - if(verbosity >= VERB_QUERY) { - log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out); - log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name, - &target->addr, target->addrlen); - verbose(VERB_ALGO, "dnssec status: %s%s", - iq->dnssec_expected?"expected": "not expected", - iq->dnssec_lame_query?" but lame_query anyway": ""); - } - - real_addr = target->addr; - real_addrlen = target->addrlen; - - if(ie->use_nat64 && target->addr.ss_family == AF_INET) { - addr_to_nat64(&target->addr, &ie->nat64_prefix_addr, - ie->nat64_prefix_addrlen, ie->nat64_prefix_net, - &real_addr, &real_addrlen); - log_name_addr(VERB_QUERY, "applied NAT64:", - iq->dp->name, &real_addr, real_addrlen); - } - - fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query)); - outq = (*qstate->env->send_query)(&iq->qinfo_out, - iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), - /* unset CD if to forwarder(RD set) and not dnssec retry - * (blacklist nonempty) and no trust-anchors are configured - * above the qname or on the first attempt when dnssec is on */ - EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& - !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env, - &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), - iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( - ie, iq), sq_check_ratelimit, &real_addr, real_addrlen, - iq->dp->name, iq->dp->namelen, - (iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream), - (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), - target->tls_auth_name, qstate, &sq_was_ratelimited); - if(!outq) { - if(sq_was_ratelimited) { - lock_basic_lock(&ie->queries_ratelimit_lock); - ie->num_queries_ratelimited++; - lock_basic_unlock(&ie->queries_ratelimit_lock); - verbose(VERB_ALGO, "query exceeded ratelimits"); - qstate->was_ratelimited = 1; - errinf_dname(qstate, "exceeded ratelimit for zone", - iq->dp->name); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - log_addr(VERB_QUERY, "error sending query to auth server", - &real_addr, real_addrlen); - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = SKIP_MINIMISE_STATE; - return next_state(iq, QUERYTARGETS_STATE); - } - outbound_list_insert(&iq->outlist, outq); - iq->num_current_queries++; - iq->sent_count++; - qstate->ext_state[id] = module_wait_reply; - - return 0; -} - -/** find NS rrset in given list */ -static struct ub_packed_rrset_key* -find_NS(struct reply_info* rep, size_t from, size_t to) -{ - size_t i; - for(i=from; irrsets[i]->rk.type) == LDNS_RR_TYPE_NS) - return rep->rrsets[i]; - } - return NULL; -} - - -/** - * Process the query response. All queries end up at this state first. This - * process generally consists of analyzing the response and routing the - * event to the next state (either bouncing it back to a request state, or - * terminating the processing for this event). - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param ie: iterator shared global environment. - * @param id: module id. - * @return true if the event requires more immediate processing, false if - * not. This is generally only true when forwarding the request to - * the final state (i.e., on answer). - */ -static int -processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - int dnsseclame = 0, origtypecname = 0; - enum response_type type; - - iq->num_current_queries--; - - if(!inplace_cb_query_response_call(qstate->env, qstate, iq->response)) - log_err("unable to call query_response callback"); - - if(iq->response == NULL) { - /* Don't increment qname when QNAME minimisation is enabled */ - if(qstate->env->cfg->qname_minimisation) { - iq->minimisation_state = SKIP_MINIMISE_STATE; - } - iq->timeout_count++; - iq->chase_to_rd = 0; - iq->dnssec_lame_query = 0; - verbose(VERB_ALGO, "query response was timeout"); - return next_state(iq, QUERYTARGETS_STATE); - } - iq->timeout_count = 0; - type = response_type_from_server( - (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qinfo_out, iq->dp); - iq->chase_to_rd = 0; - /* remove TC flag, if this is erroneously set by TCP upstream */ - iq->response->rep->flags &= ~BIT_TC; - if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) && - !iq->auth_zone_response) { - /* When forwarding (RD bit is set), we handle referrals - * differently. No queries should be sent elsewhere */ - type = RESPONSE_TYPE_ANSWER; - } - if(!qstate->env->cfg->disable_dnssec_lame_check && iq->dnssec_expected - && !iq->dnssec_lame_query && - !(iq->chase_flags&BIT_RD) - && iq->sent_count < DNSSEC_LAME_DETECT_COUNT - && type != RESPONSE_TYPE_LAME - && type != RESPONSE_TYPE_REC_LAME - && type != RESPONSE_TYPE_THROWAWAY - && type != RESPONSE_TYPE_UNTYPED) { - /* a possible answer, see if it is missing DNSSEC */ - /* but not when forwarding, so we dont mark fwder lame */ - if(!iter_msg_has_dnssec(iq->response)) { - /* Mark this address as dnsseclame in this dp, - * because that will make serverselection disprefer - * it, but also, once it is the only final option, - * use dnssec-lame-bypass if it needs to query there.*/ - if(qstate->reply) { - struct delegpt_addr* a = delegpt_find_addr( - iq->dp, &qstate->reply->remote_addr, - qstate->reply->remote_addrlen); - if(a) a->dnsseclame = 1; - } - /* test the answer is from the zone we expected, - * otherwise, (due to parent,child on same server), we - * might mark the server,zone lame inappropriately */ - if(!iter_msg_from_zone(iq->response, iq->dp, type, - iq->qchase.qclass)) - qstate->reply = NULL; - type = RESPONSE_TYPE_LAME; - dnsseclame = 1; - } - } else iq->dnssec_lame_query = 0; - /* see if referral brings us close to the target */ - if(type == RESPONSE_TYPE_REFERRAL) { - struct ub_packed_rrset_key* ns = find_NS( - iq->response->rep, iq->response->rep->an_numrrsets, - iq->response->rep->an_numrrsets - + iq->response->rep->ns_numrrsets); - if(!ns) ns = find_NS(iq->response->rep, 0, - iq->response->rep->an_numrrsets); - if(!ns || !dname_strict_subdomain_c(ns->rk.dname, iq->dp->name) - || !dname_subdomain_c(iq->qchase.qname, ns->rk.dname)){ - verbose(VERB_ALGO, "bad referral, throwaway"); - type = RESPONSE_TYPE_THROWAWAY; - } else - iter_scrub_ds(iq->response, ns, iq->dp->name); - } else iter_scrub_ds(iq->response, NULL, NULL); - if(type == RESPONSE_TYPE_THROWAWAY && - FLAGS_GET_RCODE(iq->response->rep->flags) == LDNS_RCODE_YXDOMAIN) { - /* YXDOMAIN is a permanent error, no need to retry */ - type = RESPONSE_TYPE_ANSWER; - } - if(type == RESPONSE_TYPE_CNAME) - origtypecname = 1; - if(type == RESPONSE_TYPE_CNAME && iq->response->rep->an_numrrsets >= 1 - && ntohs(iq->response->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DNAME) { - uint8_t* sname = NULL; - size_t snamelen = 0; - get_cname_target(iq->response->rep->rrsets[0], &sname, - &snamelen); - if(snamelen && dname_subdomain_c(sname, iq->response->rep->rrsets[0]->rk.dname)) { - /* DNAME to a subdomain loop; do not recurse */ - type = RESPONSE_TYPE_ANSWER; - } - } else if(type == RESPONSE_TYPE_CNAME && - iq->qchase.qtype == LDNS_RR_TYPE_CNAME && - iq->minimisation_state == MINIMISE_STATE && - query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) { - /* The minimised query for full QTYPE and hidden QTYPE can be - * classified as CNAME response type, even when the original - * QTYPE=CNAME. This should be treated as answer response type. - */ - type = RESPONSE_TYPE_ANSWER; - } - - /* handle each of the type cases */ - if(type == RESPONSE_TYPE_ANSWER) { - /* ANSWER type responses terminate the query algorithm, - * so they sent on their */ - if(verbosity >= VERB_DETAIL) { - verbose(VERB_DETAIL, "query response was %s", - FLAGS_GET_RCODE(iq->response->rep->flags) - ==LDNS_RCODE_NXDOMAIN?"NXDOMAIN ANSWER": - (iq->response->rep->an_numrrsets?"ANSWER": - "nodata ANSWER")); - } - /* if qtype is DS, check we have the right level of answer, - * like grandchild answer but we need the middle, reject it */ - if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point - && !(iq->chase_flags&BIT_RD) - && iter_ds_toolow(iq->response, iq->dp) - && iter_dp_cangodown(&iq->qchase, iq->dp)) { - /* close down outstanding requests to be discarded */ - outbound_list_clear(&iq->outlist); - iq->num_current_queries = 0; - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - iq->num_target_queries = 0; - return processDSNSFind(qstate, iq, id); - } - if(!qstate->no_cache_store) - iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, - iq->qchase.qtype != iq->response->qinfo.qtype, - qstate->prefetch_leeway, - iq->dp&&iq->dp->has_parent_side_NS, - qstate->region, qstate->query_flags, - qstate->qstarttime); - /* close down outstanding requests to be discarded */ - outbound_list_clear(&iq->outlist); - iq->num_current_queries = 0; - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - iq->num_target_queries = 0; - if(qstate->reply) - sock_list_insert(&qstate->reply_origin, - &qstate->reply->remote_addr, - qstate->reply->remote_addrlen, qstate->region); - if(iq->minimisation_state != DONOT_MINIMISE_STATE - && !(iq->chase_flags & BIT_RD)) { - if(FLAGS_GET_RCODE(iq->response->rep->flags) != - LDNS_RCODE_NOERROR) { - if(qstate->env->cfg->qname_minimisation_strict) { - if(FLAGS_GET_RCODE(iq->response->rep->flags) == - LDNS_RCODE_NXDOMAIN) { - iter_scrub_nxdomain(iq->response); - return final_state(iq); - } - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - /* Best effort qname-minimisation. - * Stop minimising and send full query when - * RCODE is not NOERROR. */ - iq->minimisation_state = DONOT_MINIMISE_STATE; - } - if(FLAGS_GET_RCODE(iq->response->rep->flags) == - LDNS_RCODE_NXDOMAIN && !origtypecname) { - /* Stop resolving when NXDOMAIN is DNSSEC - * signed. Based on assumption that nameservers - * serving signed zones do not return NXDOMAIN - * for empty-non-terminals. */ - /* If this response is actually a CNAME type, - * the nxdomain rcode may not be for the qname, - * and so it is not the final response. */ - if(iq->dnssec_expected) - return final_state(iq); - /* Make subrequest to validate intermediate - * NXDOMAIN if harden-below-nxdomain is - * enabled. */ - if(qstate->env->cfg->harden_below_nxdomain && - qstate->env->need_to_validate) { - struct module_qstate* subq = NULL; - log_query_info(VERB_QUERY, - "schedule NXDOMAIN validation:", - &iq->response->qinfo); - if(!generate_sub_request( - iq->response->qinfo.qname, - iq->response->qinfo.qname_len, - iq->response->qinfo.qtype, - iq->response->qinfo.qclass, - qstate, id, iq, - INIT_REQUEST_STATE, - FINISHED_STATE, &subq, 1, 1)) - verbose(VERB_ALGO, - "could not validate NXDOMAIN " - "response"); - } - } - return next_state(iq, QUERYTARGETS_STATE); - } - return final_state(iq); - } else if(type == RESPONSE_TYPE_REFERRAL) { - /* REFERRAL type responses get a reset of the - * delegation point, and back to the QUERYTARGETS_STATE. */ - verbose(VERB_DETAIL, "query response was REFERRAL"); - - /* if hardened, only store referral if we asked for it */ - if(!qstate->no_cache_store && - (!qstate->env->cfg->harden_referral_path || - ( qstate->qinfo.qtype == LDNS_RR_TYPE_NS - && (qstate->query_flags&BIT_RD) - && !(qstate->query_flags&BIT_CD) - /* we know that all other NS rrsets are scrubbed - * away, thus on referral only one is left. - * see if that equals the query name... */ - && ( /* auth section, but sometimes in answer section*/ - reply_find_rrset_section_ns(iq->response->rep, - iq->qchase.qname, iq->qchase.qname_len, - LDNS_RR_TYPE_NS, iq->qchase.qclass) - || reply_find_rrset_section_an(iq->response->rep, - iq->qchase.qname, iq->qchase.qname_len, - LDNS_RR_TYPE_NS, iq->qchase.qclass) - ) - ))) { - /* Store the referral under the current query */ - /* no prefetch-leeway, since its not the answer */ - iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 1, 0, 0, NULL, 0, - qstate->qstarttime); - if(iq->store_parent_NS) - iter_store_parentside_NS(qstate->env, - iq->response->rep); - if(qstate->env->neg_cache) - val_neg_addreferral(qstate->env->neg_cache, - iq->response->rep, iq->dp->name); - } - /* store parent-side-in-zone-glue, if directly queried for */ - if(!qstate->no_cache_store && iq->query_for_pside_glue - && !iq->pside_glue) { - iq->pside_glue = reply_find_rrset(iq->response->rep, - iq->qchase.qname, iq->qchase.qname_len, - iq->qchase.qtype, iq->qchase.qclass); - if(iq->pside_glue) { - log_rrset_key(VERB_ALGO, "found parent-side " - "glue", iq->pside_glue); - iter_store_parentside_rrset(qstate->env, - iq->pside_glue); - } - } - - /* Reset the event state, setting the current delegation - * point to the referral. */ - iq->deleg_msg = iq->response; - iq->dp = delegpt_from_message(iq->response, qstate->region); - if (qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - if(!iq->dp) { - errinf(qstate, "malloc failure, for delegation point"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(!cache_fill_missing(qstate->env, iq->qchase.qclass, - qstate->region, iq->dp)) { - errinf(qstate, "malloc failure, copy extra info into delegation point"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - if(iq->store_parent_NS && query_dname_compare(iq->dp->name, - iq->store_parent_NS->name) == 0) - iter_merge_retry_counts(iq->dp, iq->store_parent_NS, - ie->outbound_msg_retry); - delegpt_log(VERB_ALGO, iq->dp); - /* Count this as a referral. */ - iq->referral_count++; - iq->sent_count = 0; - iq->dp_target_count = 0; - /* see if the next dp is a trust anchor, or a DS was sent - * along, indicating dnssec is expected for next zone */ - iq->dnssec_expected = iter_indicates_dnssec(qstate->env, - iq->dp, iq->response, iq->qchase.qclass); - /* if dnssec, validating then also fetch the key for the DS */ - if(iq->dnssec_expected && qstate->env->cfg->prefetch_key && - !(qstate->query_flags&BIT_CD)) - generate_dnskey_prefetch(qstate, iq, id); - - /* spawn off NS and addr to auth servers for the NS we just - * got in the referral. This gets authoritative answer - * (answer section trust level) rrset. - * right after, we detach the subs, answer goes to cache. */ - if(qstate->env->cfg->harden_referral_path) - generate_ns_check(qstate, iq, id); - - /* stop current outstanding queries. - * FIXME: should the outstanding queries be waited for and - * handled? Say by a subquery that inherits the outbound_entry. - */ - outbound_list_clear(&iq->outlist); - iq->num_current_queries = 0; - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - iq->num_target_queries = 0; - iq->response = NULL; - iq->fail_addr_type = 0; - verbose(VERB_ALGO, "cleared outbound list for next round"); - return next_state(iq, QUERYTARGETS_STATE); - } else if(type == RESPONSE_TYPE_CNAME) { - uint8_t* sname = NULL; - size_t snamelen = 0; - /* CNAME type responses get a query restart (i.e., get a - * reset of the query state and go back to INIT_REQUEST_STATE). - */ - verbose(VERB_DETAIL, "query response was CNAME"); - if(verbosity >= VERB_ALGO) - log_dns_msg("cname msg", &iq->response->qinfo, - iq->response->rep); - /* if qtype is DS, check we have the right level of answer, - * like grandchild answer but we need the middle, reject it */ - if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point - && !(iq->chase_flags&BIT_RD) - && iter_ds_toolow(iq->response, iq->dp) - && iter_dp_cangodown(&iq->qchase, iq->dp)) { - outbound_list_clear(&iq->outlist); - iq->num_current_queries = 0; - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - iq->num_target_queries = 0; - return processDSNSFind(qstate, iq, id); - } - /* Process the CNAME response. */ - if(!handle_cname_response(qstate, iq, iq->response, - &sname, &snamelen)) { - errinf(qstate, "malloc failure, CNAME info"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - /* cache the CNAME response under the current query */ - /* NOTE : set referral=1, so that rrsets get stored but not - * the partial query answer (CNAME only). */ - /* prefetchleeway applied because this updates answer parts */ - if(!qstate->no_cache_store) - iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 1, qstate->prefetch_leeway, - iq->dp&&iq->dp->has_parent_side_NS, NULL, - qstate->query_flags, qstate->qstarttime); - /* set the current request's qname to the new value. */ - iq->qchase.qname = sname; - iq->qchase.qname_len = snamelen; - if(qstate->env->auth_zones) { - /* apply rpz qname triggers after cname */ - struct dns_msg* forged_response = - rpz_callback_from_iterator_cname(qstate, iq); - while(forged_response && reply_find_rrset_section_an( - forged_response->rep, iq->qchase.qname, - iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, - iq->qchase.qclass)) { - /* another cname to follow */ - if(!handle_cname_response(qstate, iq, forged_response, - &sname, &snamelen)) { - errinf(qstate, "malloc failure, CNAME info"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - iq->qchase.qname = sname; - iq->qchase.qname_len = snamelen; - forged_response = - rpz_callback_from_iterator_cname(qstate, iq); - } - if(forged_response != NULL) { - qstate->ext_state[id] = module_finished; - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = forged_response; - iq->response = forged_response; - next_state(iq, FINISHED_STATE); - if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { - log_err("rpz: after cname, prepend rrsets: out of memory"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - qstate->return_msg->qinfo = qstate->qinfo; - return 0; - } - } - /* Clear the query state, since this is a query restart. */ - iq->deleg_msg = NULL; - iq->dp = NULL; - iq->dsns_point = NULL; - iq->auth_zone_response = 0; - iq->sent_count = 0; - iq->dp_target_count = 0; - if(iq->minimisation_state != MINIMISE_STATE) - /* Only count as query restart when it is not an extra - * query as result of qname minimisation. */ - iq->query_restart_count++; - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - - /* stop current outstanding queries. - * FIXME: should the outstanding queries be waited for and - * handled? Say by a subquery that inherits the outbound_entry. - */ - outbound_list_clear(&iq->outlist); - iq->num_current_queries = 0; - fptr_ok(fptr_whitelist_modenv_detach_subs( - qstate->env->detach_subs)); - (*qstate->env->detach_subs)(qstate); - iq->num_target_queries = 0; - if(qstate->reply) - sock_list_insert(&qstate->reply_origin, - &qstate->reply->remote_addr, - qstate->reply->remote_addrlen, qstate->region); - verbose(VERB_ALGO, "cleared outbound list for query restart"); - /* go to INIT_REQUEST_STATE for new qname. */ - return next_state(iq, INIT_REQUEST_STATE); - } else if(type == RESPONSE_TYPE_LAME) { - /* Cache the LAMEness. */ - verbose(VERB_DETAIL, "query response was %sLAME", - dnsseclame?"DNSSEC ":""); - if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) { - log_err("mark lame: mismatch in qname and dpname"); - /* throwaway this reply below */ - } else if(qstate->reply) { - /* need addr for lameness cache, but we may have - * gotten this from cache, so test to be sure */ - if(!infra_set_lame(qstate->env->infra_cache, - &qstate->reply->remote_addr, - qstate->reply->remote_addrlen, - iq->dp->name, iq->dp->namelen, - *qstate->env->now, dnsseclame, 0, - iq->qchase.qtype)) - log_err("mark host lame: out of memory"); - } - } else if(type == RESPONSE_TYPE_REC_LAME) { - /* Cache the LAMEness. */ - verbose(VERB_DETAIL, "query response REC_LAME: " - "recursive but not authoritative server"); - if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) { - log_err("mark rec_lame: mismatch in qname and dpname"); - /* throwaway this reply below */ - } else if(qstate->reply) { - /* need addr for lameness cache, but we may have - * gotten this from cache, so test to be sure */ - verbose(VERB_DETAIL, "mark as REC_LAME"); - if(!infra_set_lame(qstate->env->infra_cache, - &qstate->reply->remote_addr, - qstate->reply->remote_addrlen, - iq->dp->name, iq->dp->namelen, - *qstate->env->now, 0, 1, iq->qchase.qtype)) - log_err("mark host lame: out of memory"); - } - } else if(type == RESPONSE_TYPE_THROWAWAY) { - /* LAME and THROWAWAY responses are handled the same way. - * In this case, the event is just sent directly back to - * the QUERYTARGETS_STATE without resetting anything, - * because, clearly, the next target must be tried. */ - verbose(VERB_DETAIL, "query response was THROWAWAY"); - } else { - log_warn("A query response came back with an unknown type: %d", - (int)type); - } - - /* LAME, THROWAWAY and "unknown" all end up here. - * Recycle to the QUERYTARGETS state to hopefully try a - * different target. */ - if (qstate->env->cfg->qname_minimisation && - !qstate->env->cfg->qname_minimisation_strict) - iq->minimisation_state = DONOT_MINIMISE_STATE; - if(iq->auth_zone_response) { - /* can we fallback? */ - iq->auth_zone_response = 0; - if(!auth_zones_can_fallback(qstate->env->auth_zones, - iq->dp->name, iq->dp->namelen, qstate->qinfo.qclass)) { - verbose(VERB_ALGO, "auth zone response bad, and no" - " fallback possible, servfail"); - errinf_dname(qstate, "response is bad, no fallback, " - "for auth zone", iq->dp->name); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - verbose(VERB_ALGO, "auth zone response was bad, " - "fallback enabled"); - iq->auth_zone_avoid = 1; - if(iq->dp->auth_dp) { - /* we are using a dp for the auth zone, with no - * nameservers, get one first */ - iq->dp = NULL; - return next_state(iq, INIT_REQUEST_STATE); - } - } - return next_state(iq, QUERYTARGETS_STATE); -} - -/** - * Return priming query results to interested super querystates. - * - * Sets the delegation point and delegation message (not nonRD queries). - * This is a callback from walk_supers. - * - * @param qstate: priming query state that finished. - * @param id: module id. - * @param forq: the qstate for which priming has been done. - */ -static void -prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq) -{ - struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; - struct delegpt* dp = NULL; - - log_assert(qstate->is_priming || foriq->wait_priming_stub); - log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR); - /* Convert our response to a delegation point */ - dp = delegpt_from_message(qstate->return_msg, forq->region); - if(!dp) { - /* if there is no convertible delegation point, then - * the ANSWER type was (presumably) a negative answer. */ - verbose(VERB_ALGO, "prime response was not a positive " - "ANSWER; failing"); - foriq->dp = NULL; - foriq->state = QUERYTARGETS_STATE; - return; - } - - log_query_info(VERB_DETAIL, "priming successful for", &qstate->qinfo); - delegpt_log(VERB_ALGO, dp); - foriq->dp = dp; - foriq->deleg_msg = dns_copy_msg(qstate->return_msg, forq->region); - if(!foriq->deleg_msg) { - log_err("copy prime response: out of memory"); - foriq->dp = NULL; - foriq->state = QUERYTARGETS_STATE; - return; - } - - /* root priming responses go to init stage 2, priming stub - * responses to to stage 3. */ - if(foriq->wait_priming_stub) { - foriq->state = INIT_REQUEST_3_STATE; - foriq->wait_priming_stub = 0; - } else foriq->state = INIT_REQUEST_2_STATE; - /* because we are finished, the parent will be reactivated */ -} - -/** - * This handles the response to a priming query. This is used to handle both - * root and stub priming responses. This is basically the equivalent of the - * QUERY_RESP_STATE, but will not handle CNAME responses and will treat - * REFERRALs as ANSWERS. It will also update and reactivate the originating - * event. - * - * @param qstate: query state. - * @param id: module id. - * @return true if the event needs more immediate processing, false if not. - * This state always returns false. - */ -static int -processPrimeResponse(struct module_qstate* qstate, int id) -{ - struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; - enum response_type type; - iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */ - type = response_type_from_server( - (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qchase, iq->dp); - if(type == RESPONSE_TYPE_ANSWER) { - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = iq->response; - } else { - errinf(qstate, "prime response did not get an answer"); - errinf_dname(qstate, "for", qstate->qinfo.qname); - qstate->return_rcode = LDNS_RCODE_SERVFAIL; - qstate->return_msg = NULL; - } - - /* validate the root or stub after priming (if enabled). - * This is the same query as the prime query, but with validation. - * Now that we are primed, the additional queries that validation - * may need can be resolved. */ - if(qstate->env->cfg->harden_referral_path) { - struct module_qstate* subq = NULL; - log_nametypeclass(VERB_ALGO, "schedule prime validation", - qstate->qinfo.qname, qstate->qinfo.qtype, - qstate->qinfo.qclass); - if(!generate_sub_request(qstate->qinfo.qname, - qstate->qinfo.qname_len, qstate->qinfo.qtype, - qstate->qinfo.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate prime check"); - } - generate_a_aaaa_check(qstate, iq, id); - } - - /* This event is finished. */ - qstate->ext_state[id] = module_finished; - return 0; -} - -/** - * Do final processing on responses to target queries. Events reach this - * state after the iterative resolution algorithm terminates. This state is - * responsible for reactivating the original event, and housekeeping related - * to received target responses (caching, updating the current delegation - * point, etc). - * Callback from walk_supers for every super state that is interested in - * the results from this query. - * - * @param qstate: query state. - * @param id: module id. - * @param forq: super query state. - */ -static void -processTargetResponse(struct module_qstate* qstate, int id, - struct module_qstate* forq) -{ - struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; - struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; - struct ub_packed_rrset_key* rrset; - struct delegpt_ns* dpns; - log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR); - - foriq->state = QUERYTARGETS_STATE; - log_query_info(VERB_ALGO, "processTargetResponse", &qstate->qinfo); - log_query_info(VERB_ALGO, "processTargetResponse super", &forq->qinfo); - - /* Tell the originating event that this target query has finished - * (regardless if it succeeded or not). */ - foriq->num_target_queries--; - - /* check to see if parent event is still interested (in orig name). */ - if(!foriq->dp) { - verbose(VERB_ALGO, "subq: parent not interested, was reset"); - return; /* not interested anymore */ - } - dpns = delegpt_find_ns(foriq->dp, qstate->qinfo.qname, - qstate->qinfo.qname_len); - if(!dpns) { - /* If not interested, just stop processing this event */ - verbose(VERB_ALGO, "subq: parent not interested anymore"); - /* could be because parent was jostled out of the cache, - and a new identical query arrived, that does not want it*/ - return; - } - - /* if iq->query_for_pside_glue then add the pside_glue (marked lame) */ - if(iq->pside_glue) { - /* if the pside_glue is NULL, then it could not be found, - * the done_pside is already set when created and a cache - * entry created in processFinished so nothing to do here */ - log_rrset_key(VERB_ALGO, "add parentside glue to dp", - iq->pside_glue); - if(!delegpt_add_rrset(foriq->dp, forq->region, - iq->pside_glue, 1, NULL)) - log_err("out of memory adding pside glue"); - } - - /* This response is relevant to the current query, so we - * add (attempt to add, anyway) this target(s) and reactivate - * the original event. - * NOTE: we could only look for the AnswerRRset if the - * response type was ANSWER. */ - rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep); - if(rrset) { - int additions = 0; - /* if CNAMEs have been followed - add new NS to delegpt. */ - /* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */ - if(!delegpt_find_ns(foriq->dp, rrset->rk.dname, - rrset->rk.dname_len)) { - /* if dpns->lame then set newcname ns lame too */ - if(!delegpt_add_ns(foriq->dp, forq->region, - rrset->rk.dname, dpns->lame, dpns->tls_auth_name, - dpns->port)) - log_err("out of memory adding cnamed-ns"); - } - /* if dpns->lame then set the address(es) lame too */ - if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, - dpns->lame, &additions)) - log_err("out of memory adding targets"); - if(!additions) { - /* no new addresses, increase the nxns counter, like - * this could be a list of wildcards with no new - * addresses */ - target_count_increase_nx(foriq, 1); - } - verbose(VERB_ALGO, "added target response"); - delegpt_log(VERB_ALGO, foriq->dp); - } else { - verbose(VERB_ALGO, "iterator TargetResponse failed"); - delegpt_mark_neg(dpns, qstate->qinfo.qtype); - if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) && - (dpns->got6 == 2 || !ie->supports_ipv6)) { - dpns->resolved = 1; /* fail the target */ - /* do not count cached answers */ - if(qstate->reply_origin && qstate->reply_origin->len != 0) { - target_count_increase_nx(foriq, 1); - } - } - } -} - -/** - * Process response for DS NS Find queries, that attempt to find the delegation - * point where we ask the DS query from. - * - * @param qstate: query state. - * @param id: module id. - * @param forq: super query state. - */ -static void -processDSNSResponse(struct module_qstate* qstate, int id, - struct module_qstate* forq) -{ - struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; - - /* if the finished (iq->response) query has no NS set: continue - * up to look for the right dp; nothing to change, do DPNSstate */ - if(qstate->return_rcode != LDNS_RCODE_NOERROR) - return; /* seek further */ - /* find the NS RRset (without allowing CNAMEs) */ - if(!reply_find_rrset(qstate->return_msg->rep, qstate->qinfo.qname, - qstate->qinfo.qname_len, LDNS_RR_TYPE_NS, - qstate->qinfo.qclass)){ - return; /* seek further */ - } - - /* else, store as DP and continue at querytargets */ - foriq->state = QUERYTARGETS_STATE; - foriq->dp = delegpt_from_message(qstate->return_msg, forq->region); - if(!foriq->dp) { - log_err("out of memory in dsns dp alloc"); - errinf(qstate, "malloc failure, in DS search"); - return; /* dp==NULL in QUERYTARGETS makes SERVFAIL */ - } - /* success, go query the querytargets in the new dp (and go down) */ -} - -/** - * Process response for qclass=ANY queries for a particular class. - * Append to result or error-exit. - * - * @param qstate: query state. - * @param id: module id. - * @param forq: super query state. - */ -static void -processClassResponse(struct module_qstate* qstate, int id, - struct module_qstate* forq) -{ - struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; - struct dns_msg* from = qstate->return_msg; - log_query_info(VERB_ALGO, "processClassResponse", &qstate->qinfo); - log_query_info(VERB_ALGO, "processClassResponse super", &forq->qinfo); - if(qstate->return_rcode != LDNS_RCODE_NOERROR) { - /* cause servfail for qclass ANY query */ - foriq->response = NULL; - foriq->state = FINISHED_STATE; - return; - } - /* append result */ - if(!foriq->response) { - /* allocate the response: copy RCODE, sec_state */ - foriq->response = dns_copy_msg(from, forq->region); - if(!foriq->response) { - log_err("malloc failed for qclass ANY response"); - foriq->state = FINISHED_STATE; - return; - } - foriq->response->qinfo.qclass = forq->qinfo.qclass; - /* qclass ANY does not receive the AA flag on replies */ - foriq->response->rep->authoritative = 0; - } else { - struct dns_msg* to = foriq->response; - /* add _from_ this response _to_ existing collection */ - /* if there are records, copy RCODE */ - /* lower sec_state if this message is lower */ - if(from->rep->rrset_count != 0) { - size_t n = from->rep->rrset_count+to->rep->rrset_count; - struct ub_packed_rrset_key** dest, **d; - /* copy appropriate rcode */ - to->rep->flags = from->rep->flags; - /* copy rrsets */ - if(from->rep->rrset_count > RR_COUNT_MAX || - to->rep->rrset_count > RR_COUNT_MAX) { - log_err("malloc failed (too many rrsets) in collect ANY"); - foriq->state = FINISHED_STATE; - return; /* integer overflow protection */ - } - dest = regional_alloc(forq->region, sizeof(dest[0])*n); - if(!dest) { - log_err("malloc failed in collect ANY"); - foriq->state = FINISHED_STATE; - return; - } - d = dest; - /* copy AN */ - memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets - * sizeof(dest[0])); - dest += to->rep->an_numrrsets; - memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets - * sizeof(dest[0])); - dest += from->rep->an_numrrsets; - /* copy NS */ - memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets, - to->rep->ns_numrrsets * sizeof(dest[0])); - dest += to->rep->ns_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets, - from->rep->ns_numrrsets * sizeof(dest[0])); - dest += from->rep->ns_numrrsets; - /* copy AR */ - memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets+ - to->rep->ns_numrrsets, - to->rep->ar_numrrsets * sizeof(dest[0])); - dest += to->rep->ar_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+ - from->rep->ns_numrrsets, - from->rep->ar_numrrsets * sizeof(dest[0])); - /* update counts */ - to->rep->rrsets = d; - to->rep->an_numrrsets += from->rep->an_numrrsets; - to->rep->ns_numrrsets += from->rep->ns_numrrsets; - to->rep->ar_numrrsets += from->rep->ar_numrrsets; - to->rep->rrset_count = n; - } - if(from->rep->security < to->rep->security) /* lowest sec */ - to->rep->security = from->rep->security; - if(from->rep->qdcount != 0) /* insert qd if appropriate */ - to->rep->qdcount = from->rep->qdcount; - if(from->rep->ttl < to->rep->ttl) /* use smallest TTL */ - to->rep->ttl = from->rep->ttl; - if(from->rep->prefetch_ttl < to->rep->prefetch_ttl) - to->rep->prefetch_ttl = from->rep->prefetch_ttl; - if(from->rep->serve_expired_ttl < to->rep->serve_expired_ttl) - to->rep->serve_expired_ttl = from->rep->serve_expired_ttl; - } - /* are we done? */ - foriq->num_current_queries --; - if(foriq->num_current_queries == 0) - foriq->state = FINISHED_STATE; -} - -/** - * Collect class ANY responses and make them into one response. This - * state is started and it creates queries for all classes (that have - * root hints). The answers are then collected. - * - * @param qstate: query state. - * @param id: module id. - * @return true if the event needs more immediate processing, false if not. - */ -static int -processCollectClass(struct module_qstate* qstate, int id) -{ - struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; - struct module_qstate* subq; - /* If qchase.qclass == 0 then send out queries for all classes. - * Otherwise, do nothing (wait for all answers to arrive and the - * processClassResponse to put them together, and that moves us - * towards the Finished state when done. */ - if(iq->qchase.qclass == 0) { - uint16_t c = 0; - iq->qchase.qclass = LDNS_RR_CLASS_ANY; - while(iter_get_next_root(qstate->env->hints, - qstate->env->fwds, &c)) { - /* generate query for this class */ - log_nametypeclass(VERB_ALGO, "spawn collect query", - qstate->qinfo.qname, qstate->qinfo.qtype, c); - if(!generate_sub_request(qstate->qinfo.qname, - qstate->qinfo.qname_len, qstate->qinfo.qtype, - c, qstate, id, iq, INIT_REQUEST_STATE, - FINISHED_STATE, &subq, - (int)!(qstate->query_flags&BIT_CD), 0)) { - errinf(qstate, "could not generate class ANY" - " lookup query"); - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } - /* ignore subq, no special init required */ - iq->num_current_queries ++; - if(c == 0xffff) - break; - else c++; - } - /* if no roots are configured at all, return */ - if(iq->num_current_queries == 0) { - verbose(VERB_ALGO, "No root hints or fwds, giving up " - "on qclass ANY"); - return error_response(qstate, id, LDNS_RCODE_REFUSED); - } - /* return false, wait for queries to return */ - } - /* if woke up here because of an answer, wait for more answers */ - return 0; -} - -/** - * This handles the final state for first-tier responses (i.e., responses to - * externally generated queries). - * - * @param qstate: query state. - * @param iq: iterator query state. - * @param id: module id. - * @return true if the event needs more processing, false if not. Since this - * is the final state for an event, it always returns false. - */ -static int -processFinished(struct module_qstate* qstate, struct iter_qstate* iq, - int id) -{ - log_query_info(VERB_QUERY, "finishing processing for", - &qstate->qinfo); - - /* store negative cache element for parent side glue. */ - if(!qstate->no_cache_store && iq->query_for_pside_glue - && !iq->pside_glue) - iter_store_parentside_neg(qstate->env, &qstate->qinfo, - iq->deleg_msg?iq->deleg_msg->rep: - (iq->response?iq->response->rep:NULL)); - if(!iq->response) { - verbose(VERB_ALGO, "No response is set, servfail"); - errinf(qstate, "(no response found at query finish)"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - - /* Make sure that the RA flag is set (since the presence of - * this module means that recursion is available) */ - iq->response->rep->flags |= BIT_RA; - - /* Clear the AA flag */ - /* FIXME: does this action go here or in some other module? */ - iq->response->rep->flags &= ~BIT_AA; - - /* make sure QR flag is on */ - iq->response->rep->flags |= BIT_QR; - - /* explicitly set the EDE string to NULL */ - iq->response->rep->reason_bogus_str = NULL; - - /* we have finished processing this query */ - qstate->ext_state[id] = module_finished; - - /* TODO: we are using a private TTL, trim the response. */ - /* if (mPrivateTTL > 0){IterUtils.setPrivateTTL(resp, mPrivateTTL); } */ - - /* prepend any items we have accumulated */ - if(iq->an_prepend_list || iq->ns_prepend_list) { - if(!iter_prepend(iq, iq->response, qstate->region)) { - log_err("prepend rrsets: out of memory"); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } - /* reset the query name back */ - iq->response->qinfo = qstate->qinfo; - /* the security state depends on the combination */ - iq->response->rep->security = sec_status_unchecked; - /* store message with the finished prepended items, - * but only if we did recursion. The nonrecursion referral - * from cache does not need to be stored in the msg cache. */ - if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) { - iter_dns_store(qstate->env, &qstate->qinfo, - iq->response->rep, 0, qstate->prefetch_leeway, - iq->dp&&iq->dp->has_parent_side_NS, - qstate->region, qstate->query_flags, - qstate->qstarttime); - } - } - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = iq->response; - return 0; -} - -/* - * Return priming query results to interested super querystates. - * - * Sets the delegation point and delegation message (not nonRD queries). - * This is a callback from walk_supers. - * - * @param qstate: query state that finished. - * @param id: module id. - * @param super: the qstate to inform. - */ -void -iter_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) -{ - if(!qstate->is_priming && super->qinfo.qclass == LDNS_RR_CLASS_ANY) - processClassResponse(qstate, id, super); - else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*) - super->minfo[id])->state == DSNS_FIND_STATE) - processDSNSResponse(qstate, id, super); - else if(qstate->return_rcode != LDNS_RCODE_NOERROR) - error_supers(qstate, id, super); - else if(qstate->is_priming) - prime_supers(qstate, id, super); - else processTargetResponse(qstate, id, super); -} - -/** - * Handle iterator state. - * Handle events. This is the real processing loop for events, responsible - * for moving events through the various states. If a processing method - * returns true, then it will be advanced to the next state. If false, then - * processing will stop. - * - * @param qstate: query state. - * @param ie: iterator shared global environment. - * @param iq: iterator query state. - * @param id: module id. - */ -static void -iter_handle(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - int cont = 1; - while(cont) { - verbose(VERB_ALGO, "iter_handle processing q with state %s", - iter_state_to_string(iq->state)); - switch(iq->state) { - case INIT_REQUEST_STATE: - cont = processInitRequest(qstate, iq, ie, id); - break; - case INIT_REQUEST_2_STATE: - cont = processInitRequest2(qstate, iq, id); - break; - case INIT_REQUEST_3_STATE: - cont = processInitRequest3(qstate, iq, id); - break; - case QUERYTARGETS_STATE: - cont = processQueryTargets(qstate, iq, ie, id); - break; - case QUERY_RESP_STATE: - cont = processQueryResponse(qstate, iq, ie, id); - break; - case PRIME_RESP_STATE: - cont = processPrimeResponse(qstate, id); - break; - case COLLECT_CLASS_STATE: - cont = processCollectClass(qstate, id); - break; - case DSNS_FIND_STATE: - cont = processDSNSFind(qstate, iq, id); - break; - case FINISHED_STATE: - cont = processFinished(qstate, iq, id); - break; - default: - log_warn("iterator: invalid state: %d", - iq->state); - cont = 0; - break; - } - } -} - -/** - * This is the primary entry point for processing request events. Note that - * this method should only be used by external modules. - * @param qstate: query state. - * @param ie: iterator shared global environment. - * @param iq: iterator query state. - * @param id: module id. - */ -static void -process_request(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) -{ - /* external requests start in the INIT state, and finish using the - * FINISHED state. */ - iq->state = INIT_REQUEST_STATE; - iq->final_state = FINISHED_STATE; - verbose(VERB_ALGO, "process_request: new external request event"); - iter_handle(qstate, iq, ie, id); -} - -/** process authoritative server reply */ -static void -process_response(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id, struct outbound_entry* outbound, - enum module_ev event) -{ - struct msg_parse* prs; - struct edns_data edns; - sldns_buffer* pkt; - - verbose(VERB_ALGO, "process_response: new external response event"); - iq->response = NULL; - iq->state = QUERY_RESP_STATE; - if(event == module_event_noreply || event == module_event_error) { - if(event == module_event_noreply && iq->timeout_count >= 3 && - qstate->env->cfg->use_caps_bits_for_id && - !iq->caps_fallback && !is_caps_whitelisted(ie, iq)) { - /* start fallback */ - iq->caps_fallback = 1; - iq->caps_server = 0; - iq->caps_reply = NULL; - iq->caps_response = NULL; - iq->caps_minimisation_state = DONOT_MINIMISE_STATE; - iq->state = QUERYTARGETS_STATE; - iq->num_current_queries--; - /* need fresh attempts for the 0x20 fallback, if - * that was the cause for the failure */ - iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); - verbose(VERB_DETAIL, "Capsforid: timeouts, starting fallback"); - goto handle_it; - } - goto handle_it; - } - if( (event != module_event_reply && event != module_event_capsfail) - || !qstate->reply) { - log_err("Bad event combined with response"); - outbound_list_remove(&iq->outlist, outbound); - errinf(qstate, "module iterator received wrong internal event with a response message"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - - /* parse message */ - fill_fail_addr(iq, &qstate->reply->remote_addr, - qstate->reply->remote_addrlen); - prs = (struct msg_parse*)regional_alloc(qstate->env->scratch, - sizeof(struct msg_parse)); - if(!prs) { - log_err("out of memory on incoming message"); - /* like packet got dropped */ - goto handle_it; - } - memset(prs, 0, sizeof(*prs)); - memset(&edns, 0, sizeof(edns)); - pkt = qstate->reply->c->buffer; - sldns_buffer_set_position(pkt, 0); - if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) { - verbose(VERB_ALGO, "parse error on reply packet"); - iq->parse_failures++; - goto handle_it; - } - /* edns is not examined, but removed from message to help cache */ - if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) != - LDNS_RCODE_NOERROR) { - iq->parse_failures++; - goto handle_it; - } - - /* Copy the edns options we may got from the back end */ - if(edns.opt_list_in) { - qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in, - qstate->region); - if(!qstate->edns_opts_back_in) { - log_err("out of memory on incoming message"); - /* like packet got dropped */ - goto handle_it; - } - if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) { - log_err("unable to call edns_back_parsed callback"); - goto handle_it; - } - } - - /* remove CD-bit, we asked for in case we handle validation ourself */ - prs->flags &= ~BIT_CD; - - /* normalize and sanitize: easy to delete items from linked lists */ - if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name, - qstate->env->scratch, qstate->env, ie)) { - /* if 0x20 enabled, start fallback, but we have no message */ - if(event == module_event_capsfail && !iq->caps_fallback) { - iq->caps_fallback = 1; - iq->caps_server = 0; - iq->caps_reply = NULL; - iq->caps_response = NULL; - iq->caps_minimisation_state = DONOT_MINIMISE_STATE; - iq->state = QUERYTARGETS_STATE; - iq->num_current_queries--; - verbose(VERB_DETAIL, "Capsforid: scrub failed, starting fallback with no response"); - } - iq->scrub_failures++; - goto handle_it; - } - - /* allocate response dns_msg in region */ - iq->response = dns_alloc_msg(pkt, prs, qstate->region); - if(!iq->response) - goto handle_it; - log_query_info(VERB_DETAIL, "response for", &qstate->qinfo); - log_name_addr(VERB_DETAIL, "reply from", iq->dp->name, - &qstate->reply->remote_addr, qstate->reply->remote_addrlen); - if(verbosity >= VERB_ALGO) - log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo, - iq->response->rep); - - if(event == module_event_capsfail || iq->caps_fallback) { - if(qstate->env->cfg->qname_minimisation && - iq->minimisation_state != DONOT_MINIMISE_STATE) { - /* Skip QNAME minimisation for next query, since that - * one has to match the current query. */ - iq->minimisation_state = SKIP_MINIMISE_STATE; - } - /* for fallback we care about main answer, not additionals */ - /* removing that makes comparison more likely to succeed */ - caps_strip_reply(iq->response->rep); - - if(iq->caps_fallback && - iq->caps_minimisation_state != iq->minimisation_state) { - /* QNAME minimisation state has changed, restart caps - * fallback. */ - iq->caps_fallback = 0; - } - - if(!iq->caps_fallback) { - /* start fallback */ - iq->caps_fallback = 1; - iq->caps_server = 0; - iq->caps_reply = iq->response->rep; - iq->caps_response = iq->response; - iq->caps_minimisation_state = iq->minimisation_state; - iq->state = QUERYTARGETS_STATE; - iq->num_current_queries--; - verbose(VERB_DETAIL, "Capsforid: starting fallback"); - goto handle_it; - } else { - /* check if reply is the same, otherwise, fail */ - if(!iq->caps_reply) { - iq->caps_reply = iq->response->rep; - iq->caps_response = iq->response; - iq->caps_server = -1; /*become zero at ++, - so that we start the full set of trials */ - } else if(caps_failed_rcode(iq->caps_reply) && - !caps_failed_rcode(iq->response->rep)) { - /* prefer to upgrade to non-SERVFAIL */ - iq->caps_reply = iq->response->rep; - iq->caps_response = iq->response; - } else if(!caps_failed_rcode(iq->caps_reply) && - caps_failed_rcode(iq->response->rep)) { - /* if we have non-SERVFAIL as answer then - * we can ignore SERVFAILs for the equality - * comparison */ - /* no instructions here, skip other else */ - } else if(caps_failed_rcode(iq->caps_reply) && - caps_failed_rcode(iq->response->rep)) { - /* failure is same as other failure in fallbk*/ - /* no instructions here, skip other else */ - } else if(!reply_equal(iq->response->rep, iq->caps_reply, - qstate->env->scratch)) { - verbose(VERB_DETAIL, "Capsforid fallback: " - "getting different replies, failed"); - outbound_list_remove(&iq->outlist, outbound); - errinf(qstate, "0x20 failed, then got different replies in fallback"); - (void)error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - return; - } - /* continue the fallback procedure at next server */ - iq->caps_server++; - iq->state = QUERYTARGETS_STATE; - iq->num_current_queries--; - verbose(VERB_DETAIL, "Capsforid: reply is equal. " - "go to next fallback"); - goto handle_it; - } - } - iq->caps_fallback = 0; /* if we were in fallback, 0x20 is OK now */ - -handle_it: - outbound_list_remove(&iq->outlist, outbound); - iter_handle(qstate, iq, ie, id); -} - -void -iter_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; - verbose(VERB_QUERY, "iterator[module %d] operate: extstate:%s event:%s", - id, strextstate(qstate->ext_state[id]), strmodulevent(event)); - if(iq) log_query_info(VERB_QUERY, "iterator operate: query", - &qstate->qinfo); - if(iq && qstate->qinfo.qname != iq->qchase.qname) - log_query_info(VERB_QUERY, "iterator operate: chased to", - &iq->qchase); - - /* perform iterator state machine */ - if((event == module_event_new || event == module_event_pass) && - iq == NULL) { - if(!iter_new(qstate, id)) { - errinf(qstate, "malloc failure, new iterator module allocation"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - iq = (struct iter_qstate*)qstate->minfo[id]; - process_request(qstate, iq, ie, id); - return; - } - if(iq && event == module_event_pass) { - iter_handle(qstate, iq, ie, id); - return; - } - if(iq && outbound) { - process_response(qstate, iq, ie, id, outbound, event); - return; - } - if(event == module_event_error) { - verbose(VERB_ALGO, "got called with event error, giving up"); - errinf(qstate, "iterator module got the error event"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return; - } - - log_err("bad event for iterator"); - errinf(qstate, "iterator module received wrong event"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); -} - -void -iter_clear(struct module_qstate* qstate, int id) -{ - struct iter_qstate* iq; - if(!qstate) - return; - iq = (struct iter_qstate*)qstate->minfo[id]; - if(iq) { - outbound_list_clear(&iq->outlist); - if(iq->target_count && --iq->target_count[TARGET_COUNT_REF] == 0) { - free(iq->target_count); - if(*iq->nxns_dp) free(*iq->nxns_dp); - free(iq->nxns_dp); - } - iq->num_current_queries = 0; - } - qstate->minfo[id] = NULL; -} - -size_t -iter_get_mem(struct module_env* env, int id) -{ - struct iter_env* ie = (struct iter_env*)env->modinfo[id]; - if(!ie) - return 0; - return sizeof(*ie) + sizeof(int)*((size_t)ie->max_dependency_depth+1) - + donotq_get_mem(ie->donotq) + priv_get_mem(ie->priv); -} - -/** - * The iterator function block - */ -static struct module_func_block iter_block = { - "iterator", - &iter_init, &iter_deinit, &iter_operate, &iter_inform_super, - &iter_clear, &iter_get_mem -}; - -struct module_func_block* -iter_get_funcblock(void) -{ - return &iter_block; -} - -const char* -iter_state_to_string(enum iter_state state) -{ - switch (state) - { - case INIT_REQUEST_STATE : - return "INIT REQUEST STATE"; - case INIT_REQUEST_2_STATE : - return "INIT REQUEST STATE (stage 2)"; - case INIT_REQUEST_3_STATE: - return "INIT REQUEST STATE (stage 3)"; - case QUERYTARGETS_STATE : - return "QUERY TARGETS STATE"; - case PRIME_RESP_STATE : - return "PRIME RESPONSE STATE"; - case COLLECT_CLASS_STATE : - return "COLLECT CLASS STATE"; - case DSNS_FIND_STATE : - return "DSNS FIND STATE"; - case QUERY_RESP_STATE : - return "QUERY RESPONSE STATE"; - case FINISHED_STATE : - return "FINISHED RESPONSE STATE"; - default : - return "UNKNOWN ITER STATE"; - } -} - -int -iter_state_is_responsestate(enum iter_state s) -{ - switch(s) { - case INIT_REQUEST_STATE : - case INIT_REQUEST_2_STATE : - case INIT_REQUEST_3_STATE : - case QUERYTARGETS_STATE : - case COLLECT_CLASS_STATE : - return 0; - default: - break; - } - return 1; -} diff --git a/crates/libunbound-sys/unbound/iterator/iterator.h b/crates/libunbound-sys/unbound/iterator/iterator.h deleted file mode 100644 index fad7f03e..00000000 --- a/crates/libunbound-sys/unbound/iterator/iterator.h +++ /dev/null @@ -1,523 +0,0 @@ -/* - * iterator/iterator.h - iterative resolver DNS query response module - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs recursive iterative DNS query - * processing. - */ - -#ifndef ITERATOR_ITERATOR_H -#define ITERATOR_ITERATOR_H -#include "services/outbound_list.h" -#include "util/data/msgreply.h" -#include "util/module.h" -struct delegpt; -struct iter_hints; -struct iter_forwards; -struct iter_donotq; -struct iter_prep_list; -struct iter_priv; -struct rbtree_type; - -/** max number of targets spawned for a query and its subqueries */ -#define MAX_TARGET_COUNT 64 -/** max number of target lookups per qstate, per delegation point */ -#define MAX_DP_TARGET_COUNT 16 -/** max number of nxdomains allowed for target lookups for a query and - * its subqueries */ -#define MAX_TARGET_NX 5 -/** max number of nxdomains allowed for target lookups for a query and - * its subqueries when fallback has kicked in */ -#define MAX_TARGET_NX_FALLBACK (MAX_TARGET_NX*2) -/** max number of referrals. Makes sure resolver does not run away */ -#define MAX_REFERRAL_COUNT 130 -/** max number of queries for which to perform dnsseclameness detection, - * (rrsigs missing detection) after that, just pick up that response */ -#define DNSSEC_LAME_DETECT_COUNT 4 -/** - * max number of QNAME minimisation iterations. Limits number of queries for - * QNAMEs with a lot of labels. -*/ -#define MAX_MINIMISE_COUNT 10 -/* max number of time-outs for minimised query. Prevents resolving failures - * when the QNAME minimisation QTYPE is blocked. */ -#define MAX_MINIMISE_TIMEOUT_COUNT 3 -/** - * number of labels from QNAME that are always send individually when using - * QNAME minimisation, even when the number of labels of the QNAME is bigger - * than MAX_MINIMISE_COUNT */ -#define MINIMISE_ONE_LAB 4 -#define MINIMISE_MULTIPLE_LABS (MAX_MINIMISE_COUNT - MINIMISE_ONE_LAB) -/** at what query-sent-count to stop target fetch policy */ -#define TARGET_FETCH_STOP 3 -/** how nice is a server without further information, in msec - * Equals rtt initial timeout value. - */ -extern int UNKNOWN_SERVER_NICENESS; -/** maximum timeout before a host is deemed unsuitable, in msec. - * After host_ttl this will be timed out and the host will be tried again. - * Equals RTT_MAX_TIMEOUT, and thus when RTT_MAX_TIMEOUT is overwritten by - * config infra_cache_max_rtt, it will be overwritten as well. */ -extern int USEFUL_SERVER_TOP_TIMEOUT; -/** penalty to validation failed blacklisted IPs - * Equals USEFUL_SERVER_TOP_TIMEOUT*4, and thus when RTT_MAX_TIMEOUT is - * overwritten by config infra_cache_max_rtt, it will be overwritten as well. */ -extern int BLACKLIST_PENALTY; -/** RTT band, within this amount from the best, servers are chosen randomly. - * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a - * fast server, this causes server exploration as a side benefit. msec. */ -#define RTT_BAND 400 - -/** - * Global state for the iterator. - */ -struct iter_env { - /** A flag to indicate whether or not we have an IPv6 route */ - int supports_ipv6; - - /** A flag to indicate whether or not we have an IPv4 route */ - int supports_ipv4; - - /** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */ - int use_nat64; - - /** NAT64 prefix address, cf. dns64_env->prefix_addr */ - struct sockaddr_storage nat64_prefix_addr; - - /** sizeof(sockaddr_in6) */ - socklen_t nat64_prefix_addrlen; - - /** CIDR mask length of NAT64 prefix */ - int nat64_prefix_net; - - /** A set of inetaddrs that should never be queried. */ - struct iter_donotq* donotq; - - /** private address space and private domains */ - struct iter_priv* priv; - - /** whitelist for capsforid names */ - struct rbtree_type* caps_white; - - /** The maximum dependency depth that this resolver will pursue. */ - int max_dependency_depth; - - /** - * The target fetch policy for each dependency level. This is - * described as a simple number (per dependency level): - * negative numbers (usually just -1) mean fetch-all, - * 0 means only fetch on demand, and - * positive numbers mean to fetch at most that many targets. - * array of max_dependency_depth+1 size. - */ - int* target_fetch_policy; - - /** lock on ratelimit counter */ - lock_basic_type queries_ratelimit_lock; - /** number of queries that have been ratelimited */ - size_t num_queries_ratelimited; - - /** number of retries on outgoing queries */ - int outbound_msg_retry; - - /** number of queries_sent */ - int max_sent_count; - - /** max number of query restarts to limit length of CNAME chain */ - int max_query_restarts; -}; - -/** - * QNAME minimisation state - */ -enum minimisation_state { - /** - * (Re)start minimisation. Outgoing QNAME should be set to dp->name. - * State entered on new query or after following referral or CNAME. - */ - INIT_MINIMISE_STATE = 0, - /** - * QNAME minimisation ongoing. Increase QNAME on every iteration. - */ - MINIMISE_STATE, - /** - * Don't increment QNAME this iteration - */ - SKIP_MINIMISE_STATE, - /** - * Send out full QNAME + original QTYPE - */ - DONOT_MINIMISE_STATE, -}; - -/** - * State of the iterator for a query. - */ -enum iter_state { - /** - * Externally generated queries start at this state. Query restarts are - * reset to this state. - */ - INIT_REQUEST_STATE = 0, - - /** - * Root priming events reactivate here, most other events pass - * through this naturally as the 2nd part of the INIT_REQUEST_STATE. - */ - INIT_REQUEST_2_STATE, - - /** - * Stub priming events reactivate here, most other events pass - * through this naturally as the 3rd part of the INIT_REQUEST_STATE. - */ - INIT_REQUEST_3_STATE, - - /** - * Each time a delegation point changes for a given query or a - * query times out and/or wakes up, this state is (re)visited. - * This state is responsible for iterating through a list of - * nameserver targets. - */ - QUERYTARGETS_STATE, - - /** - * Responses to queries start at this state. This state handles - * the decision tree associated with handling responses. - */ - QUERY_RESP_STATE, - - /** Responses to priming queries finish at this state. */ - PRIME_RESP_STATE, - - /** Collecting query class information, for qclass=ANY, when - * it spawns off queries for every class, it returns here. */ - COLLECT_CLASS_STATE, - - /** Find NS record to resolve DS record from, walking to the right - * NS spot until we find it */ - DSNS_FIND_STATE, - - /** Responses that are to be returned upstream end at this state. - * As well as responses to target queries. */ - FINISHED_STATE -}; - -/** - * Shared counters for queries. - */ -enum target_count_variables { - /** Reference count for the shared iter_qstate->target_count. */ - TARGET_COUNT_REF = 0, - /** Number of target queries spawned for the query and subqueries. */ - TARGET_COUNT_QUERIES, - /** Number of nxdomain responses encountered. */ - TARGET_COUNT_NX, - - /** This should stay last here, it is used for the allocation */ - TARGET_COUNT_MAX, -}; - -/** - * Per query state for the iterator module. - */ -struct iter_qstate { - /** - * State of the iterator module. - * This is the state that event is in or should sent to -- all - * requests should start with the INIT_REQUEST_STATE. All - * responses should start with QUERY_RESP_STATE. Subsequent - * processing of the event will change this state. - */ - enum iter_state state; - - /** - * Final state for the iterator module. - * This is the state that responses should be routed to once the - * response is final. For externally initiated queries, this - * will be FINISHED_STATE, locally initiated queries will have - * different final states. - */ - enum iter_state final_state; - - /** - * The depth of this query, this means the depth of recursion. - * This address is needed for another query, which is an address - * needed for another query, etc. Original client query has depth 0. - */ - int depth; - - /** - * The response - */ - struct dns_msg* response; - - /** - * This is a list of RRsets that must be prepended to the - * ANSWER section of a response before being sent upstream. - */ - struct iter_prep_list* an_prepend_list; - /** Last element of the prepend list */ - struct iter_prep_list* an_prepend_last; - - /** - * This is the list of RRsets that must be prepended to the - * AUTHORITY section of the response before being sent upstream. - */ - struct iter_prep_list* ns_prepend_list; - /** Last element of the authority prepend list */ - struct iter_prep_list* ns_prepend_last; - - /** query name used for chasing the results. Initially the same as - * the state qinfo, but after CNAMEs this will be different. - * The query info used to elicit the results needed. */ - struct query_info qchase; - /** query flags to use when chasing the answer (i.e. RD flag) */ - uint16_t chase_flags; - /** true if we set RD bit because of last resort recursion lame query*/ - int chase_to_rd; - - /** - * This is the current delegation point for an in-progress query. This - * object retains state as to which delegation targets need to be - * (sub)queried for vs which ones have already been visited. - */ - struct delegpt* dp; - - /** state for 0x20 fallback when capsfail happens, 0 not a fallback */ - int caps_fallback; - /** state for capsfail: current server number to try */ - size_t caps_server; - /** state for capsfail: stored query for comparisons. Can be NULL if - * no response had been seen prior to starting the fallback. */ - struct reply_info* caps_reply; - struct dns_msg* caps_response; - - /** Current delegation message - returned for non-RD queries */ - struct dns_msg* deleg_msg; - - /** number of outstanding target sub queries */ - int num_target_queries; - - /** outstanding direct queries */ - int num_current_queries; - - /** the number of times this query has been restarted. */ - int query_restart_count; - - /** the number of times this query has followed a referral. */ - int referral_count; - - /** number of queries fired off */ - int sent_count; - - /** malloced-array shared with this query and its subqueries. It keeps - * track of the defined enum target_count_variables counters. */ - int* target_count; - - /** number of target lookups per delegation point. Reset to 0 after - * receiving referral answer. Not shared with subqueries. */ - int dp_target_count; - - /** Delegation point that triggered the NXNS fallback; shared with - * this query and its subqueries, count-referenced by the reference - * counter in target_count. - * This also marks the fallback activation. */ - uint8_t** nxns_dp; - - /** if true, already tested for ratelimiting and passed the test */ - int ratelimit_ok; - - /** - * The query must store NS records from referrals as parentside RRs - * Enabled once it hits resolution problems, to throttle retries. - * If enabled it is the pointer to the old delegation point with - * the old retry counts for bad-nameserver-addresses. - */ - struct delegpt* store_parent_NS; - - /** - * The query is for parent-side glue(A or AAAA) for a nameserver. - * If the item is seen as glue in a referral, and pside_glue is NULL, - * then it is stored in pside_glue for later. - * If it was never seen, at the end, then a negative caching element - * must be created. - * The (data or negative) RR cache element then throttles retries. - */ - int query_for_pside_glue; - /** the parent-side-glue element (NULL if none, its first match) */ - struct ub_packed_rrset_key* pside_glue; - - /** If nonNULL we are walking upwards from DS query to find NS */ - uint8_t* dsns_point; - /** length of the dname in dsns_point */ - size_t dsns_point_len; - - /** - * expected dnssec information for this iteration step. - * If dnssec rrsigs are expected and not given, the server is marked - * lame (dnssec-lame). - */ - int dnssec_expected; - - /** - * We are expecting dnssec information, but we also know the server - * is DNSSEC lame. The response need not be marked dnssec-lame again. - */ - int dnssec_lame_query; - - /** - * This is flag that, if true, means that this event is - * waiting for a stub priming query. - */ - int wait_priming_stub; - - /** - * This is a flag that, if true, means that this query is - * for (re)fetching glue from a zone. Since the address should - * have been glue, query again to the servers that should have - * been returning it as glue. - * The delegation point must be set to the one that should *not* - * be used when creating the state. A higher one will be attempted. - */ - int refetch_glue; - - /** list of pending queries to authoritative servers. */ - struct outbound_list outlist; - - /** QNAME minimisation state, RFC9156 */ - enum minimisation_state minimisation_state; - - /** State for capsfail: QNAME minimisation state for comparisons. */ - enum minimisation_state caps_minimisation_state; - - /** - * The query info that is sent upstream. Will be a subset of qchase - * when qname minimisation is enabled. - */ - struct query_info qinfo_out; - - /** - * Count number of QNAME minimisation iterations. Used to limit number of - * outgoing queries when QNAME minimisation is enabled. - */ - int minimise_count; - - /** - * Count number of time-outs. Used to prevent resolving failures when - * the QNAME minimisation QTYPE is blocked. Used to determine if - * capsforid fallback should be started.*/ - int timeout_count; - - /** True if the current response is from auth_zone */ - int auth_zone_response; - /** True if the auth_zones should not be consulted for the query */ - int auth_zone_avoid; - /** true if there have been scrubbing failures of reply packets */ - int scrub_failures; - /** true if there have been parse failures of reply packets */ - int parse_failures; - /** a failure printout address for last received answer */ - union { - struct in_addr in; -#ifdef AF_INET6 - struct in6_addr in6; -#endif - } fail_addr; - /** which fail_addr, 0 is nothing, 4 or 6 */ - int fail_addr_type; -}; - -/** - * List of prepend items - */ -struct iter_prep_list { - /** next in list */ - struct iter_prep_list* next; - /** rrset */ - struct ub_packed_rrset_key* rrset; -}; - -/** - * Get the iterator function block. - * @return: function block with function pointers to iterator methods. - */ -struct module_func_block* iter_get_funcblock(void); - -/** - * Get iterator state as a string - * @param state: to convert - * @return constant string that is printable. - */ -const char* iter_state_to_string(enum iter_state state); - -/** - * See if iterator state is a response state - * @param s: to inspect - * @return true if response state. - */ -int iter_state_is_responsestate(enum iter_state s); - -/** iterator init */ -int iter_init(struct module_env* env, int id); - -/** iterator deinit */ -void iter_deinit(struct module_env* env, int id); - -/** iterator operate on a query */ -void iter_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound); - -/** - * Return priming query results to interested super querystates. - * - * Sets the delegation point and delegation message (not nonRD queries). - * This is a callback from walk_supers. - * - * @param qstate: query state that finished. - * @param id: module id. - * @param super: the qstate to inform. - */ -void iter_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** iterator cleanup query state */ -void iter_clear(struct module_qstate* qstate, int id); - -/** iterator alloc size routine */ -size_t iter_get_mem(struct module_env* env, int id); - -#endif /* ITERATOR_ITERATOR_H */ diff --git a/crates/libunbound-sys/unbound/libunbound/context.c b/crates/libunbound-sys/unbound/libunbound/context.c deleted file mode 100644 index f7c0a2cd..00000000 --- a/crates/libunbound-sys/unbound/libunbound/context.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * libunbound/context.c - validating context for unbound internal use - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the validator context structure. - */ -#include "config.h" -#include "libunbound/context.h" -#include "util/module.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "services/modstack.h" -#include "services/localzone.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "services/authzone.h" -#include "services/listen_dnsport.h" -#include "util/data/msgreply.h" -#include "util/storage/slabhash.h" -#include "util/edns.h" -#include "sldns/sbuffer.h" - -int -context_finalize(struct ub_ctx* ctx) -{ - int is_rpz = 0; - struct config_file* cfg = ctx->env->cfg; - verbosity = cfg->verbosity; - if(ctx_logfile_overridden && !ctx->logfile_override) { - log_file(NULL); /* clear that override */ - ctx_logfile_overridden = 0; - } - if(ctx->logfile_override) { - ctx_logfile_overridden = 1; - log_file(ctx->log_out); - } else { - log_init(cfg->logfile, cfg->use_syslog, NULL); - } - ctx->pipe_pid = getpid(); - cfg_apply_local_port_policy(cfg, 65536); - config_apply(cfg); - if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) - return UB_INITFAIL; - listen_setup_locks(); - log_edns_known_options(VERB_ALGO, ctx->env); - ctx->local_zones = local_zones_create(); - if(!ctx->local_zones) - return UB_NOMEM; - if(!local_zones_apply_cfg(ctx->local_zones, cfg)) - return UB_INITFAIL; - if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz, - ctx->env, &ctx->mods)) - return UB_INITFAIL; - if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg)) - return UB_INITFAIL; - if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size, - cfg->msg_cache_slabs)) { - slabhash_delete(ctx->env->msg_cache); - ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, - HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, - msgreply_sizefunc, query_info_compare, - query_entry_delete, reply_info_delete, NULL); - if(!ctx->env->msg_cache) - return UB_NOMEM; - } - ctx->env->rrset_cache = rrset_cache_adjust(ctx->env->rrset_cache, - ctx->env->cfg, ctx->env->alloc); - if(!ctx->env->rrset_cache) - return UB_NOMEM; - ctx->env->infra_cache = infra_adjust(ctx->env->infra_cache, cfg); - if(!ctx->env->infra_cache) - return UB_NOMEM; - ctx->finalized = 1; - return UB_NOERROR; -} - -int context_query_cmp(const void* a, const void* b) -{ - if( *(int*)a < *(int*)b ) - return -1; - if( *(int*)a > *(int*)b ) - return 1; - return 0; -} - -void -context_query_delete(struct ctx_query* q) -{ - if(!q) return; - ub_resolve_free(q->res); - free(q->msg); - free(q); -} - -/** How many times to try to find an unused query-id-number for async */ -#define NUM_ID_TRIES 100000 -/** find next useful id number of 0 on error */ -static int -find_id(struct ub_ctx* ctx, int* id) -{ - size_t tries = 0; - ctx->next_querynum++; - while(rbtree_search(&ctx->queries, &ctx->next_querynum)) { - ctx->next_querynum++; /* numerical wraparound is fine */ - if(tries++ > NUM_ID_TRIES) - return 0; - } - *id = ctx->next_querynum; - return 1; -} - -struct ctx_query* -context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, - ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg) -{ - struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); - if(!q) return NULL; - lock_basic_lock(&ctx->cfglock); - if(!find_id(ctx, &q->querynum)) { - lock_basic_unlock(&ctx->cfglock); - free(q); - return NULL; - } - lock_basic_unlock(&ctx->cfglock); - q->node.key = &q->querynum; - q->async = (cb != NULL || cb_event != NULL); - q->cb = cb; - q->cb_event = cb_event; - q->cb_arg = cbarg; - q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); - if(!q->res) { - free(q); - return NULL; - } - q->res->qname = strdup(name); - if(!q->res->qname) { - free(q->res); - free(q); - return NULL; - } - q->res->qtype = rrtype; - q->res->qclass = rrclass; - - /* add to query list */ - lock_basic_lock(&ctx->cfglock); - if(q->async) - ctx->num_async ++; - (void)rbtree_insert(&ctx->queries, &q->node); - lock_basic_unlock(&ctx->cfglock); - return q; -} - -struct alloc_cache* -context_obtain_alloc(struct ub_ctx* ctx, int locking) -{ - struct alloc_cache* a; - int tnum = 0; - if(locking) { - lock_basic_lock(&ctx->cfglock); - } - a = ctx->alloc_list; - if(a) - ctx->alloc_list = a->super; /* snip off list */ - else tnum = ctx->thr_next_num++; - if(locking) { - lock_basic_unlock(&ctx->cfglock); - } - if(a) { - a->super = &ctx->superalloc; - return a; - } - a = (struct alloc_cache*)calloc(1, sizeof(*a)); - if(!a) - return NULL; - alloc_init(a, &ctx->superalloc, tnum); - return a; -} - -void -context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, - int locking) -{ - if(!ctx || !alloc) - return; - if(locking) { - lock_basic_lock(&ctx->cfglock); - } - alloc->super = ctx->alloc_list; - ctx->alloc_list = alloc; - if(locking) { - lock_basic_unlock(&ctx->cfglock); - } -} - -uint8_t* -context_serialize_new_query(struct ctx_query* q, uint32_t* len) -{ - /* format for new query is - * o uint32 cmd - * o uint32 id - * o uint32 type - * o uint32 class - * o rest queryname (string) - */ - uint8_t* p; - size_t slen = strlen(q->res->qname) + 1/*end of string*/; - *len = sizeof(uint32_t)*4 + slen; - p = (uint8_t*)malloc(*len); - if(!p) return NULL; - sldns_write_uint32(p, UB_LIBCMD_NEWQUERY); - sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); - sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype); - sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass); - memmove(p+4*sizeof(uint32_t), q->res->qname, slen); - return p; -} - -struct ctx_query* -context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) -{ - struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); - if(!q) return NULL; - if(len < 4*sizeof(uint32_t)+1) { - free(q); - return NULL; - } - log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); - q->querynum = (int)sldns_read_uint32(p+sizeof(uint32_t)); - q->node.key = &q->querynum; - q->async = 1; - q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); - if(!q->res) { - free(q); - return NULL; - } - q->res->qtype = (int)sldns_read_uint32(p+2*sizeof(uint32_t)); - q->res->qclass = (int)sldns_read_uint32(p+3*sizeof(uint32_t)); - q->res->qname = strdup((char*)(p+4*sizeof(uint32_t))); - if(!q->res->qname) { - free(q->res); - free(q); - return NULL; - } - - /** add to query list */ - ctx->num_async++; - (void)rbtree_insert(&ctx->queries, &q->node); - return q; -} - -struct ctx_query* -context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) -{ - struct ctx_query* q; - int querynum; - if(len < 4*sizeof(uint32_t)+1) { - return NULL; - } - log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); - querynum = (int)sldns_read_uint32(p+sizeof(uint32_t)); - q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum); - if(!q) { - return NULL; - } - log_assert(q->async); - return q; -} - -uint8_t* -context_serialize_answer(struct ctx_query* q, int err, sldns_buffer* pkt, - uint32_t* len) -{ - /* answer format - * o uint32 cmd - * o uint32 id - * o uint32 error_code - * o uint32 msg_security - * o uint32 was_ratelimited - * o uint32 length of why_bogus string (+1 for eos); 0 absent. - * o why_bogus_string - * o the remainder is the answer msg from resolver lookup. - * remainder can be length 0. - */ - size_t size_of_uint32s = 6 * sizeof(uint32_t); - size_t pkt_len = pkt?sldns_buffer_remaining(pkt):0; - size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0; - uint8_t* p; - *len = size_of_uint32s + pkt_len + wlen; - p = (uint8_t*)malloc(*len); - if(!p) return NULL; - sldns_write_uint32(p, UB_LIBCMD_ANSWER); - sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); - sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err); - sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security); - sldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)q->res->was_ratelimited); - sldns_write_uint32(p+5*sizeof(uint32_t), (uint32_t)wlen); - if(wlen > 0) - memmove(p+size_of_uint32s, q->res->why_bogus, wlen); - if(pkt_len > 0) - memmove(p+size_of_uint32s+wlen, - sldns_buffer_begin(pkt), pkt_len); - return p; -} - -struct ctx_query* -context_deserialize_answer(struct ub_ctx* ctx, - uint8_t* p, uint32_t len, int* err) -{ - size_t size_of_uint32s = 6 * sizeof(uint32_t); - struct ctx_query* q = NULL ; - int id; - size_t wlen; - if(len < size_of_uint32s) return NULL; - log_assert( sldns_read_uint32(p) == UB_LIBCMD_ANSWER); - id = (int)sldns_read_uint32(p+sizeof(uint32_t)); - q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); - if(!q) return NULL; - *err = (int)sldns_read_uint32(p+2*sizeof(uint32_t)); - q->msg_security = sldns_read_uint32(p+3*sizeof(uint32_t)); - q->res->was_ratelimited = (int)sldns_read_uint32(p+4*sizeof(uint32_t)); - wlen = (size_t)sldns_read_uint32(p+5*sizeof(uint32_t)); - if(len > size_of_uint32s && wlen > 0) { - if(len >= size_of_uint32s+wlen) - q->res->why_bogus = (char*)memdup( - p+size_of_uint32s, wlen); - if(!q->res->why_bogus) { - /* pass malloc failure to the user callback */ - q->msg_len = 0; - *err = UB_NOMEM; - return q; - } - q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */ - } - if(len > size_of_uint32s+wlen) { - q->msg_len = len - size_of_uint32s - wlen; - q->msg = (uint8_t*)memdup(p+size_of_uint32s+wlen, - q->msg_len); - if(!q->msg) { - /* pass malloc failure to the user callback */ - q->msg_len = 0; - *err = UB_NOMEM; - return q; - } - } - return q; -} - -uint8_t* -context_serialize_cancel(struct ctx_query* q, uint32_t* len) -{ - /* format of cancel: - * o uint32 cmd - * o uint32 async-id */ - uint8_t* p = (uint8_t*)reallocarray(NULL, sizeof(uint32_t), 2); - if(!p) return NULL; - *len = 2*sizeof(uint32_t); - sldns_write_uint32(p, UB_LIBCMD_CANCEL); - sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); - return p; -} - -struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, - uint8_t* p, uint32_t len) -{ - struct ctx_query* q; - int id; - if(len != 2*sizeof(uint32_t)) return NULL; - log_assert( sldns_read_uint32(p) == UB_LIBCMD_CANCEL); - id = (int)sldns_read_uint32(p+sizeof(uint32_t)); - q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); - return q; -} - -uint8_t* -context_serialize_quit(uint32_t* len) -{ - uint32_t* p = (uint32_t*)malloc(sizeof(uint32_t)); - if(!p) - return NULL; - *len = sizeof(uint32_t); - sldns_write_uint32(p, UB_LIBCMD_QUIT); - return (uint8_t*)p; -} - -enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len) -{ - uint32_t v; - if((size_t)len < sizeof(v)) - return UB_LIBCMD_QUIT; - v = sldns_read_uint32(p); - return v; -} diff --git a/crates/libunbound-sys/unbound/libunbound/context.h b/crates/libunbound-sys/unbound/libunbound/context.h deleted file mode 100644 index c0fc80e5..00000000 --- a/crates/libunbound-sys/unbound/libunbound/context.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * libunbound/context.h - validating context for unbound internal use - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the validator context structure. - */ -#ifndef LIBUNBOUND_CONTEXT_H -#define LIBUNBOUND_CONTEXT_H -#include "util/locks.h" -#include "util/alloc.h" -#include "util/rbtree.h" -#include "services/modstack.h" -#include "libunbound/unbound.h" -#include "libunbound/unbound-event.h" -#include "util/data/packed_rrset.h" -struct libworker; -struct tube; -struct sldns_buffer; -struct ub_event_base; - -/** store that the logfile has a debug override */ -extern int ctx_logfile_overridden; - -/** - * The context structure - * - * Contains two pipes for async service - * qq : write queries to the async service pid/tid. - * rr : read results from the async service pid/tid. - */ -struct ub_ctx { - /* --- pipes --- */ - /** mutex on query write pipe */ - lock_basic_type qqpipe_lock; - /** the query write pipe */ - struct tube* qq_pipe; - /** mutex on result read pipe */ - lock_basic_type rrpipe_lock; - /** the result read pipe */ - struct tube* rr_pipe; - - /* --- shared data --- */ - /** mutex for access to env.cfg, finalized and dothread */ - lock_basic_type cfglock; - /** - * The context has been finalized - * This is after config when the first resolve is done. - * The modules are inited (module-init()) and shared caches created. - */ - int finalized; - - /** is bg worker created yet ? */ - int created_bg; - /** pid of bg worker process */ - pid_t bg_pid; - /** tid of bg worker thread */ - ub_thread_type bg_tid; - /** pid when pipes are created. This was the process when the - * setup was called. Helps with clean up, so we can tell after a fork - * which side of the fork the delete is on. */ - pid_t pipe_pid; - /** when threaded, the worker that exists in the created thread. */ - struct libworker* thread_worker; - - /** do threading (instead of forking) for async resolution */ - int dothread; - /** next thread number for new threads */ - int thr_next_num; - /** if logfile is overridden */ - int logfile_override; - /** what logfile to use instead */ - FILE* log_out; - /** - * List of alloc-cache-id points per threadnum for notinuse threads. - * Simply the entire struct alloc_cache with the 'super' member used - * to link a simply linked list. Reset super member to the superalloc - * before use. - */ - struct alloc_cache* alloc_list; - - /** shared caches, and so on */ - struct alloc_cache superalloc; - /** module env master value */ - struct module_env* env; - /** module stack */ - struct module_stack mods; - /** local authority zones */ - struct local_zones* local_zones; - /** random state used to seed new random state structures */ - struct ub_randstate* seed_rnd; - - /** event base for event oriented interface */ - struct ub_event_base* event_base; - /** true if the event_base is a pluggable base that is malloced - * with a user event base inside, if so, clean up the pluggable alloc*/ - int event_base_malloced; - /** libworker for event based interface */ - struct libworker* event_worker; - - /** next query number (to try) to use */ - int next_querynum; - /** number of async queries outstanding */ - size_t num_async; - /** - * Tree of outstanding queries. Indexed by querynum - * Used when results come in for async to lookup. - * Used when cancel is done for lookup (and delete). - * Used to see if querynum is free for use. - * Content of type ctx_query. - */ - rbtree_type queries; -}; - -/** - * The queries outstanding for the libunbound resolver. - * These are outstanding for async resolution. - * But also, outstanding for sync resolution by one of the threads that - * has joined the threadpool. - */ -struct ctx_query { - /** node in rbtree, must be first entry, key is ptr to the querynum */ - struct rbnode_type node; - /** query id number, key for node */ - int querynum; - /** was this an async query? */ - int async; - /** was this query cancelled (for bg worker) */ - int cancelled; - - /** for async query, the callback function of type ub_callback_type */ - ub_callback_type cb; - /** for event callbacks the type is ub_event_callback_type */ - ub_event_callback_type cb_event; - /** for async query, the callback user arg */ - void* cb_arg; - - /** answer message, result from resolver lookup. */ - uint8_t* msg; - /** resulting message length. */ - size_t msg_len; - /** validation status on security */ - enum sec_status msg_security; - /** store libworker that is handling this query */ - struct libworker* w; - - /** result structure, also contains original query, type, class. - * malloced ptr ready to hand to the client. */ - struct ub_result* res; -}; - -/** - * Command codes for libunbound pipe. - * - * Serialization looks like this: - * o length (of remainder) uint32. - * o uint32 command code. - * o per command format. - */ -enum ub_ctx_cmd { - /** QUIT */ - UB_LIBCMD_QUIT = 0, - /** New query, sent to bg worker */ - UB_LIBCMD_NEWQUERY, - /** Cancel query, sent to bg worker */ - UB_LIBCMD_CANCEL, - /** Query result, originates from bg worker */ - UB_LIBCMD_ANSWER -}; - -/** - * finalize a context. - * @param ctx: context to finalize. creates shared data. - * @return 0 if OK, or errcode. - */ -int context_finalize(struct ub_ctx* ctx); - -/** compare two ctx_query elements */ -int context_query_cmp(const void* a, const void* b); - -/** - * delete context query - * @param q: query to delete, including message packet and prealloc result - */ -void context_query_delete(struct ctx_query* q); - -/** - * Create new query in context, add to querynum list. - * @param ctx: context - * @param name: query name - * @param rrtype: type - * @param rrclass: class - * @param cb: callback for async, or NULL for sync. - * @param cb_event: event callback for async, or NULL for sync. - * @param cbarg: user arg for async queries. - * @return new ctx_query or NULL for malloc failure. - */ -struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, ub_callback_type cb, ub_event_callback_type cb_event, - void* cbarg); - -/** - * Get a new alloc. Creates a new one or uses a cached one. - * @param ctx: context - * @param locking: if true, cfglock is locked while getting alloc. - * @return an alloc, or NULL on mem error. - */ -struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking); - -/** - * Release an alloc. Puts it into the cache. - * @param ctx: context - * @param locking: if true, cfglock is locked while releasing alloc. - * @param alloc: alloc to relinquish. - */ -void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, - int locking); - -/** - * Serialize a context query that questions data. - * This serializes the query name, type, ... - * As well as command code 'new_query'. - * @param q: context query - * @param len: the length of the allocation is returned. - * @return: an alloc, or NULL on mem error. - */ -uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len); - -/** - * Serialize a context_query result to hand back to user. - * This serializes the query name, type, ..., and result. - * As well as command code 'answer'. - * @param q: context query - * @param err: error code to pass to client. - * @param pkt: the packet to add, can be NULL. - * @param len: the length of the allocation is returned. - * @return: an alloc, or NULL on mem error. - */ -uint8_t* context_serialize_answer(struct ctx_query* q, int err, - struct sldns_buffer* pkt, uint32_t* len); - -/** - * Serialize a query cancellation. Serializes query async id - * as well as command code 'cancel' - * @param q: context query - * @param len: the length of the allocation is returned. - * @return: an alloc, or NULL on mem error. - */ -uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len); - -/** - * Serialize a 'quit' command. - * @param len: the length of the allocation is returned. - * @return: an alloc, or NULL on mem error. - */ -uint8_t* context_serialize_quit(uint32_t* len); - -/** - * Obtain command code from serialized buffer - * @param p: buffer serialized. - * @param len: length of buffer. - * @return command code or QUIT on error. - */ -enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len); - -/** - * Lookup query from new_query buffer. - * @param ctx: context - * @param p: buffer serialized. - * @param len: length of buffer. - * @return looked up ctx_query or NULL for malloc failure. - */ -struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx, - uint8_t* p, uint32_t len); - -/** - * Deserialize a new_query buffer. - * @param ctx: context - * @param p: buffer serialized. - * @param len: length of buffer. - * @return new ctx_query or NULL for malloc failure. - */ -struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx, - uint8_t* p, uint32_t len); - -/** - * Deserialize an answer buffer. - * @param ctx: context - * @param p: buffer serialized. - * @param len: length of buffer. - * @param err: error code to be returned to client is passed. - * @return ctx_query with answer added or NULL for malloc failure. - */ -struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, - uint8_t* p, uint32_t len, int* err); - -/** - * Deserialize a cancel buffer. - * @param ctx: context - * @param p: buffer serialized. - * @param len: length of buffer. - * @return ctx_query to cancel or NULL for failure. - */ -struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, - uint8_t* p, uint32_t len); - -#endif /* LIBUNBOUND_CONTEXT_H */ diff --git a/crates/libunbound-sys/unbound/libunbound/libunbound.c b/crates/libunbound-sys/unbound/libunbound/libunbound.c deleted file mode 100644 index 80a82bb4..00000000 --- a/crates/libunbound-sys/unbound/libunbound/libunbound.c +++ /dev/null @@ -1,1465 +0,0 @@ -/* - * unbound.c - unbound validating resolver public API implementation - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to resolve DNS queries and - * validate the answers. Synchronously and asynchronously. - * - */ - -/* include the public api first, it should be able to stand alone */ -#include "libunbound/unbound.h" -#include "libunbound/unbound-event.h" -#include "config.h" -#include -#include "libunbound/context.h" -#include "libunbound/libworker.h" -#include "util/locks.h" -#include "util/config_file.h" -#include "util/alloc.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/random.h" -#include "util/net_help.h" -#include "util/tube.h" -#include "util/ub_event.h" -#include "util/edns.h" -#include "services/modstack.h" -#include "services/localzone.h" -#include "services/cache/infra.h" -#include "services/cache/rrset.h" -#include "services/authzone.h" -#include "services/listen_dnsport.h" -#include "sldns/sbuffer.h" -#ifdef HAVE_PTHREAD -#include -#endif -#ifdef HAVE_SYS_WAIT_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif - -#if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H) -#include -#include -#endif /* UB_ON_WINDOWS */ - -/** store that the logfile has a debug override */ -int ctx_logfile_overridden = 0; - -/** create context functionality, but no pipes */ -static struct ub_ctx* ub_ctx_create_nopipe(void) -{ - struct ub_ctx* ctx; -#ifdef USE_WINSOCK - int r; - WSADATA wsa_data; -#endif - - checklock_start(); - if(!ctx_logfile_overridden) - log_init(NULL, 0, NULL); /* logs to stderr */ - log_ident_set("libunbound"); -#ifdef USE_WINSOCK - if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { - log_err("could not init winsock. WSAStartup: %s", - wsa_strerror(r)); - return NULL; - } -#endif - verbosity = NO_VERBOSE; /* errors only */ - checklock_start(); - ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx)); - if(!ctx) { - errno = ENOMEM; - return NULL; - } - alloc_init(&ctx->superalloc, NULL, 0); - if(!(ctx->seed_rnd = ub_initstate(NULL))) { - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - lock_basic_init(&ctx->qqpipe_lock); - lock_basic_init(&ctx->rrpipe_lock); - lock_basic_init(&ctx->cfglock); - ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); - if(!ctx->env) { - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - ctx->env->cfg = config_create_forlib(); - if(!ctx->env->cfg) { - free(ctx->env); - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - /* init edns_known_options */ - if(!edns_known_options_init(ctx->env)) { - config_delete(ctx->env->cfg); - free(ctx->env); - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - ctx->env->auth_zones = auth_zones_create(); - if(!ctx->env->auth_zones) { - edns_known_options_delete(ctx->env); - config_delete(ctx->env->cfg); - free(ctx->env); - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - ctx->env->edns_strings = edns_strings_create(); - if(!ctx->env->edns_strings) { - auth_zones_delete(ctx->env->auth_zones); - edns_known_options_delete(ctx->env); - config_delete(ctx->env->cfg); - free(ctx->env); - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = ENOMEM; - return NULL; - } - - ctx->env->alloc = &ctx->superalloc; - ctx->env->worker = NULL; - ctx->env->need_to_validate = 0; - modstack_init(&ctx->mods); - rbtree_init(&ctx->queries, &context_query_cmp); - return ctx; -} - -struct ub_ctx* -ub_ctx_create(void) -{ - struct ub_ctx* ctx = ub_ctx_create_nopipe(); - if(!ctx) - return NULL; - if((ctx->qq_pipe = tube_create()) == NULL) { - int e = errno; - ub_randfree(ctx->seed_rnd); - config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); - listen_desetup_locks(); - edns_known_options_delete(ctx->env); - edns_strings_delete(ctx->env->edns_strings); - free(ctx->env); - free(ctx); - errno = e; - return NULL; - } - if((ctx->rr_pipe = tube_create()) == NULL) { - int e = errno; - tube_delete(ctx->qq_pipe); - ub_randfree(ctx->seed_rnd); - config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); - listen_desetup_locks(); - edns_known_options_delete(ctx->env); - edns_strings_delete(ctx->env->edns_strings); - free(ctx->env); - free(ctx); - errno = e; - return NULL; - } - return ctx; -} - -struct ub_ctx* -ub_ctx_create_ub_event(struct ub_event_base* ueb) -{ - struct ub_ctx* ctx = ub_ctx_create_nopipe(); - if(!ctx) - return NULL; - /* no pipes, but we have the locks to make sure everything works */ - ctx->created_bg = 0; - ctx->dothread = 1; /* the processing is in the same process, - makes ub_cancel and ub_ctx_delete do the right thing */ - ctx->event_base = ueb; - return ctx; -} - -struct ub_ctx* -ub_ctx_create_event(struct event_base* eb) -{ - struct ub_ctx* ctx = ub_ctx_create_nopipe(); - if(!ctx) - return NULL; - /* no pipes, but we have the locks to make sure everything works */ - ctx->created_bg = 0; - ctx->dothread = 1; /* the processing is in the same process, - makes ub_cancel and ub_ctx_delete do the right thing */ - ctx->event_base = ub_libevent_event_base(eb); - if (!ctx->event_base) { - ub_ctx_delete(ctx); - return NULL; - } - ctx->event_base_malloced = 1; - return ctx; -} - -/** delete q */ -static void -delq(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct ctx_query* q = (struct ctx_query*)n; - context_query_delete(q); -} - -/** stop the bg thread */ -static void ub_stop_bg(struct ub_ctx* ctx) -{ - /* stop the bg thread */ - lock_basic_lock(&ctx->cfglock); - if(ctx->created_bg) { - uint8_t* msg; - uint32_t len; - uint32_t cmd = UB_LIBCMD_QUIT; - lock_basic_unlock(&ctx->cfglock); - lock_basic_lock(&ctx->qqpipe_lock); - (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, - (uint32_t)sizeof(cmd), 0); - lock_basic_unlock(&ctx->qqpipe_lock); - lock_basic_lock(&ctx->rrpipe_lock); - while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) { - /* discard all results except a quit confirm */ - if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) { - free(msg); - break; - } - free(msg); - } - lock_basic_unlock(&ctx->rrpipe_lock); - - /* if bg worker is a thread, wait for it to exit, so that all - * resources are really gone. */ - lock_basic_lock(&ctx->cfglock); - if(ctx->dothread) { - lock_basic_unlock(&ctx->cfglock); - ub_thread_join(ctx->bg_tid); - } else { - lock_basic_unlock(&ctx->cfglock); -#ifndef UB_ON_WINDOWS - if(waitpid(ctx->bg_pid, NULL, 0) == -1) { - if(verbosity > 2) - log_err("waitpid: %s", strerror(errno)); - } -#endif - } - } - else { - lock_basic_unlock(&ctx->cfglock); - } -} - -void -ub_ctx_delete(struct ub_ctx* ctx) -{ - struct alloc_cache* a, *na; - int do_stop = 1; - if(!ctx) return; - - /* if the delete is called but it has forked, and before the fork - * the context was finalized, then the bg worker is not stopped - * from here. There is one worker, but two contexts that refer to - * it and only one should clean up, the one with getpid == pipe_pid.*/ - if(ctx->created_bg && ctx->pipe_pid != getpid()) { - do_stop = 0; -#ifndef USE_WINSOCK - /* Stop events from getting deregistered, if the backend is - * epoll, the epoll fd is the same as the other process. - * That process should deregister them. */ - if(ctx->qq_pipe->listen_com) - ctx->qq_pipe->listen_com->event_added = 0; - if(ctx->qq_pipe->res_com) - ctx->qq_pipe->res_com->event_added = 0; - if(ctx->rr_pipe->listen_com) - ctx->rr_pipe->listen_com->event_added = 0; - if(ctx->rr_pipe->res_com) - ctx->rr_pipe->res_com->event_added = 0; -#endif - } - /* see if bg thread is created and if threads have been killed */ - /* no locks, because those may be held by terminated threads */ - /* for processes the read pipe is closed and we see that on read */ -#ifdef HAVE_PTHREAD - if(ctx->created_bg && ctx->dothread && do_stop) { - if(pthread_kill(ctx->bg_tid, 0) == ESRCH) { - /* thread has been killed */ - do_stop = 0; - } - } -#endif /* HAVE_PTHREAD */ - if(do_stop) - ub_stop_bg(ctx); - if(ctx->created_bg && ctx->pipe_pid != getpid() && ctx->thread_worker) { - /* This delete is happening from a different process. Delete - * the thread worker from this process memory space. The - * thread is not there to do so, so it is freed here. */ - struct ub_event_base* evbase = comm_base_internal( - ctx->thread_worker->base); - libworker_delete_event(ctx->thread_worker); - ctx->thread_worker = NULL; -#ifdef USE_MINI_EVENT - ub_event_base_free(evbase); -#else - /* cannot event_base_free, because the epoll_fd cleanup - * in libevent could stop the original event_base in the - * other process from working. */ - free(evbase); -#endif - } - libworker_delete_event(ctx->event_worker); - - modstack_desetup(&ctx->mods, ctx->env); - a = ctx->alloc_list; - while(a) { - na = a->super; - a->super = &ctx->superalloc; - alloc_clear(a); - free(a); - a = na; - } - local_zones_delete(ctx->local_zones); - lock_basic_destroy(&ctx->qqpipe_lock); - lock_basic_destroy(&ctx->rrpipe_lock); - lock_basic_destroy(&ctx->cfglock); - tube_delete(ctx->qq_pipe); - tube_delete(ctx->rr_pipe); - if(ctx->env) { - slabhash_delete(ctx->env->msg_cache); - rrset_cache_delete(ctx->env->rrset_cache); - infra_delete(ctx->env->infra_cache); - config_delete(ctx->env->cfg); - edns_known_options_delete(ctx->env); - edns_strings_delete(ctx->env->edns_strings); - auth_zones_delete(ctx->env->auth_zones); - free(ctx->env); - } - ub_randfree(ctx->seed_rnd); - alloc_clear(&ctx->superalloc); - listen_desetup_locks(); - traverse_postorder(&ctx->queries, delq, NULL); - if(ctx_logfile_overridden) { - log_file(NULL); - ctx_logfile_overridden = 0; - } - if(ctx->event_base_malloced) - free(ctx->event_base); - free(ctx); -#ifdef USE_WINSOCK - WSACleanup(); -#endif -} - -int -ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val) -{ - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - return UB_AFTERFINAL; - } - if(!config_set_option(ctx->env->cfg, opt, val)) { - lock_basic_unlock(&ctx->cfglock); - return UB_SYNTAX; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str) -{ - int r; - lock_basic_lock(&ctx->cfglock); - r = config_get_option_collate(ctx->env->cfg, opt, str); - lock_basic_unlock(&ctx->cfglock); - if(r == 0) r = UB_NOERROR; - else if(r == 1) r = UB_SYNTAX; - else if(r == 2) r = UB_NOMEM; - return r; -} - -int -ub_ctx_config(struct ub_ctx* ctx, const char* fname) -{ - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - return UB_AFTERFINAL; - } - if(!config_read(ctx->env->cfg, fname, NULL)) { - lock_basic_unlock(&ctx->cfglock); - return UB_SYNTAX; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta) -{ - char* dup = strdup(ta); - if(!dup) return UB_NOMEM; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - free(dup); - return UB_AFTERFINAL; - } - if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) { - lock_basic_unlock(&ctx->cfglock); - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname) -{ - char* dup = strdup(fname); - if(!dup) return UB_NOMEM; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - free(dup); - return UB_AFTERFINAL; - } - if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) { - lock_basic_unlock(&ctx->cfglock); - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname) -{ - char* dup = strdup(fname); - if(!dup) return UB_NOMEM; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - free(dup); - return UB_AFTERFINAL; - } - if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list, - dup)) { - lock_basic_unlock(&ctx->cfglock); - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname) -{ - char* dup = strdup(fname); - if(!dup) return UB_NOMEM; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - free(dup); - return UB_AFTERFINAL; - } - if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) { - lock_basic_unlock(&ctx->cfglock); - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_debuglevel(struct ub_ctx* ctx, int d) -{ - lock_basic_lock(&ctx->cfglock); - verbosity = d; - ctx->env->cfg->verbosity = d; - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int ub_ctx_debugout(struct ub_ctx* ctx, void* out) -{ - lock_basic_lock(&ctx->cfglock); - log_file((FILE*)out); - ctx_logfile_overridden = 1; - ctx->logfile_override = 1; - ctx->log_out = out; - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_async(struct ub_ctx* ctx, int dothread) -{ -#ifdef THREADS_DISABLED - if(dothread) /* cannot do threading */ - return UB_NOERROR; -#endif - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - return UB_AFTERFINAL; - } - ctx->dothread = dothread; - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_poll(struct ub_ctx* ctx) -{ - /* no need to hold lock while testing for readability. */ - return tube_poll(ctx->rr_pipe); -} - -int -ub_fd(struct ub_ctx* ctx) -{ - return tube_read_fd(ctx->rr_pipe); -} - -/** process answer from bg worker */ -static int -process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, - ub_callback_type* cb, void** cbarg, int* err, - struct ub_result** res) -{ - struct ctx_query* q; - if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { - log_err("error: bad data from bg worker %d", - (int)context_serial_getcmd(msg, len)); - return 0; - } - - lock_basic_lock(&ctx->cfglock); - q = context_deserialize_answer(ctx, msg, len, err); - if(!q) { - lock_basic_unlock(&ctx->cfglock); - /* probably simply the lookup that failed, i.e. - * response returned before cancel was sent out, so noerror */ - return 1; - } - log_assert(q->async); - - /* grab cb while locked */ - if(q->cancelled) { - *cb = NULL; - *cbarg = NULL; - } else { - *cb = q->cb; - *cbarg = q->cb_arg; - } - if(*err) { - *res = NULL; - ub_resolve_free(q->res); - } else { - /* parse the message, extract rcode, fill result */ - sldns_buffer* buf = sldns_buffer_new(q->msg_len); - struct regional* region = regional_create(); - *res = q->res; - (*res)->rcode = LDNS_RCODE_SERVFAIL; - if(region && buf) { - sldns_buffer_clear(buf); - sldns_buffer_write(buf, q->msg, q->msg_len); - sldns_buffer_flip(buf); - libworker_enter_result(*res, buf, region, - q->msg_security); - } - (*res)->answer_packet = q->msg; - (*res)->answer_len = (int)q->msg_len; - q->msg = NULL; - sldns_buffer_free(buf); - regional_destroy(region); - } - q->res = NULL; - /* delete the q from list */ - (void)rbtree_delete(&ctx->queries, q->node.key); - ctx->num_async--; - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - - if(*cb) return 2; - ub_resolve_free(*res); - return 1; -} - -/** process answer from bg worker */ -static int -process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len) -{ - int err; - ub_callback_type cb; - void* cbarg; - struct ub_result* res; - int r; - - r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); - - /* no locks held while calling callback, so that library is - * re-entrant. */ - if(r == 2) - (*cb)(cbarg, err, res); - - return r; -} - -int -ub_process(struct ub_ctx* ctx) -{ - int r; - uint8_t* msg; - uint32_t len; - while(1) { - msg = NULL; - lock_basic_lock(&ctx->rrpipe_lock); - r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); - lock_basic_unlock(&ctx->rrpipe_lock); - if(r == 0) - return UB_PIPE; - else if(r == -1) - break; - if(!process_answer(ctx, msg, len)) { - free(msg); - return UB_PIPE; - } - free(msg); - } - return UB_NOERROR; -} - -int -ub_wait(struct ub_ctx* ctx) -{ - int err; - ub_callback_type cb; - void* cbarg; - struct ub_result* res; - int r; - uint8_t* msg; - uint32_t len; - /* this is basically the same loop as _process(), but with changes. - * holds the rrpipe lock and waits with tube_wait */ - while(1) { - lock_basic_lock(&ctx->rrpipe_lock); - lock_basic_lock(&ctx->cfglock); - if(ctx->num_async == 0) { - lock_basic_unlock(&ctx->cfglock); - lock_basic_unlock(&ctx->rrpipe_lock); - break; - } - lock_basic_unlock(&ctx->cfglock); - - /* keep rrpipe locked, while - * o waiting for pipe readable - * o parsing message - * o possibly decrementing num_async - * do callback without lock - */ - r = tube_wait(ctx->rr_pipe); - if(r) { - r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); - if(r == 0) { - lock_basic_unlock(&ctx->rrpipe_lock); - return UB_PIPE; - } - if(r == -1) { - lock_basic_unlock(&ctx->rrpipe_lock); - continue; - } - r = process_answer_detail(ctx, msg, len, - &cb, &cbarg, &err, &res); - lock_basic_unlock(&ctx->rrpipe_lock); - free(msg); - if(r == 0) - return UB_PIPE; - if(r == 2) - (*cb)(cbarg, err, res); - } else { - lock_basic_unlock(&ctx->rrpipe_lock); - } - } - return UB_NOERROR; -} - -int -ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, struct ub_result** result) -{ - struct ctx_query* q; - int r; - *result = NULL; - - lock_basic_lock(&ctx->cfglock); - if(!ctx->finalized) { - r = context_finalize(ctx); - if(r) { - lock_basic_unlock(&ctx->cfglock); - return r; - } - } - /* create new ctx_query and attempt to add to the list */ - lock_basic_unlock(&ctx->cfglock); - q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL); - if(!q) - return UB_NOMEM; - /* become a resolver thread for a bit */ - - r = libworker_fg(ctx, q); - if(r) { - lock_basic_lock(&ctx->cfglock); - (void)rbtree_delete(&ctx->queries, q->node.key); - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - return r; - } - q->res->answer_packet = q->msg; - q->res->answer_len = (int)q->msg_len; - q->msg = NULL; - *result = q->res; - q->res = NULL; - - lock_basic_lock(&ctx->cfglock); - (void)rbtree_delete(&ctx->queries, q->node.key); - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, void* mydata, ub_event_callback_type callback, - int* async_id) -{ - struct ctx_query* q; - int r; - - if(async_id) - *async_id = 0; - lock_basic_lock(&ctx->cfglock); - if(!ctx->finalized) { - r = context_finalize(ctx); - if(r) { - lock_basic_unlock(&ctx->cfglock); - return r; - } - } - lock_basic_unlock(&ctx->cfglock); - if(!ctx->event_worker) { - ctx->event_worker = libworker_create_event(ctx, - ctx->event_base); - if(!ctx->event_worker) { - return UB_INITFAIL; - } - } - - /* set time in case answer comes from cache */ - ub_comm_base_now(ctx->event_worker->base); - - /* create new ctx_query and attempt to add to the list */ - q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata); - if(!q) - return UB_NOMEM; - - /* attach to mesh */ - if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) - return r; - return UB_NOERROR; -} - - -int -ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, void* mydata, ub_callback_type callback, int* async_id) -{ - struct ctx_query* q; - uint8_t* msg = NULL; - uint32_t len = 0; - - if(async_id) - *async_id = 0; - lock_basic_lock(&ctx->cfglock); - if(!ctx->finalized) { - int r = context_finalize(ctx); - if(r) { - lock_basic_unlock(&ctx->cfglock); - return r; - } - } - if(!ctx->created_bg) { - int r; - ctx->created_bg = 1; - lock_basic_unlock(&ctx->cfglock); - r = libworker_bg(ctx); - if(r) { - lock_basic_lock(&ctx->cfglock); - ctx->created_bg = 0; - lock_basic_unlock(&ctx->cfglock); - return r; - } - } else { - lock_basic_unlock(&ctx->cfglock); - } - - /* create new ctx_query and attempt to add to the list */ - q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata); - if(!q) - return UB_NOMEM; - - /* write over pipe to background worker */ - lock_basic_lock(&ctx->cfglock); - msg = context_serialize_new_query(q, &len); - if(!msg) { - (void)rbtree_delete(&ctx->queries, q->node.key); - ctx->num_async--; - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - return UB_NOMEM; - } - if(async_id) - *async_id = q->querynum; - lock_basic_unlock(&ctx->cfglock); - - lock_basic_lock(&ctx->qqpipe_lock); - if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { - lock_basic_unlock(&ctx->qqpipe_lock); - free(msg); - return UB_PIPE; - } - lock_basic_unlock(&ctx->qqpipe_lock); - free(msg); - return UB_NOERROR; -} - -int -ub_cancel(struct ub_ctx* ctx, int async_id) -{ - struct ctx_query* q; - uint8_t* msg = NULL; - uint32_t len = 0; - lock_basic_lock(&ctx->cfglock); - q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); - if(!q || !q->async) { - /* it is not there, so nothing to do */ - lock_basic_unlock(&ctx->cfglock); - return UB_NOID; - } - log_assert(q->async); - q->cancelled = 1; - - /* delete it */ - if(!ctx->dothread) { /* if forked */ - (void)rbtree_delete(&ctx->queries, q->node.key); - ctx->num_async--; - msg = context_serialize_cancel(q, &len); - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - if(!msg) { - return UB_NOMEM; - } - /* send cancel to background worker */ - lock_basic_lock(&ctx->qqpipe_lock); - if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { - lock_basic_unlock(&ctx->qqpipe_lock); - free(msg); - return UB_PIPE; - } - lock_basic_unlock(&ctx->qqpipe_lock); - free(msg); - } else { - lock_basic_unlock(&ctx->cfglock); - } - return UB_NOERROR; -} - -void -ub_resolve_free(struct ub_result* result) -{ - char** p; - if(!result) return; - free(result->qname); - if(result->canonname != result->qname) - free(result->canonname); - if(result->data) - for(p = result->data; *p; p++) - free(*p); - free(result->data); - free(result->len); - free(result->answer_packet); - free(result->why_bogus); - free(result); -} - -const char* -ub_strerror(int err) -{ - switch(err) { - case UB_NOERROR: return "no error"; - case UB_SOCKET: return "socket io error"; - case UB_NOMEM: return "out of memory"; - case UB_SYNTAX: return "syntax error"; - case UB_SERVFAIL: return "server failure"; - case UB_FORKFAIL: return "could not fork"; - case UB_INITFAIL: return "initialization failure"; - case UB_AFTERFINAL: return "setting change after finalize"; - case UB_PIPE: return "error in pipe communication with async"; - case UB_READFILE: return "error reading file"; - case UB_NOID: return "error async_id does not exist"; - default: return "unknown error"; - } -} - -int -ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr) -{ - struct sockaddr_storage storage; - socklen_t stlen; - struct config_stub* s; - char* dupl; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - errno=EINVAL; - return UB_AFTERFINAL; - } - if(!addr) { - /* disable fwd mode - the root stub should be first. */ - if(ctx->env->cfg->forwards && - strcmp(ctx->env->cfg->forwards->name, ".") == 0) { - s = ctx->env->cfg->forwards; - ctx->env->cfg->forwards = s->next; - s->next = NULL; - config_delstubs(s); - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; - } - lock_basic_unlock(&ctx->cfglock); - - /* check syntax for addr */ - if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { - errno=EINVAL; - return UB_SYNTAX; - } - - /* it parses, add root stub in front of list */ - lock_basic_lock(&ctx->cfglock); - if(!ctx->env->cfg->forwards || - strcmp(ctx->env->cfg->forwards->name, ".") != 0) { - s = calloc(1, sizeof(*s)); - if(!s) { - lock_basic_unlock(&ctx->cfglock); - errno=ENOMEM; - return UB_NOMEM; - } - s->name = strdup("."); - if(!s->name) { - free(s); - lock_basic_unlock(&ctx->cfglock); - errno=ENOMEM; - return UB_NOMEM; - } - s->next = ctx->env->cfg->forwards; - ctx->env->cfg->forwards = s; - } else { - log_assert(ctx->env->cfg->forwards); - s = ctx->env->cfg->forwards; - } - dupl = strdup(addr); - if(!dupl) { - lock_basic_unlock(&ctx->cfglock); - errno=ENOMEM; - return UB_NOMEM; - } - if(!cfg_strlist_insert(&s->addrs, dupl)) { - lock_basic_unlock(&ctx->cfglock); - errno=ENOMEM; - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int ub_ctx_set_tls(struct ub_ctx* ctx, int tls) -{ - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - errno=EINVAL; - return UB_AFTERFINAL; - } - ctx->env->cfg->ssl_upstream = tls; - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, - int isprime) -{ - char* a; - struct config_stub **prev, *elem; - - /* check syntax for zone name */ - if(zone) { - uint8_t* nm; - int nmlabs; - size_t nmlen; - if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { - errno=EINVAL; - return UB_SYNTAX; - } - free(nm); - } else { - zone = "."; - } - - /* check syntax for addr (if not NULL) */ - if(addr) { - struct sockaddr_storage storage; - socklen_t stlen; - if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { - errno=EINVAL; - return UB_SYNTAX; - } - } - - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - errno=EINVAL; - return UB_AFTERFINAL; - } - - /* arguments all right, now find or add the stub */ - prev = &ctx->env->cfg->stubs; - elem = cfg_stub_find(&prev, zone); - if(!elem && !addr) { - /* not found and we want to delete, nothing to do */ - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; - } else if(elem && !addr) { - /* found, and we want to delete */ - *prev = elem->next; - config_delstub(elem); - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; - } else if(!elem) { - /* not found, create the stub entry */ - elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); - if(elem) elem->name = strdup(zone); - if(!elem || !elem->name) { - free(elem); - lock_basic_unlock(&ctx->cfglock); - errno = ENOMEM; - return UB_NOMEM; - } - elem->next = ctx->env->cfg->stubs; - ctx->env->cfg->stubs = elem; - } - - /* add the address to the list and set settings */ - elem->isprime = isprime; - a = strdup(addr); - if(!a) { - lock_basic_unlock(&ctx->cfglock); - errno = ENOMEM; - return UB_NOMEM; - } - if(!cfg_strlist_insert(&elem->addrs, a)) { - lock_basic_unlock(&ctx->cfglock); - errno = ENOMEM; - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - return UB_NOERROR; -} - -int -ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) -{ - FILE* in; - int numserv = 0; - char buf[1024]; - char* parse, *addr; - int r; - - if(fname == NULL) { -#if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) - fname = "/etc/resolv.conf"; -#else - FIXED_INFO *info; - ULONG buflen = sizeof(*info); - IP_ADDR_STRING *ptr; - - info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); - if (info == NULL) - return UB_READFILE; - - if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { - free(info); - info = (FIXED_INFO *) malloc(buflen); - if (info == NULL) - return UB_READFILE; - } - - if (GetNetworkParams(info, &buflen) == NO_ERROR) { - int retval=0; - ptr = &(info->DnsServerList); - while (ptr) { - numserv++; - if((retval=ub_ctx_set_fwd(ctx, - ptr->IpAddress.String))!=0) { - free(info); - return retval; - } - ptr = ptr->Next; - } - free(info); - if (numserv==0) - return UB_READFILE; - return UB_NOERROR; - } - free(info); - return UB_READFILE; -#endif /* WINDOWS */ - } - in = fopen(fname, "r"); - if(!in) { - /* error in errno! perror(fname) */ - return UB_READFILE; - } - while(fgets(buf, (int)sizeof(buf), in)) { - buf[sizeof(buf)-1] = 0; - parse=buf; - while(*parse == ' ' || *parse == '\t') - parse++; - if(strncmp(parse, "nameserver", 10) == 0) { - numserv++; - parse += 10; /* skip 'nameserver' */ - /* skip whitespace */ - while(*parse == ' ' || *parse == '\t') - parse++; - addr = parse; - /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ - while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') - parse++; - /* terminate after the address, remove newline */ - *parse = 0; - - if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { - fclose(in); - return r; - } - } - } - fclose(in); - if(numserv == 0) { - /* from resolv.conf(5) if none given, use localhost */ - return ub_ctx_set_fwd(ctx, "127.0.0.1"); - } - return UB_NOERROR; -} - -int -ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) -{ - FILE* in; - char buf[1024], ldata[2048]; - char* parse, *addr, *name, *ins; - lock_basic_lock(&ctx->cfglock); - if(ctx->finalized) { - lock_basic_unlock(&ctx->cfglock); - errno=EINVAL; - return UB_AFTERFINAL; - } - lock_basic_unlock(&ctx->cfglock); - if(fname == NULL) { -#if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) - /* - * If this is Windows NT/XP/2K it's in - * %WINDIR%\system32\drivers\etc\hosts. - * If this is Windows 95/98/Me it's in %WINDIR%\hosts. - */ - name = getenv("WINDIR"); - if (name != NULL) { - int retval=0; - snprintf(buf, sizeof(buf), "%s%s", name, - "\\system32\\drivers\\etc\\hosts"); - if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { - snprintf(buf, sizeof(buf), "%s%s", name, - "\\hosts"); - retval=ub_ctx_hosts(ctx, buf); - } - return retval; - } - return UB_READFILE; -#else - fname = "/etc/hosts"; -#endif /* WIN32 */ - } - in = fopen(fname, "r"); - if(!in) { - /* error in errno! perror(fname) */ - return UB_READFILE; - } - while(fgets(buf, (int)sizeof(buf), in)) { - buf[sizeof(buf)-1] = 0; - parse=buf; - while(*parse == ' ' || *parse == '\t') - parse++; - if(*parse == '#') - continue; /* skip comment */ - /* format: spaces spaces ... */ - addr = parse; - /* skip addr */ - while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') - parse++; - if(*parse == '\r') - parse++; - if(*parse == '\n' || *parse == 0) - continue; - if(*parse == '%') - continue; /* ignore macOSX fe80::1%lo0 localhost */ - if(*parse != ' ' && *parse != '\t') { - /* must have whitespace after address */ - fclose(in); - errno=EINVAL; - return UB_SYNTAX; - } - *parse++ = 0; /* end delimiter for addr ... */ - /* go to names and add them */ - while(*parse) { - while(*parse == ' ' || *parse == '\t' || *parse=='\n' - || *parse=='\r') - parse++; - if(*parse == 0 || *parse == '#') - break; - /* skip name, allows (too) many printable characters */ - name = parse; - while('!' <= *parse && *parse <= '~') - parse++; - if(*parse) - *parse++ = 0; /* end delimiter for name */ - snprintf(ldata, sizeof(ldata), "%s %s %s", - name, str_is_ip6(addr)?"AAAA":"A", addr); - ins = strdup(ldata); - if(!ins) { - /* out of memory */ - fclose(in); - errno=ENOMEM; - return UB_NOMEM; - } - lock_basic_lock(&ctx->cfglock); - if(!cfg_strlist_insert(&ctx->env->cfg->local_data, - ins)) { - lock_basic_unlock(&ctx->cfglock); - fclose(in); - errno=ENOMEM; - return UB_NOMEM; - } - lock_basic_unlock(&ctx->cfglock); - } - } - fclose(in); - return UB_NOERROR; -} - -/** finalize the context, if not already finalized */ -static int ub_ctx_finalize(struct ub_ctx* ctx) -{ - int res = 0; - lock_basic_lock(&ctx->cfglock); - if (!ctx->finalized) { - res = context_finalize(ctx); - } - lock_basic_unlock(&ctx->cfglock); - return res; -} - -/* Print local zones and RR data */ -int ub_ctx_print_local_zones(struct ub_ctx* ctx) -{ - int res = ub_ctx_finalize(ctx); - if (res) return res; - - local_zones_print(ctx->local_zones); - - return UB_NOERROR; -} - -/* Add a new zone */ -int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, - const char *zone_type) -{ - enum localzone_type t; - struct local_zone* z; - uint8_t* nm; - int nmlabs; - size_t nmlen; - - int res = ub_ctx_finalize(ctx); - if (res) return res; - - if(!local_zone_str2type(zone_type, &t)) { - return UB_SYNTAX; - } - - if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { - return UB_SYNTAX; - } - - lock_rw_wrlock(&ctx->local_zones->lock); - if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, - LDNS_RR_CLASS_IN))) { - /* already present in tree */ - lock_rw_wrlock(&z->lock); - z->type = t; /* update type anyway */ - lock_rw_unlock(&z->lock); - lock_rw_unlock(&ctx->local_zones->lock); - free(nm); - return UB_NOERROR; - } - if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, - LDNS_RR_CLASS_IN, t)) { - lock_rw_unlock(&ctx->local_zones->lock); - return UB_NOMEM; - } - lock_rw_unlock(&ctx->local_zones->lock); - return UB_NOERROR; -} - -/* Remove zone */ -int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name) -{ - struct local_zone* z; - uint8_t* nm; - int nmlabs; - size_t nmlen; - - int res = ub_ctx_finalize(ctx); - if (res) return res; - - if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { - return UB_SYNTAX; - } - - lock_rw_wrlock(&ctx->local_zones->lock); - if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, - LDNS_RR_CLASS_IN))) { - /* present in tree */ - local_zones_del_zone(ctx->local_zones, z); - } - lock_rw_unlock(&ctx->local_zones->lock); - free(nm); - return UB_NOERROR; -} - -/* Add new RR data */ -int ub_ctx_data_add(struct ub_ctx* ctx, const char *data) -{ - int res = ub_ctx_finalize(ctx); - if (res) return res; - - res = local_zones_add_RR(ctx->local_zones, data); - return (!res) ? UB_NOMEM : UB_NOERROR; -} - -/* Remove RR data */ -int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data) -{ - uint8_t* nm; - int nmlabs; - size_t nmlen; - int res = ub_ctx_finalize(ctx); - if (res) return res; - - if(!parse_dname(data, &nm, &nmlen, &nmlabs)) - return UB_SYNTAX; - - local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, - LDNS_RR_CLASS_IN); - - free(nm); - return UB_NOERROR; -} - -const char* ub_version(void) -{ - return PACKAGE_VERSION; -} - -int -ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { - struct ub_event_base* new_base; - - if (!ctx || !ctx->event_base || !base) { - return UB_INITFAIL; - } - if (ub_libevent_get_event_base(ctx->event_base) == base) { - /* already set */ - return UB_NOERROR; - } - - lock_basic_lock(&ctx->cfglock); - /* destroy the current worker - safe to pass in NULL */ - libworker_delete_event(ctx->event_worker); - ctx->event_worker = NULL; - new_base = ub_libevent_event_base(base); - if (new_base) - ctx->event_base = new_base; - ctx->created_bg = 0; - ctx->dothread = 1; - lock_basic_unlock(&ctx->cfglock); - return new_base ? UB_NOERROR : UB_INITFAIL; -} diff --git a/crates/libunbound-sys/unbound/libunbound/libworker.c b/crates/libunbound-sys/unbound/libunbound/libworker.c deleted file mode 100644 index 10424493..00000000 --- a/crates/libunbound-sys/unbound/libunbound/libworker.c +++ /dev/null @@ -1,1070 +0,0 @@ -/* - * libunbound/worker.c - worker thread or process that resolves - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the worker process or thread that performs - * the DNS resolving and validation. The worker is called by a procedure - * and if in the background continues until exit, if in the foreground - * returns from the procedure when done. - */ -#include "config.h" -#ifdef HAVE_SSL -#include -#endif -#include "libunbound/libworker.h" -#include "libunbound/context.h" -#include "libunbound/unbound.h" -#include "libunbound/worker.h" -#include "libunbound/unbound-event.h" -#include "services/outside_network.h" -#include "services/mesh.h" -#include "services/localzone.h" -#include "services/cache/rrset.h" -#include "services/outbound_list.h" -#include "services/authzone.h" -#include "util/fptr_wlist.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/random.h" -#include "util/config_file.h" -#include "util/netevent.h" -#include "util/storage/lookup3.h" -#include "util/storage/slabhash.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "util/data/msgreply.h" -#include "util/data/msgencode.h" -#include "util/tube.h" -#include "iterator/iter_fwd.h" -#include "iterator/iter_hints.h" -#include "sldns/sbuffer.h" -#include "sldns/str2wire.h" -#ifdef USE_DNSTAP -#include "dnstap/dtstream.h" -#endif - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) -#undef HAVE_FORK -#endif - -/** handle new query command for bg worker */ -static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); - -/** delete libworker env */ -static void -libworker_delete_env(struct libworker* w) -{ - if(w->env) { - outside_network_quit_prepare(w->back); - mesh_delete(w->env->mesh); - context_release_alloc(w->ctx, w->env->alloc, - !w->is_bg || w->is_bg_thread); - sldns_buffer_free(w->env->scratch_buffer); - regional_destroy(w->env->scratch); - forwards_delete(w->env->fwds); - hints_delete(w->env->hints); - ub_randfree(w->env->rnd); - free(w->env); - } -#ifdef HAVE_SSL - SSL_CTX_free(w->sslctx); -#endif - outside_network_delete(w->back); -} - -/** delete libworker struct */ -static void -libworker_delete(struct libworker* w) -{ - if(!w) return; - libworker_delete_env(w); - comm_base_delete(w->base); - free(w); -} - -void -libworker_delete_event(struct libworker* w) -{ - if(!w) return; - libworker_delete_env(w); - comm_base_delete_no_base(w->base); - free(w); -} - -/** setup fresh libworker struct */ -static struct libworker* -libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) -{ - struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); - struct config_file* cfg = ctx->env->cfg; - int* ports; - int numports; - if(!w) return NULL; - w->is_bg = is_bg; - w->ctx = ctx; - w->env = (struct module_env*)malloc(sizeof(*w->env)); - if(!w->env) { - free(w); - return NULL; - } - *w->env = *ctx->env; - w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); - if(!w->env->alloc) { - libworker_delete(w); - return NULL; - } - w->thread_num = w->env->alloc->thread_num; - alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); - if(!w->is_bg || w->is_bg_thread) { - lock_basic_lock(&ctx->cfglock); - } - w->env->scratch = regional_create_custom(cfg->msg_buffer_size); - w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size); - w->env->fwds = forwards_create(); - if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { - forwards_delete(w->env->fwds); - w->env->fwds = NULL; - } - w->env->hints = hints_create(); - if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { - hints_delete(w->env->hints); - w->env->hints = NULL; - } - w->sslctx = connect_sslctx_create(NULL, NULL, - cfg->tls_cert_bundle, cfg->tls_win_cert); - if(!w->sslctx) { - /* to make the setup fail after unlock */ - hints_delete(w->env->hints); - w->env->hints = NULL; - } - if(!w->is_bg || w->is_bg_thread) { - lock_basic_unlock(&ctx->cfglock); - } - if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds || - !w->env->hints) { - libworker_delete(w); - return NULL; - } - w->env->worker = (struct worker*)w; - w->env->probe_timer = NULL; - if(!w->is_bg || w->is_bg_thread) { - lock_basic_lock(&ctx->cfglock); - } - if(!(w->env->rnd = ub_initstate(ctx->seed_rnd))) { - if(!w->is_bg || w->is_bg_thread) { - lock_basic_unlock(&ctx->cfglock); - } - libworker_delete(w); - return NULL; - } - if(!w->is_bg || w->is_bg_thread) { - lock_basic_unlock(&ctx->cfglock); - } - if(1) { - /* primitive lockout for threading: if it overwrites another - * thread it is like wiping the cache (which is likely empty - * at the start) */ - /* note we are holding the ctx lock in normal threaded - * cases so that is solved properly, it is only for many ctx - * in different threads that this may clash */ - static int done_raninit = 0; - if(!done_raninit) { - done_raninit = 1; - hash_set_raninit((uint32_t)ub_random(w->env->rnd)); - } - } - - if(eb) - w->base = comm_base_create_event(eb); - else w->base = comm_base_create(0); - if(!w->base) { - libworker_delete(w); - return NULL; - } - w->env->worker_base = w->base; - if(!w->is_bg || w->is_bg_thread) { - lock_basic_lock(&ctx->cfglock); - } - numports = cfg_condense_ports(cfg, &ports); - if(numports == 0) { - if(!w->is_bg || w->is_bg_thread) { - lock_basic_unlock(&ctx->cfglock); - } - libworker_delete(w); - return NULL; - } - w->back = outside_network_create(w->base, cfg->msg_buffer_size, - (size_t)cfg->outgoing_num_ports, cfg->out_ifs, - cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, - cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp, - w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, - ports, numports, cfg->unwanted_threshold, - cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w, - cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx, - cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect, - cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout, - cfg->tcp_auth_query_timeout); - w->env->outnet = w->back; - if(!w->is_bg || w->is_bg_thread) { - lock_basic_unlock(&ctx->cfglock); - } - free(ports); - if(!w->back) { - libworker_delete(w); - return NULL; - } - w->env->mesh = mesh_create(&ctx->mods, w->env); - if(!w->env->mesh) { - libworker_delete(w); - return NULL; - } - w->env->send_query = &libworker_send_query; - w->env->detach_subs = &mesh_detach_subs; - w->env->attach_sub = &mesh_attach_sub; - w->env->add_sub = &mesh_add_sub; - w->env->kill_sub = &mesh_state_delete; - w->env->detect_cycle = &mesh_detect_cycle; - comm_base_timept(w->base, &w->env->now, &w->env->now_tv); - return w; -} - -struct libworker* libworker_create_event(struct ub_ctx* ctx, - struct ub_event_base* eb) -{ - return libworker_setup(ctx, 0, eb); -} - -/** handle cancel command for bg worker */ -static void -handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) -{ - struct ctx_query* q; - if(w->is_bg_thread) { - lock_basic_lock(&w->ctx->cfglock); - q = context_deserialize_cancel(w->ctx, buf, len); - lock_basic_unlock(&w->ctx->cfglock); - } else { - q = context_deserialize_cancel(w->ctx, buf, len); - } - if(!q) { - /* probably simply lookup failed, i.e. the message had been - * processed and answered before the cancel arrived */ - return; - } - q->cancelled = 1; - free(buf); -} - -/** do control command coming into bg server */ -static void -libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) -{ - switch(context_serial_getcmd(msg, len)) { - default: - case UB_LIBCMD_ANSWER: - log_err("unknown command for bg worker %d", - (int)context_serial_getcmd(msg, len)); - /* and fall through to quit */ - /* fallthrough */ - case UB_LIBCMD_QUIT: - free(msg); - comm_base_exit(w->base); - break; - case UB_LIBCMD_NEWQUERY: - handle_newq(w, msg, len); - break; - case UB_LIBCMD_CANCEL: - handle_cancel(w, msg, len); - break; - } -} - -/** handle control command coming into server */ -void -libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), - uint8_t* msg, size_t len, int err, void* arg) -{ - struct libworker* w = (struct libworker*)arg; - - if(err != 0) { - free(msg); - /* it is of no use to go on, exit */ - comm_base_exit(w->base); - return; - } - libworker_do_cmd(w, msg, len); /* also frees the buf */ -} - -/** the background thread func */ -static void* -libworker_dobg(void* arg) -{ - /* setup */ - uint32_t m; - struct libworker* w = (struct libworker*)arg; - struct ub_ctx* ctx; - if(!w) { - log_err("libunbound bg worker init failed, nomem"); - return NULL; - } - ctx = w->ctx; - log_thread_set(&w->thread_num); -#ifdef THREADS_DISABLED - /* we are forked */ - w->is_bg_thread = 0; - /* close non-used parts of the pipes */ - tube_close_write(ctx->qq_pipe); - tube_close_read(ctx->rr_pipe); -#endif - if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, - libworker_handle_control_cmd, w)) { - log_err("libunbound bg worker init failed, no bglisten"); - return NULL; - } - if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { - log_err("libunbound bg worker init failed, no bgwrite"); - return NULL; - } - - /* do the work */ - comm_base_dispatch(w->base); - - /* cleanup */ - m = UB_LIBCMD_QUIT; - w->want_quit = 1; - tube_remove_bg_listen(w->ctx->qq_pipe); - tube_remove_bg_write(w->ctx->rr_pipe); - libworker_delete(w); - (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, - (uint32_t)sizeof(m), 0); -#ifdef THREADS_DISABLED - /* close pipes from forked process before exit */ - tube_close_read(ctx->qq_pipe); - tube_close_write(ctx->rr_pipe); -#endif - return NULL; -} - -int libworker_bg(struct ub_ctx* ctx) -{ - struct libworker* w; - /* fork or threadcreate */ - lock_basic_lock(&ctx->cfglock); - if(ctx->dothread) { - lock_basic_unlock(&ctx->cfglock); - w = libworker_setup(ctx, 1, NULL); - if(!w) return UB_NOMEM; - w->is_bg_thread = 1; - ctx->thread_worker = w; -#ifdef ENABLE_LOCK_CHECKS - w->thread_num = 1; /* for nicer DEBUG checklocks */ -#endif - ub_thread_create(&ctx->bg_tid, libworker_dobg, w); - } else { - lock_basic_unlock(&ctx->cfglock); -#ifndef HAVE_FORK - /* no fork on windows */ - return UB_FORKFAIL; -#else /* HAVE_FORK */ - switch((ctx->bg_pid=fork())) { - case 0: - w = libworker_setup(ctx, 1, NULL); - if(!w) fatal_exit("out of memory"); - /* close non-used parts of the pipes */ - tube_close_write(ctx->qq_pipe); - tube_close_read(ctx->rr_pipe); - (void)libworker_dobg(w); - exit(0); - break; - case -1: - return UB_FORKFAIL; - default: - /* close non-used parts, so that the worker - * bgprocess gets 'pipe closed' when the - * main process exits */ - tube_close_read(ctx->qq_pipe); - tube_close_write(ctx->rr_pipe); - break; - } -#endif /* HAVE_FORK */ - } - return UB_NOERROR; -} - -/** insert canonname */ -static int -fill_canon(struct ub_result* res, uint8_t* s) -{ - char buf[255+2]; - dname_str(s, buf); - res->canonname = strdup(buf); - return res->canonname != 0; -} - -/** fill data into result */ -static int -fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, - uint8_t* finalcname, struct query_info* rq, struct reply_info* rep) -{ - size_t i; - struct packed_rrset_data* data; - res->ttl = 0; - if(!answer) { - if(finalcname) { - if(!fill_canon(res, finalcname)) - return 0; /* out of memory */ - } - if(rep->rrset_count != 0) - res->ttl = (int)rep->ttl; - res->data = (char**)calloc(1, sizeof(char*)); - if(!res->data) - return 0; /* out of memory */ - res->len = (int*)calloc(1, sizeof(int)); - if(!res->len) { - free(res->data); - res->data = NULL; - return 0; /* out of memory */ - } - return 1; - } - data = (struct packed_rrset_data*)answer->entry.data; - if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { - if(!fill_canon(res, answer->rk.dname)) - return 0; /* out of memory */ - } else res->canonname = NULL; - res->data = (char**)calloc(data->count+1, sizeof(char*)); - if(!res->data) - return 0; /* out of memory */ - res->len = (int*)calloc(data->count+1, sizeof(int)); - if(!res->len) { - free(res->data); - res->data = NULL; - return 0; /* out of memory */ - } - for(i=0; icount; i++) { - /* remove rdlength from rdata */ - res->len[i] = (int)(data->rr_len[i] - 2); - res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); - if(!res->data[i]) { - size_t j; - for(j=0; jdata[j]); - res->data[j] = NULL; - } - free(res->data); - res->data = NULL; - free(res->len); - res->len = NULL; - return 0; /* out of memory */ - } - } - /* ttl for positive answers, from CNAME and answer RRs */ - if(data->count != 0) { - size_t j; - res->ttl = (int)data->ttl; - for(j=0; jan_numrrsets; j++) { - struct packed_rrset_data* d = - (struct packed_rrset_data*)rep->rrsets[j]-> - entry.data; - if((int)d->ttl < res->ttl) - res->ttl = (int)d->ttl; - } - } - /* ttl for negative answers */ - if(data->count == 0 && rep->rrset_count != 0) - res->ttl = (int)rep->ttl; - res->data[data->count] = NULL; - res->len[data->count] = 0; - return 1; -} - -/** fill result from parsed message, on error fills servfail */ -void -libworker_enter_result(struct ub_result* res, sldns_buffer* buf, - struct regional* temp, enum sec_status msg_security) -{ - struct query_info rq; - struct reply_info* rep; - res->rcode = LDNS_RCODE_SERVFAIL; - rep = parse_reply_in_temp_region(buf, temp, &rq); - if(!rep) { - log_err("cannot parse buf"); - return; /* error parsing buf, or out of memory */ - } - if(!fill_res(res, reply_find_answer_rrset(&rq, rep), - reply_find_final_cname_target(&rq, rep), &rq, rep)) - return; /* out of memory */ - /* rcode, havedata, nxdomain, secure, bogus */ - res->rcode = (int)FLAGS_GET_RCODE(rep->flags); - if(res->data && res->data[0]) - res->havedata = 1; - if(res->rcode == LDNS_RCODE_NXDOMAIN) - res->nxdomain = 1; - if(msg_security == sec_status_secure) - res->secure = 1; - if(msg_security == sec_status_bogus || - msg_security == sec_status_secure_sentinel_fail) - res->bogus = 1; -} - -/** fillup fg results */ -static void -libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf, - enum sec_status s, char* why_bogus, int was_ratelimited) -{ - q->res->was_ratelimited = was_ratelimited; - if(why_bogus) - q->res->why_bogus = strdup(why_bogus); - if(rcode != 0) { - q->res->rcode = rcode; - q->msg_security = s; - return; - } - - q->res->rcode = LDNS_RCODE_SERVFAIL; - q->msg_security = sec_status_unchecked; - q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); - q->msg_len = sldns_buffer_limit(buf); - if(!q->msg) { - return; /* the error is in the rcode */ - } - - /* canonname and results */ - q->msg_security = s; - libworker_enter_result(q->res, buf, q->w->env->scratch, s); -} - -void -libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, - char* why_bogus, int was_ratelimited) -{ - struct ctx_query* q = (struct ctx_query*)arg; - /* fg query is done; exit comm base */ - comm_base_exit(q->w->base); - - libworker_fillup_fg(q, rcode, buf, s, why_bogus, was_ratelimited); -} - -/** setup qinfo and edns */ -static int -setup_qinfo_edns(struct libworker* w, struct ctx_query* q, - struct query_info* qinfo, struct edns_data* edns) -{ - qinfo->qtype = (uint16_t)q->res->qtype; - qinfo->qclass = (uint16_t)q->res->qclass; - qinfo->local_alias = NULL; - qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len); - if(!qinfo->qname) { - return 0; - } - edns->edns_present = 1; - edns->ext_rcode = 0; - edns->edns_version = 0; - edns->bits = EDNS_DO; - edns->opt_list_in = NULL; - edns->opt_list_out = NULL; - edns->opt_list_inplace_cb_out = NULL; - edns->padding_block_size = 0; - edns->cookie_present = 0; - edns->cookie_valid = 0; - if(sldns_buffer_capacity(w->back->udp_buff) < 65535) - edns->udp_size = (uint16_t)sldns_buffer_capacity( - w->back->udp_buff); - else edns->udp_size = 65535; - return 1; -} - -int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) -{ - struct libworker* w = libworker_setup(ctx, 0, NULL); - uint16_t qflags, qid; - struct query_info qinfo; - struct edns_data edns; - if(!w) - return UB_INITFAIL; - if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { - libworker_delete(w); - return UB_SYNTAX; - } - qid = 0; - qflags = BIT_RD; - q->w = w; - /* see if there is a fixed answer */ - sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); - sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); - if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns, - w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, NULL)) { - regional_free_all(w->env->scratch); - libworker_fillup_fg(q, LDNS_RCODE_NOERROR, - w->back->udp_buff, sec_status_insecure, NULL, 0); - libworker_delete(w); - free(qinfo.qname); - return UB_NOERROR; - } - if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, - w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { - regional_free_all(w->env->scratch); - libworker_fillup_fg(q, LDNS_RCODE_NOERROR, - w->back->udp_buff, sec_status_insecure, NULL, 0); - libworker_delete(w); - free(qinfo.qname); - return UB_NOERROR; - } - /* process new query */ - if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) { - free(qinfo.qname); - return UB_NOMEM; - } - free(qinfo.qname); - - /* wait for reply */ - comm_base_dispatch(w->base); - - libworker_delete(w); - return UB_NOERROR; -} - -void -libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf, - enum sec_status s, char* why_bogus, int was_ratelimited) -{ - struct ctx_query* q = (struct ctx_query*)arg; - ub_event_callback_type cb = q->cb_event; - void* cb_arg = q->cb_arg; - int cancelled = q->cancelled; - - /* delete it now */ - struct ub_ctx* ctx = q->w->ctx; - lock_basic_lock(&ctx->cfglock); - (void)rbtree_delete(&ctx->queries, q->node.key); - ctx->num_async--; - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - - if(!cancelled) { - /* call callback */ - int sec = 0; - if(s == sec_status_bogus) - sec = 1; - else if(s == sec_status_secure) - sec = 2; - (*cb)(cb_arg, rcode, (buf?(void*)sldns_buffer_begin(buf):NULL), - (buf?(int)sldns_buffer_limit(buf):0), sec, why_bogus, was_ratelimited); - } -} - -int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, - int* async_id) -{ - struct libworker* w = ctx->event_worker; - uint16_t qflags, qid; - struct query_info qinfo; - struct edns_data edns; - if(!w) - return UB_INITFAIL; - if(!setup_qinfo_edns(w, q, &qinfo, &edns)) - return UB_SYNTAX; - qid = 0; - qflags = BIT_RD; - q->w = w; - /* see if there is a fixed answer */ - sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); - sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); - if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns, - w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, NULL)) { - regional_free_all(w->env->scratch); - free(qinfo.qname); - libworker_event_done_cb(q, LDNS_RCODE_NOERROR, - w->back->udp_buff, sec_status_insecure, NULL, 0); - return UB_NOERROR; - } - if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, - w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { - regional_free_all(w->env->scratch); - free(qinfo.qname); - libworker_event_done_cb(q, LDNS_RCODE_NOERROR, - w->back->udp_buff, sec_status_insecure, NULL, 0); - return UB_NOERROR; - } - /* process new query */ - if(async_id) - *async_id = q->querynum; - if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) { - free(qinfo.qname); - return UB_NOMEM; - } - free(qinfo.qname); - return UB_NOERROR; -} - -/** add result to the bg worker result queue */ -static void -add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt, - int err, char* reason, int was_ratelimited) -{ - uint8_t* msg = NULL; - uint32_t len = 0; - - if(w->want_quit) { - context_query_delete(q); - return; - } - /* serialize and delete unneeded q */ - if(w->is_bg_thread) { - lock_basic_lock(&w->ctx->cfglock); - if(reason) - q->res->why_bogus = strdup(reason); - q->res->was_ratelimited = was_ratelimited; - if(pkt) { - q->msg_len = sldns_buffer_remaining(pkt); - q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len); - if(!q->msg) { - msg = context_serialize_answer(q, UB_NOMEM, NULL, &len); - } else { - msg = context_serialize_answer(q, err, NULL, &len); - } - } else { - msg = context_serialize_answer(q, err, NULL, &len); - } - lock_basic_unlock(&w->ctx->cfglock); - } else { - if(reason) - q->res->why_bogus = strdup(reason); - q->res->was_ratelimited = was_ratelimited; - msg = context_serialize_answer(q, err, pkt, &len); - (void)rbtree_delete(&w->ctx->queries, q->node.key); - w->ctx->num_async--; - context_query_delete(q); - } - - if(!msg) { - log_err("out of memory for async answer"); - return; - } - if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { - log_err("out of memory for async answer"); - return; - } -} - -void -libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, - char* why_bogus, int was_ratelimited) -{ - struct ctx_query* q = (struct ctx_query*)arg; - - if(q->cancelled || q->w->back->want_to_quit) { - if(q->w->is_bg_thread) { - /* delete it now */ - struct ub_ctx* ctx = q->w->ctx; - lock_basic_lock(&ctx->cfglock); - (void)rbtree_delete(&ctx->queries, q->node.key); - ctx->num_async--; - context_query_delete(q); - lock_basic_unlock(&ctx->cfglock); - } - /* cancelled, do not give answer */ - return; - } - q->msg_security = s; - if(!buf) { - buf = q->w->env->scratch_buffer; - } - if(rcode != 0) { - error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); - } - add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus, was_ratelimited); -} - - -/** handle new query command for bg worker */ -static void -handle_newq(struct libworker* w, uint8_t* buf, uint32_t len) -{ - uint16_t qflags, qid; - struct query_info qinfo; - struct edns_data edns; - struct ctx_query* q; - if(w->is_bg_thread) { - lock_basic_lock(&w->ctx->cfglock); - q = context_lookup_new_query(w->ctx, buf, len); - lock_basic_unlock(&w->ctx->cfglock); - } else { - q = context_deserialize_new_query(w->ctx, buf, len); - } - free(buf); - if(!q) { - log_err("failed to deserialize newq"); - return; - } - if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { - add_bg_result(w, q, NULL, UB_SYNTAX, NULL, 0); - return; - } - qid = 0; - qflags = BIT_RD; - /* see if there is a fixed answer */ - sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); - sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); - if(local_zones_answer(w->ctx->local_zones, w->env, &qinfo, &edns, - w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, NULL)) { - regional_free_all(w->env->scratch); - q->msg_security = sec_status_insecure; - add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0); - free(qinfo.qname); - return; - } - if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones, - w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { - regional_free_all(w->env->scratch); - q->msg_security = sec_status_insecure; - add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0); - free(qinfo.qname); - return; - } - q->w = w; - /* process new query */ - if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, - w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) { - add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0); - } - free(qinfo.qname); -} - -void libworker_alloc_cleanup(void* arg) -{ - struct libworker* w = (struct libworker*)arg; - slabhash_clear(&w->env->rrset_cache->table); - slabhash_clear(w->env->msg_cache); -} - -struct outbound_entry* libworker_send_query(struct query_info* qinfo, - uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int check_ratelimit, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, - struct module_qstate* q, int* was_ratelimited) -{ - struct libworker* w = (struct libworker*)q->env->worker; - struct outbound_entry* e = (struct outbound_entry*)regional_alloc( - q->region, sizeof(*e)); - if(!e) - return NULL; - e->qstate = q; - e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec, - want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream, - tls_auth_name, addr, addrlen, zone, zonelen, q, - libworker_handle_service_reply, e, w->back->udp_buff, q->env, - was_ratelimited); - if(!e->qsent) { - return NULL; - } - return e; -} - -int -libworker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info) -{ - struct outbound_entry* e = (struct outbound_entry*)arg; - struct libworker* lw = (struct libworker*)e->qstate->env->worker; - - if(error != 0) { - mesh_report_reply(lw->env->mesh, e, reply_info, error); - return 0; - } - /* sanity check. */ - if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) - || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != - LDNS_PACKET_QUERY - || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { - /* error becomes timeout for the module as if this reply - * never arrived. */ - mesh_report_reply(lw->env->mesh, e, reply_info, - NETEVENT_TIMEOUT); - return 0; - } - mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); - return 0; -} - -/* --- fake callbacks for fptr_wlist to work --- */ -void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), - uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), - int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -int worker_handle_request(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -int remote_control_callback(struct comm_point* ATTR_UNUSED(c), - void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - log_assert(0); - return 0; -} - -void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo), - uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), - int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), - int ATTR_UNUSED(check_ratelimit), - struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), - uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), - int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), - struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited)) -{ - log_assert(0); - return 0; -} - -void -worker_alloc_cleanup(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_start_accept(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -void worker_stop_accept(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) -{ - log_assert(0); - return 0; -} - -int -codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - log_assert(0); - return 0; -} - -void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -#ifdef UB_ON_WINDOWS -void -worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* - ATTR_UNUSED(arg)) { - log_assert(0); -} - -void -wsvc_cron_cb(void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif /* UB_ON_WINDOWS */ - -#ifdef USE_DNSTAP -void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), - void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif - -#ifdef USE_DNSTAP -void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), - void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} -#endif diff --git a/crates/libunbound-sys/unbound/libunbound/libworker.h b/crates/libunbound-sys/unbound/libunbound/libworker.h deleted file mode 100644 index 42aa5bae..00000000 --- a/crates/libunbound-sys/unbound/libunbound/libworker.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * libunbound/libworker.h - worker thread or process that resolves - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the worker process or thread that performs - * the DNS resolving and validation. The worker is called by a procedure - * and if in the background continues until exit, if in the foreground - * returns from the procedure when done. - */ -#ifndef LIBUNBOUND_LIBWORKER_H -#define LIBUNBOUND_LIBWORKER_H -#include "util/data/packed_rrset.h" -struct ub_ctx; -struct ub_result; -struct module_env; -struct comm_base; -struct outside_network; -struct ub_randstate; -struct ctx_query; -struct outbound_entry; -struct module_qstate; -struct comm_point; -struct comm_reply; -struct regional; -struct tube; -struct sldns_buffer; -struct ub_event_base; -struct query_info; - -/** - * The library-worker status structure - * Internal to the worker. - */ -struct libworker { - /** every worker has a unique thread_num. (first in struct) */ - int thread_num; - /** context we are operating under */ - struct ub_ctx* ctx; - - /** is this the bg worker? */ - int is_bg; - /** is this a bg worker that is threaded (not forked)? */ - int is_bg_thread; - /** want to quit, stop handling new content */ - int want_quit; - - /** copy of the module environment with worker local entries. */ - struct module_env* env; - /** the event base this worker works with */ - struct comm_base* base; - /** the backside outside network interface to the auth servers */ - struct outside_network* back; - /** random() table for this worker. */ - struct ub_randstate* rndstate; - /** sslcontext for SSL wrapped DNS over TCP queries */ - void* sslctx; -}; - -/** - * Create a background worker - * @param ctx: is updated with pid/tid of the background worker. - * a new allocation cache is obtained from ctx. It contains the - * threadnumber and unique id for further (shared) cache insertions. - * @return 0 if OK, else error. - * Further communication is done via the pipes in ctx. - */ -int libworker_bg(struct ub_ctx* ctx); - -/** - * Create a foreground worker. - * This worker will join the threadpool of resolver threads. - * It exits when the query answer has been obtained (or error). - * This routine blocks until the worker is finished. - * @param ctx: new allocation cache obtained and returned to it. - * @param q: query (result is stored in here). - * @return 0 if finished OK, else error. - */ -int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q); - -/** - * create worker for event-based interface. - * @param ctx: context with config. - * @param eb: event base. - * @return new worker or NULL. - */ -struct libworker* libworker_create_event(struct ub_ctx* ctx, - struct ub_event_base* eb); - -/** - * Attach context_query to mesh for callback in event-driven setup. - * @param ctx: context - * @param q: context query entry - * @param async_id: store query num if query takes long. - * @return 0 if finished OK, else error. - */ -int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, - int* async_id); - -/** - * delete worker for event-based interface. does not free the event_base. - * @param w: event-based worker to delete. - */ -void libworker_delete_event(struct libworker* w); - -/** cleanup the cache to remove all rrset IDs from it, arg is libworker */ -void libworker_alloc_cleanup(void* arg); - -/** - * fill result from parsed message, on error fills servfail - * @param res: is clear at start, filled in at end. - * @param buf: contains DNS message. - * @param temp: temporary buffer for parse. - * @param msg_security: security status of the DNS message. - * On error, the res may contain a different status - * (out of memory is not secure, not bogus). - */ -void libworker_enter_result(struct ub_result* res, struct sldns_buffer* buf, - struct regional* temp, enum sec_status msg_security); - -#endif /* LIBUNBOUND_LIBWORKER_H */ diff --git a/crates/libunbound-sys/unbound/libunbound/python/LICENSE b/crates/libunbound-sys/unbound/libunbound/python/LICENSE deleted file mode 100644 index 7b769d09..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the organization nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/crates/libunbound-sys/unbound/libunbound/python/Makefile b/crates/libunbound-sys/unbound/libunbound/python/Makefile deleted file mode 100644 index 9a98ef5b..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -# -# Makefile: compilation of pyUnbound and documentation, testing -# -# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) -# Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) -# -# This software is open source. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of the organization nor the names of its -# contributors may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -help: - @echo "Please use \`make ' where is one of" - @echo " testenv to make test environment and run bash " - @echo " useful in case you don't want to install unbound but want to test examples" - @echo " doc to make documentation" - @echo " clean clean all" - -.PHONY: testenv clean doc swig - -#_unbound.so: ../../Makefile - #$(MAKE) -C ../.. - -#../../.libs/libunbound.so.0: ../../Makefile - #$(MAKE) -C ../.. - -clean: - rm -rdf examples/unbound - rm -f _unbound.so libunbound_wrap.o - $(MAKE) -C ../.. clean - -testenv: ../../.libs/libunbound.so.2 ../../.libs/_unbound.so - rm -rdf examples/unbound - cd examples && mkdir unbound && ln -s ../../unbound.py unbound/__init__.py && ln -s ../../_unbound.so unbound/_unbound.so && ln -s ../../../../.libs/libunbound.so.2 unbound/libunbound.so.2 && ls -la - cd examples && if test -f ../../../.libs/_unbound.so; then cp ../../../.libs/_unbound.so . ; fi - @echo "Run a script by typing ./script_name.py" - cd examples && LD_LIBRARY_PATH=unbound bash - rm -rdf examples/unbound examples/_unbound.so - -doc: ../../.libs/libunbound.so.0 _unbound.so - $(MAKE) -C docs html - -#for development only -swig: libunbound.i - swig -python -o libunbound_wrap.c -I../.. libunbound.i - gcc -c libunbound_wrap.c -O9 -fPIC -I../.. -I/usr/include/python2.5 -I. -o libunbound_wrap.o - gcc -shared libunbound_wrap.o -L../../.libs -lunbound -o _unbound.so - diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/_static/readme b/crates/libunbound-sys/unbound/libunbound/python/doc/_static/readme deleted file mode 100644 index db676aeb..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/_static/readme +++ /dev/null @@ -1 +0,0 @@ -this directory exists to pacify sphinx-build. diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/conf.py b/crates/libunbound-sys/unbound/libunbound/python/doc/conf.py deleted file mode 100644 index 1766036b..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/conf.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Unbound documentation build configuration file -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# All configuration values have a default value; values that are commented out -# serve to show the default value. - -import sys, os - -# If your extensions are in another directory, add it here. If the directory -# is relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../'))) -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../'))) -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../.libs/'))) -#print sys.path - -# General configuration -# --------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General substitutions. -project = 'pyUnbound' -copyright = '2009, Zdenek Vasicek, Marek Vavrusa' - -# The default replacements for |version| and |release|, also used in various -# other places throughout the built documents. -# -# The short X.Y version. -version = '1.0' -# The full version, including alpha/beta/rc tags. -release = '1.0.0' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directories, that shouldn't be searched -# for source files. -#exclude_dirs = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - - -# Options for HTML output -# ----------------------- - -# The theme that the html output should use. -html_theme = "classic" - -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -#html_style = 'default.css' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (within the static path) to place at the top of -# the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, the reST sources are included in the HTML build as _sources/. -html_copy_source = False - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Unbounddoc' - - -# Options for LaTeX output -# ------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, document class [howto/manual]). -latex_documents = [ - ('index', 'Unbound.tex', 'Unbound Documentation', - 'Zdenek Vasicek, Marek Vavrusa', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1a.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1a.rst deleted file mode 100644 index f46cb92f..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1a.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _example_resolve_name: - -Resolve a name -============== - -This basic example shows how to create a context and resolve a host address -(DNS record of A type). - -Source code ------------ - -:: - - #!/usr/bin/python - import unbound - - ctx = unbound.ub_ctx() - ctx.resolvconf("/etc/resolv.conf") - - status, result = ctx.resolve("www.google.com") - if status == 0 and result.havedata: - print "Result.data:", result.data.address_list - elif status != 0: - print "Resolve error:", unbound.ub_strerror(status) - -In contrast with the C API, the source code is more compact while the -performance of C implementation is preserved. -The main advantage is that you need not take care about the deallocation and -allocation of context and result structures; pyUnbound module does it -automatically for you. - -If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for -A records in IN class. diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1b.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1b.rst deleted file mode 100644 index 1adae2cb..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example1b.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _example_reverse_lookup: - -Reverse DNS lookup -================== - -Reverse DNS lookup involves determining the hostname associated with a given IP -address. -This example shows how reverse lookup can be done using unbound module. - -For the reverse DNS records, the special domain in-addr.arpa is reserved. -For example, a host name for the IP address ``74.125.43.147`` can be obtained -by issuing a DNS query for the PTR record for address -``147.43.125.74.in-addr.arpa.`` - -Source code ------------ - -:: - - #!/usr/bin/python - import unbound - - ctx = unbound.ub_ctx() - ctx.resolvconf("/etc/resolv.conf") - - status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) - if status == 0 and result.havedata: - print "Result.data:", result.data.domain_list - elif status != 0: - print "Resolve error:", unbound.ub_strerror(status) - -In order to simplify the python code, unbound module contains the -:meth:`unbound.reverse` function which reverses the hostname components. -This function is defined as follows:: - - def reverse(domain): - return '.'.join([a for a in domain.split(".")][::-1]) diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example2.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example2.rst deleted file mode 100644 index a2bf2cbf..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example2.rst +++ /dev/null @@ -1,41 +0,0 @@ -.. _example_setup_ctx: - -Lookup from threads -=================== - -This example shows how to use unbound module from a threaded program. -In this example, three lookup threads are created which work in background. -Each thread resolves different DNS record. - -Source code ------------ - -:: - - #!/usr/bin/python - from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN - from threading import Thread - - ctx = ub_ctx() - ctx.resolvconf("/etc/resolv.conf") - - class LookupThread(Thread): - def __init__(self,ctx, name): - Thread.__init__(self) - self.ctx = ctx - self.name = name - - def run(self): - print "Thread lookup started:",self.name - status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN) - if status == 0 and result.havedata: - print " Result:",self.name,":", result.data.address_list - - threads = [] - for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]: - thread = LookupThread(ctx, name) - thread.start() - threads.append(thread) - - for thread in threads: - thread.join() diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example3.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example3.rst deleted file mode 100644 index b0626b55..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example3.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. _example_asynch: - -Asynchronous lookup -=================== - -This example performs the name lookup in the background. -The main program keeps running while the name is resolved. - -Source code ------------ - -:: - - #!/usr/bin/python - import time - import unbound - - ctx = unbound.ub_ctx() - ctx.resolvconf("/etc/resolv.conf") - - def call_back(my_data,status,result): - print "Call_back:", my_data - if status == 0 and result.havedata: - print "Result:", result.data.address_list - my_data['done_flag'] = True - - - my_data = {'done_flag':False,'arbitrary':"object"} - status, async_id = ctx.resolve_async("www.seznam.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN) - - while (status == 0) and (not my_data['done_flag']): - status = ctx.process() - time.sleep(0.1) - - if (status != 0): - print "Resolve error:", unbound.ub_strerror(status) - -The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python -object. In this example, we used a dictionary object ``my_data``. diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example4.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example4.rst deleted file mode 100644 index a95be52f..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example4.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _example_examine: - -DNSSEC validator -================ - -This example program performs DNSSEC validation of a DNS lookup. - -Source code ------------ - -:: - - #!/usr/bin/python - import os - from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN - - ctx = ub_ctx() - ctx.resolvconf("/etc/resolv.conf") - if (os.path.isfile("keys")): - ctx.add_ta_file("keys") #read public keys for DNSSEC verification - - status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN) - if status == 0 and result.havedata: - - print "Result:", result.data.address_list - - if result.secure: - print "Result is secure" - elif result.bogus: - print "Result is bogus" - else: - print "Result is insecure" - -More detailed information can be seen in libUnbound DNSSEC tutorial `here`_. - -.. _here: http://www.unbound.net/documentation/libunbound-tutorial-6.html diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example5.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example5.rst deleted file mode 100644 index 9262014b..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example5.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _example_resolver_only: - -Resolver only -============= - -This example program shows how to perform DNS resolution only. -Unbound contains two basic modules: resolver and validator. -In case, the validator is not necessary, the validator module can be turned off -using "module-config" option. -This option contains a list of module names separated by the space char. This -list determined which modules should be employed and in what order. - -Source code ------------ - -:: - - #!/usr/bin/python - import os - from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN - - ctx = ub_ctx() - ctx.set_option("module-config:","iterator") - ctx.resolvconf("/etc/resolv.conf") - - status, result = ctx.resolve("www.google.com", RR_TYPE_A, RR_CLASS_IN) - if status == 0 and result.havedata: - - print "Result:", result.data.address_list - -.. note:: - The :meth:`unbound.ub_ctx.set_option` method must be used before the first - resolution (i.e. before :meth:`unbound.ub_ctx.resolve` or - :meth:`unbound.ub_ctx.resolve_async` call). diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6-1.py b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6-1.py deleted file mode 100644 index 0f405448..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6-1.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python -from unbound import ub_ctx,ub_strerror,RR_TYPE_A,RR_CLASS_IN - -ctx = ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:", result.data.address_list -else: - print "No record found" - -#define new local zone -status = ctx.zone_add("xxx.","static") -if (status != 0): print "Error zone_add:",status, ub_strerror(status) - -#add RR to the zone -status = ctx.data_add("test.record.xxx. IN A 1.2.3.4") -if (status != 0): print "Error data_add:",status, ub_strerror(status) - -#lookup for an A record -status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:", result.data.as_address_list() -else: - print "No record found" - diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6.rst deleted file mode 100644 index 6fde8b25..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example6.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _example_localzone: - -Local zone manipulation -======================= - -This example program shows how to define local zone containing custom DNS -records. - -Source code ------------ - -.. literalinclude:: example6-1.py - :language: python diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-1.py b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-1.py deleted file mode 100644 index 802bd1c3..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-1.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -# -# IDN (Internationalized Domain Name) lookup support -# -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve(u"www.háÄ�kyÄ�árky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:" - print " raw data:", result.data - for k in result.data.address_list: - print " address:%s" % k - diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-2.py b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-2.py deleted file mode 100644 index 5a41f8dc..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7-2.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -# -# IDN (Internationalized Domain Name) lookup support (lookup for MX) -# -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve(u"háÄ�kyÄ�árky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:" - print " raw data:", result.data - for k in result.data.mx_list_idn: - print " priority:%d address:%s" % k diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7.rst deleted file mode 100644 index 5fde18e0..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example7.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _example_idna: - -Internationalized domain name support -===================================== - -Unlike the libUnbound, pyUnbound is able to handle IDN queries. - -Automatic IDN DNAME conversion -------------------------------- - -If we use unicode string in :meth:`unbound.ub_ctx.resolve` method, -the IDN DNAME conversion (if it is necessary) is performed on background. - -Source code -........... - -.. literalinclude:: example7-1.py - :language: python - -IDN converted attributes ------------------------- - -The :class:`unbound.ub_data` class contains attributes suffix which converts -the dname to UTF string. These attributes have the ``_idn`` suffix. - -Apart from this approach, two conversion functions exist -(:func:`unbound.idn2dname` and :func:`unbound.dname2idn`). - -Source code -........... - -.. literalinclude:: example7-2.py - :language: python diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8-1.py b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8-1.py deleted file mode 100644 index 79060167..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8-1.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -# -# Lookup for MX and NS records -# -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:" - print " raw data:", result.data - for k in result.data.mx_list: - print " priority:%d address:%s" % k - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:" - print " raw data:", result.data - for k in result.data.address_list: - print " address:%s" % k - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print "Result:" - print " raw data:", result.data - for k in result.data.domain_list: - print " host: %s" % k - diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8.rst deleted file mode 100644 index 16c14047..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/example8.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _example_mxlookup: - -Lookup for MX and NS records -============================ - -The pyUnbound extension provides functions which are able to encode RAW RDATA -produces by unbound resolver (see :class:`unbound.ub_data`). - -Source code ------------ - -.. literalinclude:: example8-1.py - :language: python - -Output ------- - -The previous example produces the following output:: - - Result: - raw data: 00 0F 05 6D 61 69 6C 34 03 6E 69 63 02 63 7A 00;00 14 02 6D 78 05 63 7A 6E 69 63 03 6F 72 67 00;00 0A 04 6D 61 69 6C 03 6E 69 63 02 63 7A 00 - priority:15 address: mail4.nic.cz. - priority:20 address: mx.cznic.org. - priority:10 address: mail.nic.cz. - - Result: - raw data: D9 1F CD 32 - address: 217.31.205.50 - - Result: - raw data: 01 61 02 6E 73 03 6E 69 63 02 63 7A 00;01 65 02 6E 73 03 6E 69 63 02 63 7A 00;01 63 02 6E 73 03 6E 69 63 02 63 7A 00 - host: a.ns.nic.cz. - host: e.ns.nic.cz. - host: c.ns.nic.cz. diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/index.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/examples/index.rst deleted file mode 100644 index 28326165..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/examples/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -Examples -======== - -Here you can find several examples which utilizes the unbound library in Python -environment. Unbound is a caching validator and resolver and can be linked into -an application, as a library where can answer DNS queries for the application. -This set of examples shows how to use the functions from Python environment. - -Tutorials ---------- - -.. toctree:: - :maxdepth: 1 - :glob: - - example* diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/index.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/index.rst deleted file mode 100644 index b42e0526..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -PyUnbound documentation -======================================= - -This project contains an Unbound wrapper providing the thinnest layer over the library possible. -Everything you can do from the libUnbound C API, you can do from Python, even more. - -Contents ----------- -.. toctree:: - :maxdepth: 2 - - intro.rst - install.rst - examples/index.rst - modules/unbound - -Module Documentation ------------------------ - -* Module :mod:`unbound` - -Indices and tables -------------------- - -* :ref:`genindex` -* :ref:`search` - diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/install.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/install.rst deleted file mode 100644 index bb311898..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/install.rst +++ /dev/null @@ -1,38 +0,0 @@ -Installation -============ - -Prerequisites -------------- - -Python 2.4 or higher, SWIG 1.3 or higher, GNU make - -Compiling ---------- - -After downloading, you can compile the pyUnbound library by doing:: - - > tar -xzf unbound-x.x.x-py.tar.gz - > cd unbound-x.x.x - > ./configure --with-pyunbound - > make - -You may want to enable ``--with-pythonmodule`` as well if you want to use -python as a module in the resolver. - -You need ``GNU make`` to compile sources; ``SWIG`` and ``Python devel`` -libraries to compile extension module. - - -Testing -------- - -If the compilation is successful, you can test the python LDNS extension module -by:: - - > cd contrib/python - > make testenv - > ./dns-lookup.py - -You may want to ``make install`` in the main directory since ``make testenv`` -is for debugging. In contrib/examples you can find simple applications written -in Python using the Unbound extension. diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/intro.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/intro.rst deleted file mode 100644 index e490d2c6..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/intro.rst +++ /dev/null @@ -1,58 +0,0 @@ -Introduction -============ - -Unbound -------- - -`Unbound`_ is an implementation of a DNS resolver, that performs caching and -DNSSEC validation. -Together with unbound, the libunbound library is provided. -This library can be used to convert hostnames to ip addresses, and back, as -well as obtain other information. -Since the resolver allows to specify the class and type of a query (A record, -NS, MX, ...), this library offers powerful resolving tool. -The library also performs public-key validation of results with DNSSEC. - -.. _Unbound: http://www.unbound.net/documentation - -pyUnbound ---------- - -The pyUnbound is an extension module for Python which provides an -object-oriented interface to libunbound. -It is the first Python module which offers thread-safe caching resolver. - -The interface was designed with the emphasis on the simplicity of use. -There are two main classes :class:`unbound.ub_ctx` (a validation and resolution -context) and :class:`unbound.ub_result` which contains the validation and -resolution results. -The objects are thread-safe, and a context can be used in non-threaded as well -as threaded environment. -Resolution can be performed blocking and non-blocking (i.e. asynchronous). -The asynchronous method returns from the call immediately, so that processing -can go on, while the results become available later. - -Features --------- - -* Customizable caching validation resolver for synchronous and asynchronous - lookups -* Easy to use object interface -* Easy to integrate extension module -* Designed for thread environment (i.e. thread-safe) -* Allows define and customize of local zone and its RR's during the operation - (i.e. without restart) -* Includes encoding functions to simplify the results retrieval -* Internationalized domain name (`IDN`_) support - -.. _IDN: http://en.wikipedia.org/wiki/Internationalized_domain_name - -Application area ----------------- - -* DNS-based applications performing DNS lookups; the caching resolver can - reduce overhead -* Applications where the validation of DNS records is required -* Great solution for customizable and dynamic DNS-based white/blacklists (spam - rejection, connection rejection, ...) using the dynamic local zone - manipulation diff --git a/crates/libunbound-sys/unbound/libunbound/python/doc/modules/unbound.rst b/crates/libunbound-sys/unbound/libunbound/python/doc/modules/unbound.rst deleted file mode 100644 index 77e4cd1a..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/doc/modules/unbound.rst +++ /dev/null @@ -1,167 +0,0 @@ -Unbound module documentation -================================ - -.. automodule:: unbound - -Class ub_ctx --------------- -.. autoclass:: ub_ctx - :members: - :undoc-members: - - .. automethod:: __init__ - -Class ub_result ----------------------- -.. autoclass:: ub_result - :members: - - .. attribute:: qname - - The original question, name text string. - - .. attribute:: qtype - - The class asked for. - - .. attribute:: canonname - - Canonical name for the result (the final cname). May be empty if no canonical name exists. - - .. attribute:: answer_packet - - The DNS answer packet. Network formatted. Can contain DNSSEC types. - - .. attribute:: havedata - - If there is any data, this property is true. If false, there was no data (nxdomain may be true, rcode can be set). - - .. attribute:: secure - - True, if the result is validated securely. - False, if validation failed or domain queried has no security info. - - It is possible to get a result with no data (havedata is false), - and secure is true. This means that the non-existence of the data - was cryptographically proven (with signatures). - - .. attribute:: bogus - - If the result was not secure (secure==0), and this result is due to a security failure, bogus is true. - This means the data has been actively tampered with, signatures - failed, expected signatures were not present, timestamps on - signatures were out of date and so on. - - If secure==0 and bogus==0, this can happen if the data is not secure - because security is disabled for that domain name. - This means the data is from a domain where data is not signed. - - .. attribute:: nxdomain - - If there was no data, and the domain did not exist, this is true. - If it is false, and there was no data, then the domain name is purported to exist, but the requested data type is not available. - - .. attribute:: rcode - - DNS RCODE for the result. May contain additional error code if there was no data due to an error. - 0 (RCODE_NOERROR) if okay. See predefined `RCODE_` constants. - - RCODE can be represented in display representation form (string) using :attr:`rcode_str` attribute. - -Class ub_data ----------------------- -.. autoclass:: ub_data - :members: - -Functions ----------------------- -.. autofunction:: reverse -.. autofunction:: idn2dname -.. autofunction:: dname2idn - -Predefined constants ------------------------ - -**RCODE** - * RCODE_FORMERR = 1 - * RCODE_NOERROR = 0 - * RCODE_NOTAUTH = 9 - * RCODE_NOTIMPL = 4 - * RCODE_NOTZONE = 10 - * RCODE_NXDOMAIN = 3 - * RCODE_NXRRSET = 8 - * RCODE_REFUSED = 5 - * RCODE_SERVFAIL = 2 - * RCODE_YXDOMAIN = 6 - * RCODE_YXRRSET = 7 - -**RR_CLASS** - * RR_CLASS_ANY = 255 - * RR_CLASS_CH = 3 - * RR_CLASS_HS = 4 - * RR_CLASS_IN = 1 - * RR_CLASS_NONE = 254 - -**RR_TYPE** - * RR_TYPE_A = 1 - * RR_TYPE_A6 = 38 - * RR_TYPE_AAAA = 28 - * RR_TYPE_AFSDB = 18 - * RR_TYPE_ANY = 255 - * RR_TYPE_APL = 42 - * RR_TYPE_ATMA = 34 - * RR_TYPE_AXFR = 252 - * RR_TYPE_CERT = 37 - * RR_TYPE_CNAME = 5 - * RR_TYPE_DHCID = 49 - * RR_TYPE_DLV = 32769 - * RR_TYPE_DNAME = 39 - * RR_TYPE_DNSKEY = 48 - * RR_TYPE_DS = 43 - * RR_TYPE_EID = 31 - * RR_TYPE_GID = 102 - * RR_TYPE_GPOS = 27 - * RR_TYPE_HINFO = 13 - * RR_TYPE_IPSECKEY = 45 - * RR_TYPE_ISDN = 20 - * RR_TYPE_IXFR = 251 - * RR_TYPE_KEY = 25 - * RR_TYPE_KX = 36 - * RR_TYPE_LOC = 29 - * RR_TYPE_MAILA = 254 - * RR_TYPE_MAILB = 253 - * RR_TYPE_MB = 7 - * RR_TYPE_MD = 3 - * RR_TYPE_MF = 4 - * RR_TYPE_MG = 8 - * RR_TYPE_MINFO = 14 - * RR_TYPE_MR = 9 - * RR_TYPE_MX = 15 - * RR_TYPE_NAPTR = 35 - * RR_TYPE_NIMLOC = 32 - * RR_TYPE_NS = 2 - * RR_TYPE_NSAP = 22 - * RR_TYPE_NSAP_PTR = 23 - * RR_TYPE_NSEC = 47 - * RR_TYPE_NSEC3 = 50 - * RR_TYPE_NSEC3PARAMS = 51 - * RR_TYPE_NULL = 10 - * RR_TYPE_NXT = 30 - * RR_TYPE_OPT = 41 - * RR_TYPE_PTR = 12 - * RR_TYPE_PX = 26 - * RR_TYPE_RP = 17 - * RR_TYPE_RRSIG = 46 - * RR_TYPE_RT = 21 - * RR_TYPE_SIG = 24 - * RR_TYPE_SINK = 40 - * RR_TYPE_SOA = 6 - * RR_TYPE_SRV = 33 - * RR_TYPE_SSHFP = 44 - * RR_TYPE_TSIG = 250 - * RR_TYPE_TXT = 16 - * RR_TYPE_UID = 101 - * RR_TYPE_UINFO = 100 - * RR_TYPE_UNSPEC = 103 - * RR_TYPE_WKS = 11 - * RR_TYPE_X25 = 19 diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/async-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/async-lookup.py deleted file mode 100644 index 936be321..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/async-lookup.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/python -''' - async-lookup.py : This example shows how to use asynchronous lookups - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound -import time - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -def call_back(my_data,status,result): - print("Call_back:", sorted(my_data)) - if status == 0 and result.havedata: - print("Result:", sorted(result.data.address_list)) - my_data['done_flag'] = True - - -my_data = {'done_flag':False,'arbitrary':"object"} -status, async_id = ctx.resolve_async("www.nic.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN) - -while (status == 0) and (not my_data['done_flag']): - status = ctx.process() - time.sleep(0.1) - -if (status != 0): - print("Resolve error:", unbound.ub_strerror(status)) diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/dns-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/dns-lookup.py deleted file mode 100644 index a175dfb0..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/dns-lookup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python -''' - dns-lookup.py : This example shows how to resolve IP address - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("www.nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:", sorted(result.data.address_list)) -elif status != 0: - print("Error:", unbound.ub_strerror(status)) diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec-valid.py b/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec-valid.py deleted file mode 100644 index c5517efc..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec-valid.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python -''' - dnssec-valid.py: DNSSEC validation - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import os -from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN - -ctx = ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -fw = open("dnssec-valid.txt","wb") -ctx.debugout(fw) -ctx.debuglevel(2) - -if os.path.isfile("keys"): - ctx.add_ta_file("keys") #read public keys for DNSSEC verification - -status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN) -if status == 0 and result.havedata: - - print("Result:", sorted(result.data.address_list)) - - if result.secure: - print("Result is secure") - elif result.bogus: - print("Result is bogus") - else: - print("Result is insecure") - diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec_test.py b/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec_test.py deleted file mode 100644 index b76c0437..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/dnssec_test.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -from unbound import ub_ctx, RR_TYPE_A, RR_TYPE_RRSIG, RR_TYPE_NSEC, RR_TYPE_NSEC3 -import ldns - -def dnssecParse(domain, rrType=RR_TYPE_A): - print("Resolving domain", domain) - s, r = resolver.resolve(domain) - print("status: %s, secure: %s, rcode: %s, havedata: %s, answer_len; %s" % (s, r.secure, r.rcode_str, r.havedata, r.answer_len)) - - s, pkt = ldns.ldns_wire2pkt(r.packet) - if s != 0: - raise RuntimeError("Error parsing DNS packet") - - rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER) - print("RRSIGs from answer:", sorted(rrsigs)) - - rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_AUTHORITY) - print("RRSIGs from authority:", sorted(rrsigs)) - - nsecs = pkt.rr_list_by_type(RR_TYPE_NSEC, ldns.LDNS_SECTION_AUTHORITY) - print("NSECs:", sorted(nsecs)) - - nsec3s = pkt.rr_list_by_type(RR_TYPE_NSEC3, ldns.LDNS_SECTION_AUTHORITY) - print("NSEC3s:", sorted(nsec3s)) - - print("---") - - -resolver = ub_ctx() -resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5") -resolver.add_ta(". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D") - -dnssecParse("nic.cz") -dnssecParse("nonexistent-domain-blablabla.cz") -dnssecParse("nonexistent-domain-blablabla.root.cz") - diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/example8-1.py b/crates/libunbound-sys/unbound/libunbound/python/examples/example8-1.py deleted file mode 100644 index 723c4060..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/example8-1.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -''' - example8-1.py: Example shows how to lookup for MX and NS records - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.mx_list): - print(" priority:%d address:%s" % k) - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.address_list): - print(" address:%s" % k) - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.domain_list): - print(" host: %s" % k) - diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/idn-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/idn-lookup.py deleted file mode 100644 index f2831506..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/idn-lookup.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -''' - idn-lookup.py: IDN (Internationalized Domain Name) lookup support - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound -import locale - -ctx = unbound.ub_ctx() -ctx.set_option("module-config:","iterator") #We don't need validation -ctx.resolvconf("/etc/resolv.conf") - -#The unicode IDN string is automatically converted (if necessary) -status, result = ctx.resolve(u"www.háÄ�kyÄ�árky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.address_list): - print(" address:%s" % k) - -status, result = ctx.resolve(u"háÄ�kyÄ�árky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.mx_list_idn): - print(" priority:%d address:%s" % k) - -status, result = ctx.resolve(unbound.reverse('217.31.204.66')+'.in-addr.arpa', unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result.data:", result.data) - for k in sorted(result.data.domain_list_idn): - print(" dname:%s" % k) diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/mx-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/mx-lookup.py deleted file mode 100644 index e9394b35..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/mx-lookup.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -''' - mx-lookup.py: Lookup for MX records - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.mx_list): - print(" priority:%d address:%s" % k) - -status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.address_list): - print(" address:%s" % k) diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/ns-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/ns-lookup.py deleted file mode 100644 index 49f56728..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/ns-lookup.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/python -# vim:fileencoding=utf-8 -''' - ns-lookup.py: Example shows how to lookup for NS records - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve("vutbr.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result:") - print(" raw data:", result.data) - for k in sorted(result.data.domain_list): - print(" host: %s" % k) - diff --git a/crates/libunbound-sys/unbound/libunbound/python/examples/reverse-lookup.py b/crates/libunbound-sys/unbound/libunbound/python/examples/reverse-lookup.py deleted file mode 100644 index c9a13fea..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/examples/reverse-lookup.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python -''' - reverse-lookup.py: Example shows how to resolve reverse record - - Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) - Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - - Copyright (c) 2008. All rights reserved. - - This software is open source. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -''' -from __future__ import print_function -import unbound - -ctx = unbound.ub_ctx() -ctx.resolvconf("/etc/resolv.conf") - -status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) -if status == 0 and result.havedata: - print("Result.data:", result.data, sorted(result.data.domain_list)) - diff --git a/crates/libunbound-sys/unbound/libunbound/python/file_py3.i b/crates/libunbound-sys/unbound/libunbound/python/file_py3.i deleted file mode 100644 index 5d8b5a27..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/file_py3.i +++ /dev/null @@ -1,155 +0,0 @@ -/* - * file_py3.i: Typemaps for FILE* for Python 3 - * - * Copyright (c) 2011, Karel Slany (karel.slany AT nic.cz) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -%{ -#include -#include -%} - -%types(FILE *); - -//#define SWIG_FILE3_DEBUG - -/* converts basic file descriptor flags onto a string */ -%fragment("fdfl_to_str", "header") { -const char * -fdfl_to_str(int fdfl) { - - static const char * const file_mode[] = {"w+", "w", "r"}; - - if (fdfl & O_RDWR) { - return file_mode[0]; - } else if (fdfl & O_WRONLY) { - return file_mode[1]; - } else { - return file_mode[2]; - } -} -} - -%fragment("is_obj_file", "header") { -int -is_obj_file(PyObject *obj) { - int fd, fdfl; - if (!PyLong_Check(obj) && /* is not an integer */ - PyObject_HasAttrString(obj, "fileno") && /* has fileno method */ - (PyObject_CallMethod(obj, "flush", NULL) != NULL) && /* flush() succeeded */ - ((fd = PyObject_AsFileDescriptor(obj)) != -1) && /* got file descriptor */ - ((fdfl = fcntl(fd, F_GETFL)) != -1) /* got descriptor flags */ - ) { - return 1; - } - else { - return 0; - } -} -} - -%fragment("obj_to_file","header", fragment="fdfl_to_str,is_obj_file") { -FILE * -obj_to_file(PyObject *obj) { - int fd, fdfl; - FILE *fp; - if (is_obj_file(obj)) { - fd = PyObject_AsFileDescriptor(obj); - fdfl = fcntl(fd, F_GETFL); - fp = fdopen(dup(fd), fdfl_to_str(fdfl)); /* the FILE* must be flushed - and closed after being used */ -#ifdef SWIG_FILE3_DEBUG - fprintf(stderr, "opening fd %d (fl %d \"%s\") as FILE %p\n", - fd, fdfl, fdfl_to_str(fdfl), (void *)fp); -#endif - return fp; - } - return NULL; -} -} - -/* returns -1 if error occurred */ -/* caused magic SWIG Syntax errors when was commented out */ -#if 0 -%fragment("dispose_file", "header") { -int -dispose_file(FILE **fp) { -#ifdef SWIG_FILE3_DEBUG - fprintf(stderr, "flushing FILE %p\n", (void *)fp); -#endif - if (*fp == NULL) { - return 0; - } - if ((fflush(*fp) == 0) && /* flush file */ - (fclose(*fp) == 0)) { /* close file */ - *fp = NULL; - return 0; - } - return -1; -} -} -#endif - -%typemap(arginit, noblock = 1) FILE* { - $1 = NULL; -} - -/* - * added due to ub_ctx_debugout since since it is overloaded: - * takes void* and FILE*. In reality only FILE* but the wrapper - * and the function is declared in such way. - */ -%typemap(typecheck, noblock = 1, fragment = "is_obj_file", precedence = SWIG_TYPECHECK_POINTER) FILE* { - $1 = is_obj_file($input); -} - -%typemap(check, noblock = 1) FILE* { - if ($1 == NULL) { - /* The generated wrapper function raises TypeError on mismatching types. */ - SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument " - "$argnum"" of type '" "$type""'"); - } -} - -%typemap(in, noblock = 1, fragment = "obj_to_file") FILE* { - $1 = obj_to_file($input); -} - -/* - * Commented out due the way how ub_ctx_debugout() uses the parameter. - * This typemap would cause the FILE* to be closed after return from - * the function. This caused Python interpreter to crash, since the - * function just stores the FILE* internally in ctx and use it for - * logging. So we'll leave the closing of the file on the OS. - */ -/*%typemap(freearg, noblock = 1, fragment = "dispose_file") FILE* { - if (dispose_file(&$1) == -1) { - SWIG_exception_fail(SWIG_IOError, "closing file in method '" "$symname" "', argument " - "$argnum"" of type '" "$type""'"); - } -}*/ diff --git a/crates/libunbound-sys/unbound/libunbound/python/libunbound.i b/crates/libunbound-sys/unbound/libunbound/python/libunbound.i deleted file mode 100644 index 0cdb3d7e..00000000 --- a/crates/libunbound-sys/unbound/libunbound/python/libunbound.i +++ /dev/null @@ -1,982 +0,0 @@ -/* - * libunbound.i: pyUnbound module (libunbound wrapper for Python) - * - * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) - * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -%begin %{ -/* store state of warning output, restored at later pop */ -#pragma GCC diagnostic push -/* ignore warnings for pragma below, where for older GCC it can produce a - warning if the cast-function-type warning is absent. */ -#pragma GCC diagnostic ignored "-Wpragmas" -/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */ -#pragma GCC diagnostic ignored "-Wcast-function-type" -%} -%module unbound -%{ -/* restore state of warning output, remove the functioncast ignore */ -#pragma GCC diagnostic pop - #include - #ifdef HAVE_SYS_SOCKET_H - #include - #endif - #ifdef HAVE_NETINET_IN_H - #include - #endif - #ifdef HAVE_ARPA_INET_H - #include - #endif - #include "libunbound/unbound.h" -%} - -%pythoncode %{ - import encodings.idna - try: - import builtins - except ImportError: - import __builtin__ as builtins - - # Ensure compatibility with older python versions - if 'bytes' not in vars(): - bytes = str - - def ord(s): - if isinstance(s, int): - return s - return builtins.ord(s) -%} - -//%include "doc.i" -#if PY_MAJOR_VERSION >= 3 -%include "file_py3.i" // python 3 FILE * -#else -%include "file.i" -#endif - -%feature("docstring") strerror "Convert error value to a human readable string." - -// ================================================================================ -// ub_resolve - perform resolution and validation -// ================================================================================ -%typemap(in,numinputs=0,noblock=1) (struct ub_result** result) -{ - struct ub_result* newubr; - $1 = &newubr; -} - -/* result generation */ -%typemap(argout,noblock=1) (struct ub_result** result) -{ - if(1) { /* new code block for variable on stack */ - PyObject* tuple; - tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, $result); - if (result == 0) { - PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(newubr), SWIGTYPE_p_ub_result, SWIG_POINTER_OWN | 0 )); - } else { - PyTuple_SetItem(tuple, 1, Py_None); - } - $result = tuple; - } -} - - -// ================================================================================ -// ub_ctx - validation context -// ================================================================================ -%nodefaultctor ub_ctx; //no default constructor & destructor -%nodefaultdtor ub_ctx; - -%newobject ub_ctx_create; -%delobject ub_ctx_delete; -%rename(_ub_ctx_delete) ub_ctx_delete; - -%newobject ub_resolve; - -%inline %{ - void ub_ctx_free_dbg (struct ub_ctx* c) { - printf("******** UB_CTX free 0x%p ************\n", c); - ub_ctx_delete(c); - } - - //RR types - enum enum_rr_type - { - /** a host address */ - RR_TYPE_A = 1, - /** an authoritative name server */ - RR_TYPE_NS = 2, - /** a mail destination (Obsolete - use MX) */ - RR_TYPE_MD = 3, - /** a mail forwarder (Obsolete - use MX) */ - RR_TYPE_MF = 4, - /** the canonical name for an alias */ - RR_TYPE_CNAME = 5, - /** marks the start of a zone of authority */ - RR_TYPE_SOA = 6, - /** a mailbox domain name (EXPERIMENTAL) */ - RR_TYPE_MB = 7, - /** a mail group member (EXPERIMENTAL) */ - RR_TYPE_MG = 8, - /** a mail rename domain name (EXPERIMENTAL) */ - RR_TYPE_MR = 9, - /** a null RR (EXPERIMENTAL) */ - RR_TYPE_NULL = 10, - /** a well known service description */ - RR_TYPE_WKS = 11, - /** a domain name pointer */ - RR_TYPE_PTR = 12, - /** host information */ - RR_TYPE_HINFO = 13, - /** mailbox or mail list information */ - RR_TYPE_MINFO = 14, - /** mail exchange */ - RR_TYPE_MX = 15, - /** text strings */ - RR_TYPE_TXT = 16, - /** RFC1183 */ - RR_TYPE_RP = 17, - /** RFC1183 */ - RR_TYPE_AFSDB = 18, - /** RFC1183 */ - RR_TYPE_X25 = 19, - /** RFC1183 */ - RR_TYPE_ISDN = 20, - /** RFC1183 */ - RR_TYPE_RT = 21, - /** RFC1706 */ - RR_TYPE_NSAP = 22, - /** RFC1348 */ - RR_TYPE_NSAP_PTR = 23, - /** 2535typecode */ - RR_TYPE_SIG = 24, - /** 2535typecode */ - RR_TYPE_KEY = 25, - /** RFC2163 */ - RR_TYPE_PX = 26, - /** RFC1712 */ - RR_TYPE_GPOS = 27, - /** ipv6 address */ - RR_TYPE_AAAA = 28, - /** LOC record RFC1876 */ - RR_TYPE_LOC = 29, - /** 2535typecode */ - RR_TYPE_NXT = 30, - /** draft-ietf-nimrod-dns-01.txt */ - RR_TYPE_EID = 31, - /** draft-ietf-nimrod-dns-01.txt */ - RR_TYPE_NIMLOC = 32, - /** SRV record RFC2782 */ - RR_TYPE_SRV = 33, - /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */ - RR_TYPE_ATMA = 34, - /** RFC2915 */ - RR_TYPE_NAPTR = 35, - /** RFC2230 */ - RR_TYPE_KX = 36, - /** RFC2538 */ - RR_TYPE_CERT = 37, - /** RFC2874 */ - RR_TYPE_A6 = 38, - /** RFC2672 */ - RR_TYPE_DNAME = 39, - /** dnsind-kitchen-sink-02.txt */ - RR_TYPE_SINK = 40, - /** Pseudo OPT record... */ - RR_TYPE_OPT = 41, - /** RFC3123 */ - RR_TYPE_APL = 42, - /** draft-ietf-dnsext-delegation */ - RR_TYPE_DS = 43, - /** SSH Key Fingerprint */ - RR_TYPE_SSHFP = 44, - /** draft-richardson-ipseckey-rr-11.txt */ - RR_TYPE_IPSECKEY = 45, - /** draft-ietf-dnsext-dnssec-25 */ - RR_TYPE_RRSIG = 46, - RR_TYPE_NSEC = 47, - RR_TYPE_DNSKEY = 48, - RR_TYPE_DHCID = 49, - - RR_TYPE_NSEC3 = 50, - RR_TYPE_NSEC3PARAMS = 51, - - RR_TYPE_UINFO = 100, - RR_TYPE_UID = 101, - RR_TYPE_GID = 102, - RR_TYPE_UNSPEC = 103, - - RR_TYPE_TSIG = 250, - RR_TYPE_IXFR = 251, - RR_TYPE_AXFR = 252, - /** A request for mailbox-related records (MB, MG or MR) */ - RR_TYPE_MAILB = 253, - /** A request for mail agent RRs (Obsolete - see MX) */ - RR_TYPE_MAILA = 254, - /** any type (wildcard) */ - RR_TYPE_ANY = 255, - RR_TYPE_CAA = 257, - - /* RFC 4431, 5074, DNSSEC Lookaside Validation */ - RR_TYPE_DLV = 32769, - }; - - // RR classes - enum enum_rr_class - { - /** the Internet */ - RR_CLASS_IN = 1, - /** Chaos class */ - RR_CLASS_CH = 3, - /** Hesiod (Dyer 87) */ - RR_CLASS_HS = 4, - /** None class, dynamic update */ - RR_CLASS_NONE = 254, - /** Any class */ - RR_CLASS_ANY = 255, - }; -%} - -%feature("docstring") ub_ctx "Unbound resolving and validation context. - -The validation context is created to hold the resolver status, validation keys and a small cache (containing messages, rrsets, roundtrip times, trusted keys, lameness information). - -**Usage** - ->>> import unbound ->>> ctx = unbound.ub_ctx() ->>> ctx.resolvconf(\"/etc/resolv.conf\") ->>> status, result = ctx.resolve(\"www.google.com\", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) ->>> if status==0 and result.havedata: ->>> print \"Result:\",result.data.address_list -Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104'] -" - -%extend ub_ctx -{ - %pythoncode %{ - def __init__(self): - """Creates a resolving and validation context. - - An exception is invoked if the process of creation an ub_ctx instance fails. - """ - self.this = _unbound.ub_ctx_create() - if not self.this: - raise Exception("Fatal error: unbound context initialization failed") - - #__swig_destroy__ = _unbound.ub_ctx_free_dbg - __swig_destroy__ = _unbound._ub_ctx_delete - - #UB_CTX_METHODS_# - def add_ta(self,ta): - """Add a trust anchor to the given context. - - The trust anchor is a string, on one line, that holds a valid DNSKEY or DS RR. - - :param ta: - string, with zone-format RR on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_add_ta(self,ta) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def add_ta_file(self,fname): - """Add trust anchors to the given context. - - Pass name of a file with DS and DNSKEY records (like from dig or drill). - - :param fname: - filename of file with keyfile with trust anchors. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_add_ta_file(self,fname) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def config(self,fname): - """setup configuration for the given context. - - :param fname: - unbound config file (not all settings applicable). This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_config(self,fname) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def debuglevel(self,d): - """Set debug verbosity for the context Output is directed to stderr. - - :param d: - debug level, 0 is off, 1 is very minimal, 2 is detailed, and 3 is lots. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_debuglevel(self,d) - #parameters: struct ub_ctx *,int, - #retvals: int - - def debugout(self,out): - """Set debug output (and error output) to the specified stream. - - Pass None to disable. Default is stderr. - - :param out: - File stream to log to. - :returns: (int) 0 if OK, else error. - - **Usage:** - - In order to log into file, use - - :: - - ctx = unbound.ub_ctx() - fw = fopen("debug.log") - ctx.debuglevel(3) - ctx.debugout(fw) - - Another option is to print the debug information to stderr output - - :: - - ctx = unbound.ub_ctx() - ctx.debuglevel(10) - ctx.debugout(sys.stderr) - """ - return _unbound.ub_ctx_debugout(self,out) - #parameters: struct ub_ctx *,void *, - #retvals: int - - def hosts(self,fname="/etc/hosts"): - """Read list of hosts from the filename given. - - Usually "/etc/hosts". These addresses are not flagged as DNSSEC secure when queried for. - - :param fname: - file name string. If None "/etc/hosts" is used. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_hosts(self,fname) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def print_local_zones(self): - """Print the local zones and their content (RR data) to the debug output. - - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_print_local_zones(self) - #parameters: struct ub_ctx *, - #retvals: int - - def resolvconf(self,fname="/etc/resolv.conf"): - """Read list of nameservers to use from the filename given. - - Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. If they do not support DNSSEC, validation may fail. - - Only nameservers are picked up, the searchdomain, ndots and other settings from resolv.conf(5) are ignored. - - :param fname: - file name string. If None "/etc/resolv.conf" is used. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_resolvconf(self,fname) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def set_async(self,dothread): - """Set a context behaviour for asynchronous action. - - :param dothread: - if True, enables threading and a call to :meth:`resolve_async` creates a thread to handle work in the background. - If False, a process is forked to handle work in the background. - Changes to this setting after :meth:`async` calls have been made have no effect (delete and re-create the context to change). - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_async(self,dothread) - #parameters: struct ub_ctx *,int, - #retvals: int - - def set_fwd(self,addr): - """Set machine to forward DNS queries to, the caching resolver to use. - - IP4 or IP6 address. Forwards all DNS requests to that machine, which is expected to run a recursive resolver. If the is not DNSSEC-capable, validation may fail. Can be called several times, in that case the addresses are used as backup servers. - - To read the list of nameservers from /etc/resolv.conf (from DHCP or so), use the call :meth:`resolvconf`. - - :param addr: - address, IP4 or IP6 in string format. If the addr is None, forwarding is disabled. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_set_fwd(self,addr) - #parameters: struct ub_ctx *,char *, - #retvals: int - - def set_option(self,opt,val): - """Set an option for the context. - - Changes to the options after :meth:`resolve`, :meth:`resolve_async`, :meth:`zone_add`, :meth:`zone_remove`, :meth:`data_add` or :meth:`data_remove` have no effect (you have to delete and re-create the context). - - :param opt: - option name from the unbound.conf config file format. (not all settings applicable). The name includes the trailing ':' for example set_option("logfile:", "mylog.txt"); This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist. - :param val: - value of the option. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_set_option(self,opt,val) - #parameters: struct ub_ctx *,char *,char *, - #retvals: int - - def trustedkeys(self,fname): - """Add trust anchors to the given context. - - Pass the name of a bind-style config file with trusted-keys{}. - - :param fname: - filename of file with bind-style config entries with trust anchors. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_trustedkeys(self,fname) - #parameters: struct ub_ctx *,char *, - #retvals: int - #_UB_CTX_METHODS# - - def zone_print(self): - """Print local zones using debugout""" - _unbound.ub_ctx_print_local_zones(self) - - def zone_add(self,zonename,zonetype): - """Add new local zone - - :param zonename: zone domain name (e.g. myzone.) - :param zonetype: type of the zone ("static",...) - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_zone_add(self,zonename, zonetype) - #parameters: struct ub_ctx *,char*, char* - #retvals: int - - def zone_remove(self,zonename): - """Remove local zone - - If exists, removes local zone with all the RRs. - - :param zonename: zone domain name - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_zone_remove(self,zonename) - #parameters: struct ub_ctx *,char* - #retvals: int - - def data_add(self,rrdata): - """Add new local RR data - - :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] - :returns: (int) 0 if OK, else error. - - **Usage** - The local data ... - - :: - - >>> ctx = unbound.ub_ctx() - >>> ctx.zone_add("mydomain.net.","static") - 0 - >>> status = ctx.data_add("test.mydomain.net. IN A 192.168.1.1") - 0 - >>> status, result = ctx.resolve("test.mydomain.net") - >>> if status==0 and result.havedata: - >>> print \"Result:\",result.data.address_list - Result: ['192.168.1.1'] - - """ - return _unbound.ub_ctx_data_add(self,rrdata) - #parameters: struct ub_ctx *,char* - #retvals: int - - def data_remove(self,rrdata): - """Remove local RR data - - If exists, remove resource record from local zone - - :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_ctx_data_remove(self,rrdata) - #parameters: struct ub_ctx *,char* - #retvals: int - - #UB_METHODS_# - def cancel(self,async_id): - """Cancel an async query in progress. - - Its callback will not be called. - - :param async_id: - which query to cancel. - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_cancel(self,async_id) - #parameters: struct ub_ctx *,int, - #retvals: int - - def get_fd(self): - """Get file descriptor. - - Wait for it to become readable, at this point answers are returned from the asynchronous validating resolver. Then call the ub_process to continue processing. This routine works immediately after context creation, the fd does not change. - - :returns: (int) -1 on error, or file descriptor to use select(2) with. - """ - return _unbound.ub_fd(self) - #parameters: struct ub_ctx *, - #retvals: int - - def poll(self): - """Poll a context to see if it has any new results Do not poll in a loop, instead extract the fd below to poll for readiness, and then check, or wait using the wait routine. - - :returns: (int) 0 if nothing to read, or nonzero if a result is available. If nonzero, call ctx_process() to do callbacks. - """ - return _unbound.ub_poll(self) - #parameters: struct ub_ctx *, - #retvals: int - - def process(self): - """Call this routine to continue processing results from the validating resolver (when the fd becomes readable). - - Will perform necessary callbacks. - - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_process(self) - #parameters: struct ub_ctx *, - #retvals: int - - def resolve(self,name,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN): - """Perform resolution and validation of the target name. - - :param name: - domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string. - :param rrtype: - type of RR in host order (optional argument). Default value is RR_TYPE_A (A class). - :param rrclass: - class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet). - :returns: * (int) 0 if OK, else error. - * (:class:`ub_result`) the result data is returned in a newly allocated result structure. May be None on return, return value is set to an error in that case (out of memory). - """ - if isinstance(name, bytes): #probably IDN - return _unbound.ub_resolve(self,name,rrtype,rrclass) - else: - return _unbound.ub_resolve(self,idn2dname(name),rrtype,rrclass) - #parameters: struct ub_ctx *,char *,int,int, - #retvals: int,struct ub_result ** - - def resolve_async(self,name,mydata,callback,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN): - """Perform resolution and validation of the target name. - - Asynchronous, after a while, the callback will be called with your data and the result. - If an error happens during processing, your callback will be called with error set to a nonzero value (and result==None). - - :param name: - domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string. - :param mydata: - this data is your own data (you can pass arbitrary python object or None) which are passed on to the callback function. - :param callback: - call-back function which is called on completion of the resolution. - :param rrtype: - type of RR in host order (optional argument). Default value is RR_TYPE_A (A class). - :param rrclass: - class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet). - :returns: * (int) 0 if OK, else error. - * (int) async_id, an identifier number is returned for the query as it is in progress. It can be used to cancel the query. - - **Call-back function:** - The call-back function looks as the follows:: - - def call_back(mydata, status, result): - pass - - **Parameters:** - * `mydata` - mydata object - * `status` - 0 when a result has been found - * `result` - the result structure. The result may be None, in that case err is set. - - """ - if isinstance(name, bytes): #probably IDN - return _unbound._ub_resolve_async(self,name,rrtype,rrclass,mydata,callback) - else: - return _unbound._ub_resolve_async(self,idn2dname(name),rrtype,rrclass,mydata,callback) - #parameters: struct ub_ctx *,char *,int,int,void *,ub_callback_t, - #retvals: int, int - - def wait(self): - """Wait for a context to finish with results. - - Calls after the wait for you. After the wait, there are no more outstanding asynchronous queries. - - :returns: (int) 0 if OK, else error. - """ - return _unbound.ub_wait(self) - #parameters: struct ub_ctx *, - #retvals: int - - #_UB_METHODS# - %} -} - - -// ================================================================================ -// ub_result - validation and resolution results -// ================================================================================ -%nodefaultctor ub_result; //no default constructor & destructor -%nodefaultdtor ub_result; - -%delobject ub_resolve_free; -%rename(_ub_resolve_free) ub_resolve_free; - -%inline %{ - void ub_resolve_free_dbg (struct ub_result* r) { - printf("******** UB_RESOLVE free 0x%p ************\n", r); - ub_resolve_free(r); - } -%} - -%feature("docstring") ub_result "The validation and resolution results." - -//ub_result.rcode -%inline %{ - enum result_enum_rcode { - RCODE_NOERROR = 0, - RCODE_FORMERR = 1, - RCODE_SERVFAIL = 2, - RCODE_NXDOMAIN = 3, - RCODE_NOTIMPL = 4, - RCODE_REFUSED = 5, - RCODE_YXDOMAIN = 6, - RCODE_YXRRSET = 7, - RCODE_NXRRSET = 8, - RCODE_NOTAUTH = 9, - RCODE_NOTZONE = 10 - }; -%} - -%pythoncode %{ - class ub_data: - """Class which makes the resolution results accessible""" - def __init__(self, data): - """Creates ub_data class - :param data: a list of the result data in RAW format - """ - if data == None: - raise Exception("ub_data init: No data") - self.data = data - - def __str__(self): - """Represents data as string""" - return ';'.join([' '.join(map(lambda x:"%02X" % ord(x),a)) for a in self.data]) - - @staticmethod - def dname2str(s, ofs=0, maxlen=0): - """Parses DNAME and produces a list of labels - - :param ofs: where the conversion should start to parse data - :param maxlen: maximum length (0 means parse to the end) - :returns: list of labels (string) - """ - if not s: - return [] - - res = [] - slen = len(s) - if maxlen > 0: - slen = min(slen, maxlen) - - idx = ofs - while (idx < slen): - complen = ord(s[idx]) - # In python 3.x `str()` converts the string to unicode which is the expected text string type - res.append(str(s[idx+1:idx+1+complen].decode())) - idx += complen + 1 - - return res - - def as_raw_data(self): - """Returns a list of RAW strings""" - return self.data - - raw = property(as_raw_data, doc="Returns RAW data (a list of binary encoded strings). See :meth:`as_raw_data`") - - def as_mx_list(self): - """Represents data as a list of MX records (query for RR_TYPE_MX) - - :returns: list of tuples (priority, dname) - """ - return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([a for a in self.dname2str(rdf,2)])) for rdf in self.data] - - mx_list = property(as_mx_list, doc="Returns a list of tuples containing priority and domain names. See :meth:`as_mx_list`") - - def as_idn_mx_list(self): - """Represents data as a list of MX records (query for RR_TYPE_MX) - - :returns: list of tuples (priority, unicode dname) - """ - return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(rdf,2)])) for rdf in self.data] - - mx_list_idn = property(as_idn_mx_list, doc="Returns a list of tuples containing priority and IDN domain names. See :meth:`as_idn_mx_list`") - - def as_address_list(self): - """Represents data as a list of IP addresses (query for RR_TYPE_PTR) - - :returns: list of strings - """ - return ['.'.join(map(lambda x:str(ord(x)),a)) for a in self.data] - - address_list = property(as_address_list, doc="Returns a list of IP addresses. See :meth:`as_address_list`") - - def as_domain_list(self): - """Represents data as a list of domain names (query for RR_TYPE_A) - - :returns: list of strings - """ - return map(lambda x:'.'.join(self.dname2str(x)), self.data) - - domain_list = property(as_domain_list, doc="Returns a list of domain names. See :meth:`as_domain_list`") - - def as_idn_domain_list(self): - """Represents data as a list of unicode domain names (query for RR_TYPE_A) - - :returns: list of strings - """ - return map(lambda x: '.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(x)]), self.data) - - domain_list_idn = property(as_idn_domain_list, doc="Returns a list of IDN domain names. See :meth:`as_idn_domain_list`") -%} - -%extend ub_result -{ - - %rename(_data) data; - - PyObject* _ub_result_data(struct ub_result* result) { - PyObject *list; - int i,cnt; - (void)self; - if ((result == 0) || (!result->havedata) || (result->data == 0)) - return Py_None; - - for (cnt=0,i=0;;i++,cnt++) - if (result->data[i] == 0) - break; - - list = PyList_New(cnt); - for (i=0;idata[i],result->len[i])); - - return list; - } - - PyObject* _packet() { - return PyBytes_FromStringAndSize($self->answer_packet, $self->answer_len); - } - - %pythoncode %{ - def __init__(self): - raise Exception("This class can't be created directly.") - - #__swig_destroy__ = _unbound.ub_resolve_free_dbg - __swig_destroy__ = _unbound._ub_resolve_free - - #havedata = property(_unbound.ub_result_havedata_get, _unbound.ub_result_havedata_set, "Havedata property") - - rcode2str = {RCODE_NOERROR:'no error', RCODE_FORMERR:'form error', RCODE_SERVFAIL:'serv fail', RCODE_NXDOMAIN:'nx domain', RCODE_NOTIMPL:'not implemented', RCODE_REFUSED:'refused', RCODE_YXDOMAIN:'yxdomain', RCODE_YXRRSET:'yxrrset', RCODE_NXRRSET:'nxrrset', RCODE_NOTAUTH:'not auth', RCODE_NOTZONE:'not zone'} - - def _get_rcode_str(self): - """Returns rcode in display representation form - - :returns: string - """ - return self.rcode2str[self.rcode] - - rcode_str = property(_get_rcode_str) - - def _get_raw_data(self): - """Result data, a list of network order DNS rdata items. - - Data are represented as a list of strings. To decode RAW data to the list of IP addresses use :attr:`data` attribute which returns an :class:`ub_data` instance containing conversion function. - """ - return self._ub_result_data(self) - - rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.") - - def _get_data(self): - if not self.havedata: return None - return ub_data(self._ub_result_data(self)) - - packet = property(_packet) - data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None") - -%} - -} - -%exception ub_resolve -%{ - //printf("resolve_start(%lX)\n",(long unsigned int)arg1); - Py_BEGIN_ALLOW_THREADS - $function - Py_END_ALLOW_THREADS - //printf("resolve_stop()\n"); -%} - -%include "libunbound/unbound.h" - -%inline %{ - //SWIG will see the ub_ctx as a class - struct ub_ctx { - }; -%} - -//ub_ctx_debugout void* parameter correction -int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out); - -// ================================================================================ -// ub_resolve_async - perform asynchronous resolution and validation -// ================================================================================ - -%typemap(in,numinputs=0,noblock=1) (int* async_id) -{ - int asyncid = -1; - $1 = &asyncid; -} - -%apply PyObject* {void* mydata} - -/* result generation */ -%typemap(argout,noblock=1) (int* async_id) -{ - if(1) { /* new code block for variable on stack */ - PyObject* tuple; - tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, $result); - PyTuple_SetItem(tuple, 1, SWIG_From_int(asyncid)); - $result = tuple; - } -} - -// Grab a Python function object as a Python object. -%typemap(in) (PyObject *pyfunc) { - if (!PyCallable_Check($input)) - { - PyErr_SetString(PyExc_TypeError, "Need a callable object!"); - return NULL; - } - $1 = $input; -} - -// Python callback workaround -int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, void* mydata, PyObject *pyfunc, int* async_id); - -%{ - struct cb_data { - PyObject* data; - PyObject* func; - }; - - static void PythonCallBack(void* iddata, int status, struct ub_result* result) - { - PyObject *arglist; - PyObject *fresult; - struct cb_data* id; - id = (struct cb_data*) iddata; - arglist = Py_BuildValue("(OiO)",id->data,status, SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_result, 0 | 0 )); // Build argument list -#if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) - /* for python before 3.9 */ - fresult = PyEval_CallObject(id->func,arglist); // Call Python -#else - /* for python 3.9 and newer */ - fresult = PyObject_Call(id->func,arglist,NULL); -#endif - Py_DECREF(id->func); - Py_DECREF(id->data); - free(id); - ub_resolve_free(result); //free ub_result - //ub_resolve_free_dbg(result); //free ub_result - Py_DECREF(arglist); // Trash arglist - Py_XDECREF(fresult); - } - - int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, PyObject* mydata, PyObject *pyfunc, int* async_id) { - int r; - struct cb_data* id; - id = (struct cb_data*) malloc(sizeof(struct cb_data)); - if(!id) - return -2; /* UB_NOMEM */ - id->data = mydata; - id->func = pyfunc; - - r = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id); - Py_INCREF(mydata); - Py_INCREF(pyfunc); - return r; - } - -%} - -%pythoncode %{ - ub_resolve_async = _unbound._ub_resolve_async - - def reverse(domain): - """Reverse domain name - - Usable for reverse lookups when the IP address should be reversed - """ - return '.'.join([a for a in domain.split(".")][::-1]) - - def idn2dname(idnname): - """Converts domain name in IDN format to canonic domain name - - :param idnname: (unicode string) IDN name - :returns: (string) domain name - """ - return '.'.join([encodings.idna.ToASCII(a) if a else '' for a in idnname.split('.')]) - - def dname2idn(name): - """Converts canonic domain name in IDN format to unicode string - - :param name: (string) domain name - :returns: (unicode string) domain name - """ - return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')]) - -%} - diff --git a/crates/libunbound-sys/unbound/libunbound/ubsyms.def b/crates/libunbound-sys/unbound/libunbound/ubsyms.def deleted file mode 100644 index 0ace984f..00000000 --- a/crates/libunbound-sys/unbound/libunbound/ubsyms.def +++ /dev/null @@ -1,36 +0,0 @@ -ub_cancel -ub_ctx_add_ta -ub_ctx_add_ta_autr -ub_ctx_add_ta_file -ub_ctx_async -ub_ctx_config -ub_ctx_create -ub_ctx_create_event -ub_ctx_create_ub_event -ub_ctx_data_add -ub_ctx_data_remove -ub_ctx_debuglevel -ub_ctx_debugout -ub_ctx_delete -ub_ctx_get_option -ub_ctx_hosts -ub_ctx_print_local_zones -ub_ctx_resolvconf -ub_ctx_set_event -ub_ctx_set_fwd -ub_ctx_set_option -ub_ctx_set_stub -ub_ctx_set_tls -ub_ctx_trustedkeys -ub_ctx_zone_add -ub_ctx_zone_remove -ub_fd -ub_poll -ub_process -ub_resolve -ub_resolve_async -ub_resolve_event -ub_resolve_free -ub_strerror -ub_version -ub_wait diff --git a/crates/libunbound-sys/unbound/libunbound/unbound-event.h b/crates/libunbound-sys/unbound/libunbound/unbound-event.h deleted file mode 100644 index 5ca81908..00000000 --- a/crates/libunbound-sys/unbound/libunbound/unbound-event.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * unbound-event.h - unbound validating resolver public API with events - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the unbound interface for use with user defined - * pluggable event bases. - * - * Use ub_ctx_create_event_ub_base() to create an unbound context that uses - * the user provided event base API. Then, use the ub_resolve_event call - * to add DNS resolve queries to the context. Those then run with the - * provided event_base, and when they are done you get a function callback. - * - * This method does not fork another process or create a thread, the effort - * is done by the unbound state machines that are connected to the event base. - * - * It is also possible to provide a libevent based event base by using - * ub_ctx_create_event_base(). But you have to use the same libevent that - * unbound was compiled with, otherwise it wouldn't work, the event and - * event_base structures would be different. - */ -#ifndef UB_UNBOUND_EVENT_H -#define UB_UNBOUND_EVENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct ub_ctx; -struct ub_result; -struct event_base; - -/** event timeout */ -#define UB_EV_TIMEOUT 0x01 -/** event fd readable */ -#define UB_EV_READ 0x02 -/** event fd writable */ -#define UB_EV_WRITE 0x04 -/** event signal */ -#define UB_EV_SIGNAL 0x08 -/** event must persist */ -#define UB_EV_PERSIST 0x10 - -/** magic number to identify this version of the pluggable event api */ -#define UB_EVENT_MAGIC 0x44d74d78 - -struct ub_event; -struct ub_event_base; -struct timeval; - -/** - * The Virtual Method Table for and ub_event_base "object" - */ -struct ub_event_base_vmt { - /** Destructor for the ub_event_base object, - * (not called by libunbound) */ - void (*free)(struct ub_event_base*); - /** Run the event loop - * (not called by libunbound when using ub_resolve_event) */ - int (*dispatch)(struct ub_event_base*); - /** Exit the given event loop */ - int (*loopexit)(struct ub_event_base*, struct timeval*); - /** Instantiate a new ub_event associated with this event base */ - struct ub_event* (*new_event)(struct ub_event_base*, - int fd, short bits, void (*cb)(int, short, void*), void* arg); - /** Instantiate a new signal associated with this event base, - * (not called by libunbound) */ - struct ub_event* (*new_signal)(struct ub_event_base*, int fd, - void (*cb)(int, short, void*), void* arg); - /** Create a new ub_event associated with the given wsaevent, - * (not called by libunbound) */ - struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*, - void* wsaevent, void (*cb)(int, short, void*), void* arg); -}; - -/** - * A user defined pluggable event base is registered by providing a - * ub_event_base "object" with the ub_ctx_create_ub_event() function. - * The magic number must be correct and the Virtual Method Table must be - * fully equipped providing the event base API to be used by libunbound. - */ -struct ub_event_base { - /** magic must be UB_EVENT_MAGIC (0x44d74d78) */ - unsigned long magic; - /** Virtual Method Table for ub_event_base */ - struct ub_event_base_vmt* vmt; -}; - -/** - * The Virtual Method Table for and ub_event "object" - */ -struct ub_event_vmt { - /** Add event bits for this event to fire on. - * The event will be deactivated before this function is called. */ - void (*add_bits)(struct ub_event*, short); - /** Configure the event so it will not longer fire on given bits - * The event will be deactivated before this function is called. */ - void (*del_bits)(struct ub_event*, short); - /** Change or set the file descriptor on the event - * The event will be deactivated before this function is called. */ - void (*set_fd)(struct ub_event*, int); - /** Destructor for the ub_event object */ - void (*free)(struct ub_event*); - /** Activate the event. The given timeval is an timeout value. */ - int (*add)(struct ub_event*, struct timeval*); - /** Deactivate the event */ - int (*del)(struct ub_event*); - /** Reconfigure and activate a timeout event */ - int (*add_timer)(struct ub_event*, struct ub_event_base*, - void (*cb)(int, short, void*), void* arg, struct timeval*); - /** Deactivate the timeout event */ - int (*del_timer)(struct ub_event*); - /** Activate a signal event (not called by libunbound). */ - int (*add_signal)(struct ub_event*, struct timeval*); - /** Deactivate a signal event (not called by libunbound). */ - int (*del_signal)(struct ub_event*); - /** Destructor for a ub_event associated with a wsaevent, - * (not called by libunbound) - */ - void (*winsock_unregister_wsaevent)(struct ub_event* ev); - /** Libunbound will signal the eventloop when a TCP windows socket - * will block on next read or write (given by the eventbits), to work - * around edge trigger event behaviour of select on windows with TCP. - */ - void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit); -}; - -/** - * An "object" comprising a user defined pluggable event. - * The magic number must be correct and the Virtual Method Table must be - * fully equipped providing the ub_event API to be used by libunbound. - */ -struct ub_event { - /** magic must be UB_EVENT_MAGIC (0x44d74d78) */ - unsigned long magic; - /** Virtual Method Table for ub_event */ - struct ub_event_vmt* vmt; -}; - -typedef void (*ub_event_callback_type)(void*, int, void*, int, int, char*, int); - -/** - * Create a resolving and validation context. - * The information from /etc/resolv.conf and /etc/hosts is not utilised by - * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - * @param base: the pluggable event base that the caller has created. - * The unbound context uses this event base. - * @return a new context. default initialisation. - * returns NULL on error. - * You must use ub_resolve_event with this context. - * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done - * with the event_base. Setup the options you like with the other functions. - */ -struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base); - -/** - * Create a resolving and validation context. - * The information from /etc/resolv.conf and /etc/hosts is not utilised by - * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - * You have to use the same libevent that unbound was compiled with, - * otherwise it wouldn't work, the event and event_base structures would - * be different. - * @param base: the event base that the caller has created. The unbound - * context uses this event base. - * @return a new context. default initialisation. - * returns NULL on error. - * You must use ub_resolve_event with this context. - * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done - * with the event_base. Setup the options you like with the other functions. - */ -struct ub_ctx* ub_ctx_create_event(struct event_base* base); - -/** - * Set a new libevent event_base on a context created with ub_ctx_create_event. - * You have to use the same libevent that unbound was compiled with, - * otherwise it wouldn't work, the event and event_base structures would - * be different. - * Any outbound queries will be canceled. - * @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event - * @param base the new event_base to attach to the ctx - * @return 0 if OK, else error - */ -int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base); - -/** - * Perform resolution and validation of the target name. - * Asynchronous, after a while, the callback will be called with your - * data and the result. Uses the event_base user installed by creating the - * context with ub_ctx_create_event(). - * @param ctx: context with event_base in it. - * The context is finalized, and can no longer accept all config changes. - * @param name: domain name in text format (a string). - * @param rrtype: type of RR in host order, 1 is A. - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param mydata: this data is your own data (you can pass NULL), - * and is passed on to the callback function. - * @param callback: this is called on completion of the resolution. - * It is called as: - * void callback(void* mydata, int rcode, void* packet, int packet_len, - * int sec, char* why_bogus, int was_ratelimited) - * with mydata: the same as passed here, you may pass NULL, - * with rcode: 0 on no error, nonzero for mostly SERVFAIL situations, - * this is a DNS rcode. - * with packet: a buffer with DNS wireformat packet with the answer. - * do not inspect if rcode != 0. - * do not write or free the packet buffer, it is used internally - * in unbound (for other callbacks that want the same data). - * with packet_len: length in bytes of the packet buffer. - * with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure. - * with why_bogus: text string explaining why it is bogus (or NULL). - * with was_ratelimited: if the query was ratelimited. - * These point to buffers inside unbound; do not deallocate the packet or - * error string. - * - * If an error happens during processing, your callback will be called - * with error set to a nonzero value (and result==NULL). - * For localdata (etc/hosts) the callback is called immediately, before - * resolve_event returns, async_id=0 is returned. - * @param async_id: if you pass a non-NULL value, an identifier number is - * returned for the query as it is in progress. It can be used to - * cancel the query. - * @return 0 if OK, else error. - */ -int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, void* mydata, ub_event_callback_type callback, - int* async_id); - -#ifdef __cplusplus -} -#endif - -#endif /* UB_UNBOUND_EVENT_H */ diff --git a/crates/libunbound-sys/unbound/libunbound/unbound.h b/crates/libunbound-sys/unbound/libunbound/unbound.h deleted file mode 100644 index bb8e8acf..00000000 --- a/crates/libunbound-sys/unbound/libunbound/unbound.h +++ /dev/null @@ -1,879 +0,0 @@ -/* - * unbound.h - unbound validating resolver public API - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to resolve DNS queries and - * validate the answers. Synchronously and asynchronously. - * - * Several ways to use this interface from an application wishing - * to perform (validated) DNS lookups. - * - * All start with - * ctx = ub_ctx_create(); - * err = ub_ctx_add_ta(ctx, "..."); - * err = ub_ctx_add_ta(ctx, "..."); - * ... some lookups - * ... call ub_ctx_delete(ctx); when you want to stop. - * - * Application not threaded. Blocking. - * int err = ub_resolve(ctx, "www.example.com", ... - * if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err)); - * ... use the answer - * - * Application not threaded. Non-blocking ('asynchronous'). - * err = ub_resolve_async(ctx, "www.example.com", ... my_callback); - * ... application resumes processing ... - * ... and when either ub_poll(ctx) is true - * ... or when the file descriptor ub_fd(ctx) is readable, - * ... or whenever, the app calls ... - * ub_process(ctx); - * ... if no result is ready, the app resumes processing above, - * ... or process() calls my_callback() with results. - * - * ... if the application has nothing more to do, wait for answer - * ub_wait(ctx); - * - * Application threaded. Blocking. - * Blocking, same as above. The current thread does the work. - * Multiple threads can use the *same context*, each does work and uses - * shared cache data from the context. - * - * Application threaded. Non-blocking ('asynchronous'). - * ... setup threaded-asynchronous config option - * err = ub_ctx_async(ctx, 1); - * ... same as async for non-threaded - * ... the callbacks are called in the thread that calls process(ctx) - * - * Openssl needs to have locking in place, and the application must set - * it up, because a mere library cannot do this, use the calls - * CRYPTO_set_id_callback and CRYPTO_set_locking_callback. - * - * If no threading is compiled in, the above async example uses fork(2) to - * create a process to perform the work. The forked process exits when the - * calling process exits, or ctx_delete() is called. - * Otherwise, for asynchronous with threading, a worker thread is created. - * - * The blocking calls use shared ctx-cache when threaded. Thus - * ub_resolve() and ub_resolve_async() && ub_wait() are - * not the same. The first makes the current thread do the work, setting - * up buffers, etc, to perform the work (but using shared cache data). - * The second calls another worker thread (or process) to perform the work. - * And no buffers need to be set up, but a context-switch happens. - */ -#ifndef UB_UNBOUND_H -#define UB_UNBOUND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** the version of this header file */ -#define UNBOUND_VERSION_MAJOR @UNBOUND_VERSION_MAJOR@ -#define UNBOUND_VERSION_MINOR @UNBOUND_VERSION_MINOR@ -#define UNBOUND_VERSION_MICRO @UNBOUND_VERSION_MICRO@ - -/** - * The validation context is created to hold the resolver status, - * validation keys and a small cache (containing messages, rrsets, - * roundtrip times, trusted keys, lameness information). - * - * Its contents are internally defined. - */ -struct ub_ctx; - -/** - * The validation and resolution results. - * Allocated by the resolver, and need to be freed by the application - * with ub_resolve_free(). - */ -struct ub_result { - /** The original question, name text string. */ - char* qname; - /** the type asked for */ - int qtype; - /** the class asked for */ - int qclass; - - /** - * a list of network order DNS rdata items, terminated with a - * NULL pointer, so that data[0] is the first result entry, - * data[1] the second, and the last entry is NULL. - * If there was no data, data[0] is NULL. - */ - char** data; - - /** the length in bytes of the data items, len[i] for data[i] */ - int* len; - - /** - * canonical name for the result (the final cname). - * zero terminated string. - * May be NULL if no canonical name exists. - */ - char* canonname; - - /** - * DNS RCODE for the result. May contain additional error code if - * there was no data due to an error. 0 (NOERROR) if okay. - */ - int rcode; - - /** - * The DNS answer packet. Network formatted. Can contain DNSSEC types. - */ - void* answer_packet; - /** length of the answer packet in octets. */ - int answer_len; - - /** - * If there is any data, this is true. - * If false, there was no data (nxdomain may be true, rcode can be set). - */ - int havedata; - - /** - * If there was no data, and the domain did not exist, this is true. - * If it is false, and there was no data, then the domain name - * is purported to exist, but the requested data type is not available. - */ - int nxdomain; - - /** - * True, if the result is validated securely. - * False, if validation failed or domain queried has no security info. - * - * It is possible to get a result with no data (havedata is false), - * and secure is true. This means that the non-existence of the data - * was cryptographically proven (with signatures). - */ - int secure; - - /** - * If the result was not secure (secure==0), and this result is due - * to a security failure, bogus is true. - * This means the data has been actively tampered with, signatures - * failed, expected signatures were not present, timestamps on - * signatures were out of date and so on. - * - * If !secure and !bogus, this can happen if the data is not secure - * because security is disabled for that domain name. - * This means the data is from a domain where data is not signed. - */ - int bogus; - - /** - * If the result is bogus this contains a string (zero terminated) - * that describes the failure. There may be other errors as well - * as the one described, the description may not be perfectly accurate. - * Is NULL if the result is not bogus. - */ - char* why_bogus; - - /** - * If the query or one of its subqueries was ratelimited. Useful if - * ratelimiting is enabled and answer to the client is SERVFAIL as a - * result. - */ - int was_ratelimited; - - /** - * TTL for the result, in seconds. If the security is bogus, then - * you also cannot trust this value. - */ - int ttl; -}; - -/** - * Callback for results of async queries. - * The readable function definition looks like: - * void my_callback(void* my_arg, int err, struct ub_result* result); - * It is called with - * void* my_arg: your pointer to a (struct of) data of your choice, - * or NULL. - * int err: if 0 all is OK, otherwise an error occurred and no results - * are forthcoming. - * struct result: pointer to more detailed result structure. - * This structure is allocated on the heap and needs to be - * freed with ub_resolve_free(result); - */ -typedef void (*ub_callback_type)(void*, int, struct ub_result*); - -/** - * The error constants - */ -enum ub_ctx_err { - /** no error */ - UB_NOERROR = 0, - /** socket operation. Set to -1, so that if an error from _fd() is - * passed (-1) it gives a socket error. */ - UB_SOCKET = -1, - /** alloc failure */ - UB_NOMEM = -2, - /** syntax error */ - UB_SYNTAX = -3, - /** DNS service failed */ - UB_SERVFAIL = -4, - /** fork() failed */ - UB_FORKFAIL = -5, - /** cfg change after finalize() */ - UB_AFTERFINAL = -6, - /** initialization failed (bad settings) */ - UB_INITFAIL = -7, - /** error in pipe communication with async bg worker */ - UB_PIPE = -8, - /** error reading from file (resolv.conf) */ - UB_READFILE = -9, - /** error async_id does not exist or result already been delivered */ - UB_NOID = -10 -}; - -/** - * Create a resolving and validation context. - * The information from /etc/resolv.conf and /etc/hosts is not utilised by - * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - * @return a new context. default initialisation. - * returns NULL on error. - */ -struct ub_ctx* ub_ctx_create(void); - -/** - * Destroy a validation context and free all its resources. - * Outstanding async queries are killed and callbacks are not called for them. - * @param ctx: context to delete. - */ -void ub_ctx_delete(struct ub_ctx* ctx); - -/** - * Set an option for the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name includes the trailing ':' - * for example ub_ctx_set_option(ctx, "logfile:", "mylog.txt"); - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @param val: value of the option. - * @return: 0 if OK, else error. - */ -int ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val); - -/** - * Get an option from the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name excludes the trailing ':' - * for example ub_ctx_get_option(ctx, "logfile", &result); - * This is a power-users interface that lets you specify all sorts - * of options. - * @param str: the string is malloced and returned here. NULL on error. - * The caller must free() the string. In cases with multiple - * entries (auto-trust-anchor-file), a newline delimited list is - * returned in the string. - * @return 0 if OK else an error code (malloc failure, syntax error). - */ -int ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str); - -/** - * setup configuration for the given context. - * @param ctx: context. - * @param fname: unbound config file (not all settings applicable). - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @return: 0 if OK, else error. - */ -int ub_ctx_config(struct ub_ctx* ctx, const char* fname); - -/** - * Set machine to forward DNS queries to, the caching resolver to use. - * IP4 or IP6 address. Forwards all DNS requests to that machine, which - * is expected to run a recursive resolver. If the proxy is not - * DNSSEC-capable, validation may fail. Can be called several times, in - * that case the addresses are used as backup servers. - * - * To read the list of nameservers from /etc/resolv.conf (from DHCP or so), - * use the call ub_ctx_resolvconf. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param addr: address, IP4 or IP6 in string format. - * If the addr is NULL, forwarding is disabled. - * @return 0 if OK, else error. - */ -int ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr); - -/** - * Use DNS over TLS to send queries to machines set with ub_ctx_set_fwd(). - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param tls: enable or disable DNS over TLS - * @return 0 if OK, else error. - */ -int ub_ctx_set_tls(struct ub_ctx* ctx, int tls); - -/** - * Add a stub zone, with given address to send to. This is for custom - * root hints or pointing to a local authoritative dns server. - * For dns resolvers and the 'DHCP DNS' ip address, use ub_ctx_set_fwd. - * This is similar to a stub-zone entry in unbound.conf. - * - * @param ctx: context. - * It is only possible to set configuration before the - * first resolve is done. - * @param zone: name of the zone, string. - * @param addr: address, IP4 or IP6 in string format. - * The addr is added to the list of stub-addresses if the entry exists. - * If the addr is NULL the stub entry is removed. - * @param isprime: set to true to set stub-prime to yes for the stub. - * For local authoritative servers, people usually set it to false, - * For root hints it should be set to true. - * @return 0 if OK, else error. - */ -int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, - int isprime); - -/** - * Read list of nameservers to use from the filename given. - * Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. - * If they do not support DNSSEC, validation may fail. - * - * Only nameservers are picked up, the searchdomain, ndots and other - * settings from resolv.conf(5) are ignored. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/resolv.conf" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname); - -/** - * Read list of hosts from the filename given. - * Usually "/etc/hosts". - * These addresses are not flagged as DNSSEC secure when queried for. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/hosts" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_hosts(struct ub_ctx* ctx, const char* fname); - -/** - * Add a trust anchor to the given context. - * The trust anchor is a string, on one line, that holds a valid DNSKEY or - * DS RR. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param ta: string, with zone-format RR on one line. - * [domainname] [TTL optional] [type] [class optional] [rdata contents] - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta); - -/** - * Add trust anchors to the given context. - * Pass name of a file with DS and DNSKEY records (like from dig or drill). - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with keyfile with trust anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname); - -/** - * Add trust anchor to the given context that is tracked with RFC5011 - * automated trust anchor maintenance. The file is written to when the - * trust anchor is changed. - * Pass the name of a file that was output from eg. unbound-anchor, - * or you can start it by providing a trusted DNSKEY or DS record on one - * line in the file. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with trust anchor. - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname); - -/** - * Add trust anchors to the given context. - * Pass the name of a bind-style config file with trusted-keys{}. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with bind-style config entries with trust - * anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname); - -/** - * Set debug output (and error output) to the specified stream. - * Pass NULL to disable. Default is stderr. - * @param ctx: context. - * @param out: FILE* out file stream to log to. - * Type void* to avoid stdio dependency of this header file. - * @return 0 if OK, else error. - */ -int ub_ctx_debugout(struct ub_ctx* ctx, void* out); - -/** - * Set debug verbosity for the context - * Output is directed to stderr. - * @param ctx: context. - * @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed, - * and 3 is lots. - * @return 0 if OK, else error. - */ -int ub_ctx_debuglevel(struct ub_ctx* ctx, int d); - -/** - * Set a context behaviour for asynchronous action. - * @param ctx: context. - * @param dothread: if true, enables threading and a call to resolve_async() - * creates a thread to handle work in the background. - * If false, a process is forked to handle work in the background. - * Changes to this setting after async() calls have been made have - * no effect (delete and re-create the context to change). - * @return 0 if OK, else error. - */ -int ub_ctx_async(struct ub_ctx* ctx, int dothread); - -/** - * Poll a context to see if it has any new results - * Do not poll in a loop, instead extract the fd below to poll for readiness, - * and then check, or wait using the wait routine. - * @param ctx: context. - * @return: 0 if nothing to read, or nonzero if a result is available. - * If nonzero, call ctx_process() to do callbacks. - */ -int ub_poll(struct ub_ctx* ctx); - -/** - * Wait for a context to finish with results. Calls ub_process() after - * the wait for you. After the wait, there are no more outstanding - * asynchronous queries. - * @param ctx: context. - * @return: 0 if OK, else error. - */ -int ub_wait(struct ub_ctx* ctx); - -/** - * Get file descriptor. Wait for it to become readable, at this point - * answers are returned from the asynchronous validating resolver. - * Then call the ub_process to continue processing. - * This routine works immediately after context creation, the fd - * does not change. - * @param ctx: context. - * @return: -1 on error, or file descriptor to use select(2) with. - */ -int ub_fd(struct ub_ctx* ctx); - -/** - * Call this routine to continue processing results from the validating - * resolver (when the fd becomes readable). - * Will perform necessary callbacks. - * @param ctx: context - * @return: 0 if OK, else error. - */ -int ub_process(struct ub_ctx* ctx); - -/** - * Perform resolution and validation of the target name. - * @param ctx: context. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a zero terminated text string). - * @param rrtype: type of RR in host order, 1 is A (address). - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param result: the result data is returned in a newly allocated result - * structure. May be NULL on return, return value is set to an error - * in that case (out of memory). - * @return 0 if OK, else error. - */ -int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, struct ub_result** result); - -/** - * Perform resolution and validation of the target name. - * Asynchronous, after a while, the callback will be called with your - * data and the result. - * @param ctx: context. - * If no thread or process has been created yet to perform the - * work in the background, it is created now. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a string). - * @param rrtype: type of RR in host order, 1 is A. - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param mydata: this data is your own data (you can pass NULL), - * and is passed on to the callback function. - * @param callback: this is called on completion of the resolution. - * It is called as: - * void callback(void* mydata, int err, struct ub_result* result) - * with mydata: the same as passed here, you may pass NULL, - * with err: is 0 when a result has been found. - * with result: a newly allocated result structure. - * The result may be NULL, in that case err is set. - * - * If an error happens during processing, your callback will be called - * with error set to a nonzero value (and result==NULL). - * @param async_id: if you pass a non-NULL value, an identifier number is - * returned for the query as it is in progress. It can be used to - * cancel the query. - * @return 0 if OK, else error. - */ -int ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, void* mydata, ub_callback_type callback, int* async_id); - -/** - * Cancel an async query in progress. - * Its callback will not be called. - * - * @param ctx: context. - * @param async_id: which query to cancel. - * @return 0 if OK, else error. - * This routine can return an error if the async_id passed does not exist - * or has already been delivered. If another thread is processing results - * at the same time, the result may be delivered at the same time and the - * cancel fails with an error. Also the cancel can fail due to a system - * error, no memory or socket failures. - */ -int ub_cancel(struct ub_ctx* ctx, int async_id); - -/** - * Free storage associated with a result structure. - * @param result: to free - */ -void ub_resolve_free(struct ub_result* result); - -/** - * Convert error value to a human readable string. - * @param err: error code from one of the libunbound functions. - * The error codes are from the type enum ub_ctx_err. - * @return pointer to constant text string, zero terminated. - */ -const char* ub_strerror(int err); - -/** - * Debug routine. Print the local zone information to debug output. - * @param ctx: context. Is finalized by the routine. - * @return 0 if OK, else error. - */ -int ub_ctx_print_local_zones(struct ub_ctx* ctx); - -/** - * Add a new zone with the zonetype to the local authority info of the - * library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it already exists, the type is updated. - * @param zone_type: type of the zone (like for unbound.conf) in text. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, - const char *zone_type); - -/** - * Remove zone from local authority info of the library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it does not exist, nothing happens. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name); - -/** - * Add localdata to the library local authority info. - * Similar to local-data config statement. - * @param ctx: context. Is finalized by the routine. - * @param data: the resource record in text format, for example - * "www.example.com IN A 127.0.0.1" - * @return 0 if OK, else error. - */ -int ub_ctx_data_add(struct ub_ctx* ctx, const char *data); - -/** - * Remove localdata from the library local authority info. - * @param ctx: context. Is finalized by the routine. - * @param data: the name to delete all data from, like "www.example.com". - * @return 0 if OK, else error. - */ -int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data); - -/** - * Get a version string from the libunbound implementation. - * @return a static constant string with the version number. - */ -const char* ub_version(void); - -/** - * Some global statistics that are not in struct stats_info, - * this struct is shared on a shm segment (shm-key in unbound.conf) - */ -struct ub_shm_stat_info { - int num_threads; - - struct { - long long now_sec, now_usec; - long long up_sec, up_usec; - long long elapsed_sec, elapsed_usec; - } time; - - struct { - long long msg; - long long rrset; - long long val; - long long iter; - long long subnet; - long long ipsecmod; - long long respip; - long long dnscrypt_shared_secret; - long long dnscrypt_nonce; - long long dynlib; - } mem; -}; - -/** number of qtype that is stored for in array */ -#define UB_STATS_QTYPE_NUM 256 -/** number of qclass that is stored for in array */ -#define UB_STATS_QCLASS_NUM 256 -/** number of rcodes in stats */ -#define UB_STATS_RCODE_NUM 16 -/** number of opcodes in stats */ -#define UB_STATS_OPCODE_NUM 16 -/** number of histogram buckets */ -#define UB_STATS_BUCKET_NUM 40 -/** number of RPZ actions */ -#define UB_STATS_RPZ_ACTION_NUM 10 - -/** per worker statistics. */ -struct ub_server_stats { - /** number of queries from clients received. */ - long long num_queries; - /** number of queries that have been dropped/ratelimited by ip. */ - long long num_queries_ip_ratelimited; - /** number of queries with a valid DNS Cookie. */ - long long num_queries_cookie_valid; - /** number of queries with only the client part of the DNS Cookie. */ - long long num_queries_cookie_client; - /** number of queries with invalid DNS Cookie. */ - long long num_queries_cookie_invalid; - /** number of queries that had a cache-miss. */ - long long num_queries_missed_cache; - /** number of prefetch queries - cachehits with prefetch */ - long long num_queries_prefetch; - /** number of queries which are too late to process */ - long long num_queries_timed_out; - /** the longest wait time in the queue */ - long long max_query_time_us; - /** - * Sum of the querylistsize of the worker for - * every query that missed cache. To calculate average. - */ - long long sum_query_list_size; - /** max value of query list size reached. */ - long long max_query_list_size; - - /** Extended stats below (bool) */ - int extended; - - /** qtype stats */ - long long qtype[UB_STATS_QTYPE_NUM]; - /** bigger qtype values not in array */ - long long qtype_big; - /** qclass stats */ - long long qclass[UB_STATS_QCLASS_NUM]; - /** bigger qclass values not in array */ - long long qclass_big; - /** query opcodes */ - long long qopcode[UB_STATS_OPCODE_NUM]; - /** number of queries over TCP */ - long long qtcp; - /** number of outgoing queries over TCP */ - long long qtcp_outgoing; - /** number of outgoing queries over UDP */ - long long qudp_outgoing; - /** number of queries over (DNS over) TLS */ - long long qtls; - /** number of queries over (DNS over) HTTPS */ - long long qhttps; - /** number of queries over IPv6 */ - long long qipv6; - /** number of queries with QR bit */ - long long qbit_QR; - /** number of queries with AA bit */ - long long qbit_AA; - /** number of queries with TC bit */ - long long qbit_TC; - /** number of queries with RD bit */ - long long qbit_RD; - /** number of queries with RA bit */ - long long qbit_RA; - /** number of queries with Z bit */ - long long qbit_Z; - /** number of queries with AD bit */ - long long qbit_AD; - /** number of queries with CD bit */ - long long qbit_CD; - /** number of queries with EDNS OPT record */ - long long qEDNS; - /** number of queries with EDNS with DO flag */ - long long qEDNS_DO; - /** answer rcodes */ - long long ans_rcode[UB_STATS_RCODE_NUM]; - /** answers with pseudo rcode 'nodata' */ - long long ans_rcode_nodata; - /** answers that were secure (AD) */ - long long ans_secure; - /** answers that were bogus (withheld as SERVFAIL) */ - long long ans_bogus; - /** rrsets marked bogus by validator */ - long long rrset_bogus; - /** number of queries that have been ratelimited by domain recursion. */ - long long queries_ratelimited; - /** unwanted traffic received on server-facing ports */ - long long unwanted_replies; - /** unwanted traffic received on client-facing ports */ - long long unwanted_queries; - /** usage of tcp accept list */ - long long tcp_accept_usage; - /** expired answers served from cache */ - long long ans_expired; - /** histogram data exported to array - * if the array is the same size, no data is lost, and - * if all histograms are same size (is so by default) then - * adding up works well. */ - long long hist[UB_STATS_BUCKET_NUM]; - - /** number of message cache entries */ - long long msg_cache_count; - /** number of rrset cache entries */ - long long rrset_cache_count; - /** number of infra cache entries */ - long long infra_cache_count; - /** number of key cache entries */ - long long key_cache_count; - - /** maximum number of collisions in the msg cache */ - long long msg_cache_max_collisions; - /** maximum number of collisions in the rrset cache */ - long long rrset_cache_max_collisions; - - /** number of queries that used dnscrypt */ - long long num_query_dnscrypt_crypted; - /** number of queries that queried dnscrypt certificates */ - long long num_query_dnscrypt_cert; - /** number of queries in clear text and not asking for the certificates */ - long long num_query_dnscrypt_cleartext; - /** number of malformed encrypted queries */ - long long num_query_dnscrypt_crypted_malformed; - /** number of queries which did not have a shared secret in cache */ - long long num_query_dnscrypt_secret_missed_cache; - /** number of dnscrypt shared secret cache entries */ - long long shared_secret_cache_count; - /** number of queries which are replays */ - long long num_query_dnscrypt_replay; - /** number of dnscrypt nonces cache entries */ - long long nonce_cache_count; - /** number of queries for unbound's auth_zones, upstream query */ - long long num_query_authzone_up; - /** number of queries for unbound's auth_zones, downstream answers */ - long long num_query_authzone_down; - /** number of times neg cache records were used to generate NOERROR - * responses. */ - long long num_neg_cache_noerror; - /** number of times neg cache records were used to generate NXDOMAIN - * responses. */ - long long num_neg_cache_nxdomain; - /** number of queries answered from edns-subnet specific data */ - long long num_query_subnet; - /** number of queries answered from edns-subnet specific data, and - * the answer was from the edns-subnet cache. */ - long long num_query_subnet_cache; - /** number of queries served from cachedb */ - long long num_query_cachedb; - /** number of bytes in the stream wait buffers */ - long long mem_stream_wait; - /** number of bytes in the HTTP2 query buffers */ - long long mem_http2_query_buffer; - /** number of bytes in the HTTP2 response buffers */ - long long mem_http2_response_buffer; - /** number of TLS connection resume */ - long long qtls_resume; - /** RPZ action stats */ - long long rpz_action[UB_STATS_RPZ_ACTION_NUM]; -}; - -/** - * Statistics to send over the control pipe when asked - * This struct is made to be memcopied, sent in binary. - * shm mapped with (number+1) at num_threads+1, with first as total - */ -struct ub_stats_info { - /** the thread stats */ - struct ub_server_stats svr; - - /** mesh stats: current number of states */ - long long mesh_num_states; - /** mesh stats: current number of reply (user) states */ - long long mesh_num_reply_states; - /** mesh stats: number of reply states overwritten with a new one */ - long long mesh_jostled; - /** mesh stats: number of incoming queries dropped */ - long long mesh_dropped; - /** mesh stats: replies sent */ - long long mesh_replies_sent; - /** mesh stats: sum of waiting times for the replies */ - long long mesh_replies_sum_wait_sec, mesh_replies_sum_wait_usec; - /** mesh stats: median of waiting times for replies (in sec) */ - double mesh_time_median; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* UB_UNBOUND_H */ diff --git a/crates/libunbound-sys/unbound/libunbound/worker.h b/crates/libunbound-sys/unbound/libunbound/worker.h deleted file mode 100644 index 0fa5bfa9..00000000 --- a/crates/libunbound-sys/unbound/libunbound/worker.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * libunbound/worker.h - prototypes for worker methods. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file declares the methods any worker has to implement. - */ - -#ifndef LIBUNBOUND_WORKER_H -#define LIBUNBOUND_WORKER_H - -#include "sldns/sbuffer.h" -#include "util/data/packed_rrset.h" /* for enum sec_status */ -struct comm_reply; -struct comm_point; -struct module_qstate; -struct tube; -struct edns_option; -struct query_info; - -/** - * Worker service routine to send serviced queries to authoritative servers. - * @param qinfo: query info. - * @param flags: host order flags word, with opcode and CD bit. - * @param dnssec: if set, EDNS record will have DO bit set. - * @param want_dnssec: signatures needed. - * @param nocaps: ignore capsforid(if in config), do not perturb qname. - * @param check_ratelimit: if set, will check ratelimit before sending out. - * @param addr: where to. - * @param addrlen: length of addr. - * @param zone: delegation point name. - * @param zonelen: length of zone name wireformat dname. - * @param tcp_upstream: use TCP for upstream queries. - * @param ssl_upstream: use SSL for upstream queries. - * @param tls_auth_name: if ssl_upstream, use this name with TLS - * authentication. - * @param q: which query state to reactivate upon return. - * @param was_ratelimited: it will signal back if the query failed to pass the - * ratelimit check. - * @return: false on failure (memory or socket related). no query was - * sent. - */ -struct outbound_entry* libworker_send_query(struct query_info* qinfo, - uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int check_ratelimit, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, - struct module_qstate* q, int* was_ratelimited); - -/** process incoming serviced query replies from the network */ -int libworker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** handle control command coming into server */ -void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, - int err, void* arg); - -/** mesh callback with fg results */ -void libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, - enum sec_status s, char* why_bogus, int was_ratelimited); - -/** mesh callback with bg results */ -void libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, - enum sec_status s, char* why_bogus, int was_ratelimited); - -/** mesh callback with event results */ -void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf, - enum sec_status s, char* why_bogus, int was_ratelimited); - -/** - * Worker signal handler function. User argument is the worker itself. - * @param sig: signal number. - * @param arg: the worker (main worker) that handles signals. - */ -void worker_sighandler(int sig, void* arg); - -/** - * Worker service routine to send serviced queries to authoritative servers. - * @param qinfo: query info. - * @param flags: host order flags word, with opcode and CD bit. - * @param dnssec: if set, EDNS record will have DO bit set. - * @param want_dnssec: signatures needed. - * @param nocaps: ignore capsforid(if in config), do not perturb qname. - * @param check_ratelimit: if set, will check ratelimit before sending out. - * @param addr: where to. - * @param addrlen: length of addr. - * @param zone: wireformat dname of the zone. - * @param zonelen: length of zone name. - * @param tcp_upstream: use TCP for upstream queries. - * @param ssl_upstream: use SSL for upstream queries. - * @param tls_auth_name: if ssl_upstream, use this name with TLS - * authentication. - * @param q: which query state to reactivate upon return. - * @param was_ratelimited: it will signal back if the query failed to pass the - * ratelimit check. - * @return: false on failure (memory or socket related). no query was - * sent. - */ -struct outbound_entry* worker_send_query(struct query_info* qinfo, - uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int check_ratelimit, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, - struct module_qstate* q, int* was_ratelimited); - -/** - * process control messages from the main thread. Frees the control - * command message. - * @param tube: tube control message came on. - * @param msg: message contents. Is freed. - * @param len: length of message. - * @param error: if error (NETEVENT_*) happened. - * @param arg: user argument - */ -void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, - int error, void* arg); - -/** handles callbacks from listening event interface */ -int worker_handle_request(struct comm_point* c, void* arg, int error, - struct comm_reply* repinfo); - -/** process incoming serviced query replies from the network */ -int worker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** cleanup the cache to remove all rrset IDs from it, arg is worker */ -void worker_alloc_cleanup(void* arg); - -/** statistics timer callback handler */ -void worker_stat_timer_cb(void* arg); - -/** probe timer callback handler */ -void worker_probe_timer_cb(void* arg); - -/** start accept callback handler */ -void worker_start_accept(void* arg); - -/** stop accept callback handler */ -void worker_stop_accept(void* arg); - -/** handle remote control accept callbacks */ -int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*); - -/** handle remote control data callbacks */ -int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*); - -/** routine to printout option values over SSL */ -void remote_get_opt_ssl(char* line, void* arg); - -#endif /* LIBUNBOUND_WORKER_H */ diff --git a/crates/libunbound-sys/unbound/respip/respip.c b/crates/libunbound-sys/unbound/respip/respip.c deleted file mode 100644 index 942e082b..00000000 --- a/crates/libunbound-sys/unbound/respip/respip.c +++ /dev/null @@ -1,1328 +0,0 @@ -/* - * respip/respip.c - filtering response IP module - */ - -/** - * \file - * - * This file contains a module that inspects a result of recursive resolution - * to see if any IP address record should trigger a special action. - * If applicable these actions can modify the original response. - */ -#include "config.h" - -#include "services/localzone.h" -#include "services/authzone.h" -#include "services/cache/dns.h" -#include "sldns/str2wire.h" -#include "util/config_file.h" -#include "util/fptr_wlist.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/data/msgreply.h" -#include "util/storage/dnstree.h" -#include "respip/respip.h" -#include "services/view.h" -#include "sldns/rrdef.h" -#include "util/data/dname.h" - - -/** Subset of resp_addr.node, used for inform-variant logging */ -struct respip_addr_info { - struct sockaddr_storage addr; - socklen_t addrlen; - int net; -}; - -/** Query state regarding the response-ip module. */ -enum respip_state { - /** - * The general state. Unless CNAME chasing takes place, all processing - * is completed in this state without any other asynchronous event. - */ - RESPIP_INIT = 0, - - /** - * A subquery for CNAME chasing is completed. - */ - RESPIP_SUBQUERY_FINISHED -}; - -/** Per query state for the response-ip module. */ -struct respip_qstate { - enum respip_state state; -}; - -struct respip_set* -respip_set_create(void) -{ - struct respip_set* set = calloc(1, sizeof(*set)); - if(!set) - return NULL; - set->region = regional_create(); - if(!set->region) { - free(set); - return NULL; - } - addr_tree_init(&set->ip_tree); - lock_rw_init(&set->lock); - return set; -} - -/** helper traverse to delete resp_addr nodes */ -static void -resp_addr_del(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct resp_addr* r = (struct resp_addr*)n->key; - lock_rw_destroy(&r->lock); -#ifdef THREADS_DISABLED - (void)r; -#endif -} - -void -respip_set_delete(struct respip_set* set) -{ - if(!set) - return; - lock_rw_destroy(&set->lock); - traverse_postorder(&set->ip_tree, resp_addr_del, NULL); - regional_destroy(set->region); - free(set); -} - -struct rbtree_type* -respip_set_get_tree(struct respip_set* set) -{ - if(!set) - return NULL; - return &set->ip_tree; -} - -struct resp_addr* -respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr, - socklen_t addrlen, int net, int create, const char* ipstr) -{ - struct resp_addr* node; - node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net); - if(!node && create) { - node = regional_alloc_zero(set->region, sizeof(*node)); - if(!node) { - log_err("out of memory"); - return NULL; - } - lock_rw_init(&node->lock); - node->action = respip_none; - if(!addr_tree_insert(&set->ip_tree, &node->node, addr, - addrlen, net)) { - /* We know we didn't find it, so this should be - * impossible. */ - log_warn("unexpected: duplicate address: %s", ipstr); - } - } - return node; -} - -void -respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node) -{ - struct resp_addr* prev; - prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node); - lock_rw_destroy(&node->lock); - (void)rbtree_delete(&set->ip_tree, node); - /* no free'ing, all allocated in region */ - if(!prev) - addr_tree_init_parents((rbtree_type*)set); - else - addr_tree_init_parents_node(&prev->node); -} - -/** returns the node in the address tree for the specified netblock string; - * non-existent node will be created if 'create' is true */ -static struct resp_addr* -respip_find_or_create(struct respip_set* set, const char* ipstr, int create) -{ - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - - if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) { - log_err("cannot parse netblock: '%s'", ipstr); - return NULL; - } - return respip_sockaddr_find_or_create(set, &addr, addrlen, net, create, - ipstr); -} - -static int -respip_tag_cfg(struct respip_set* set, const char* ipstr, - const uint8_t* taglist, size_t taglen) -{ - struct resp_addr* node; - - if(!(node=respip_find_or_create(set, ipstr, 1))) - return 0; - if(node->taglist) { - log_warn("duplicate response-address-tag for '%s', overridden.", - ipstr); - } - node->taglist = regional_alloc_init(set->region, taglist, taglen); - if(!node->taglist) { - log_err("out of memory"); - return 0; - } - node->taglen = taglen; - return 1; -} - -/** set action for the node specified by the netblock string */ -static int -respip_action_cfg(struct respip_set* set, const char* ipstr, - const char* actnstr) -{ - struct resp_addr* node; - enum respip_action action; - - if(!(node=respip_find_or_create(set, ipstr, 1))) - return 0; - if(node->action != respip_none) { - verbose(VERB_QUERY, "duplicate response-ip action for '%s', overridden.", - ipstr); - } - if(strcmp(actnstr, "deny") == 0) - action = respip_deny; - else if(strcmp(actnstr, "redirect") == 0) - action = respip_redirect; - else if(strcmp(actnstr, "inform") == 0) - action = respip_inform; - else if(strcmp(actnstr, "inform_deny") == 0) - action = respip_inform_deny; - else if(strcmp(actnstr, "inform_redirect") == 0) - action = respip_inform_redirect; - else if(strcmp(actnstr, "always_transparent") == 0) - action = respip_always_transparent; - else if(strcmp(actnstr, "always_refuse") == 0) - action = respip_always_refuse; - else if(strcmp(actnstr, "always_nxdomain") == 0) - action = respip_always_nxdomain; - else if(strcmp(actnstr, "always_nodata") == 0) - action = respip_always_nodata; - else if(strcmp(actnstr, "always_deny") == 0) - action = respip_always_deny; - else { - log_err("unknown response-ip action %s", actnstr); - return 0; - } - node->action = action; - return 1; -} - -/** allocate and initialize an rrset structure; this function is based - * on new_local_rrset() from the localzone.c module */ -static struct ub_packed_rrset_key* -new_rrset(struct regional* region, uint16_t rrtype, uint16_t rrclass) -{ - struct packed_rrset_data* pd; - struct ub_packed_rrset_key* rrset = regional_alloc_zero( - region, sizeof(*rrset)); - if(!rrset) { - log_err("out of memory"); - return NULL; - } - rrset->entry.key = rrset; - pd = regional_alloc_zero(region, sizeof(*pd)); - if(!pd) { - log_err("out of memory"); - return NULL; - } - pd->trust = rrset_trust_prim_noglue; - pd->security = sec_status_insecure; - rrset->entry.data = pd; - rrset->rk.dname = regional_alloc_zero(region, 1); - if(!rrset->rk.dname) { - log_err("out of memory"); - return NULL; - } - rrset->rk.dname_len = 1; - rrset->rk.type = htons(rrtype); - rrset->rk.rrset_class = htons(rrclass); - return rrset; -} - -/** enter local data as resource records into a response-ip node */ - -int -respip_enter_rr(struct regional* region, struct resp_addr* raddr, - uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, - size_t rdata_len, const char* rrstr, const char* netblockstr) -{ - struct packed_rrset_data* pd; - struct sockaddr* sa; - sa = (struct sockaddr*)&raddr->node.addr; - if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) { - log_err("CNAME response-ip data (%s) can not co-exist with other " - "response-ip data for netblock %s", rrstr, netblockstr); - return 0; - } else if (raddr->data && - raddr->data->rk.type == htons(LDNS_RR_TYPE_CNAME)) { - log_err("response-ip data (%s) can not be added; CNAME response-ip " - "data already in place for netblock %s", rrstr, netblockstr); - return 0; - } else if((rrtype != LDNS_RR_TYPE_CNAME) && - ((sa->sa_family == AF_INET && rrtype != LDNS_RR_TYPE_A) || - (sa->sa_family == AF_INET6 && rrtype != LDNS_RR_TYPE_AAAA))) { - log_err("response-ip data %s record type does not correspond " - "to netblock %s address family", rrstr, netblockstr); - return 0; - } - - if(!raddr->data) { - raddr->data = new_rrset(region, rrtype, rrclass); - if(!raddr->data) - return 0; - } - pd = raddr->data->entry.data; - return rrset_insert_rr(region, pd, rdata, rdata_len, ttl, rrstr); -} - -static int -respip_enter_rrstr(struct regional* region, struct resp_addr* raddr, - const char* rrstr, const char* netblock) -{ - uint8_t* nm; - uint16_t rrtype = 0, rrclass = 0; - time_t ttl = 0; - uint8_t rr[LDNS_RR_BUF_SIZE]; - uint8_t* rdata = NULL; - size_t rdata_len = 0; - char buf[65536]; - char bufshort[64]; - int ret; - if(raddr->action != respip_redirect - && raddr->action != respip_inform_redirect) { - log_err("cannot parse response-ip-data %s: response-ip " - "action for %s is not redirect", rrstr, netblock); - return 0; - } - ret = snprintf(buf, sizeof(buf), ". %s", rrstr); - if(ret < 0 || ret >= (int)sizeof(buf)) { - strlcpy(bufshort, rrstr, sizeof(bufshort)); - log_err("bad response-ip-data: %s...", bufshort); - return 0; - } - if(!rrstr_get_rr_content(buf, &nm, &rrtype, &rrclass, &ttl, rr, sizeof(rr), - &rdata, &rdata_len)) { - log_err("bad response-ip-data: %s", rrstr); - return 0; - } - free(nm); - return respip_enter_rr(region, raddr, rrtype, rrclass, ttl, rdata, - rdata_len, rrstr, netblock); -} - -static int -respip_data_cfg(struct respip_set* set, const char* ipstr, const char* rrstr) -{ - struct resp_addr* node; - - node=respip_find_or_create(set, ipstr, 0); - if(!node || node->action == respip_none) { - log_err("cannot parse response-ip-data %s: " - "response-ip node for %s not found", rrstr, ipstr); - return 0; - } - return respip_enter_rrstr(set->region, node, rrstr, ipstr); -} - -static int -respip_set_apply_cfg(struct respip_set* set, char* const* tagname, int num_tags, - struct config_strbytelist* respip_tags, - struct config_str2list* respip_actions, - struct config_str2list* respip_data) -{ - struct config_strbytelist* p; - struct config_str2list* pa; - struct config_str2list* pd; - - set->tagname = tagname; - set->num_tags = num_tags; - - p = respip_tags; - while(p) { - struct config_strbytelist* np = p->next; - - log_assert(p->str && p->str2); - if(!respip_tag_cfg(set, p->str, p->str2, p->str2len)) { - config_del_strbytelist(p); - return 0; - } - free(p->str); - free(p->str2); - free(p); - p = np; - } - - pa = respip_actions; - while(pa) { - struct config_str2list* np = pa->next; - log_assert(pa->str && pa->str2); - if(!respip_action_cfg(set, pa->str, pa->str2)) { - config_deldblstrlist(pa); - return 0; - } - free(pa->str); - free(pa->str2); - free(pa); - pa = np; - } - - pd = respip_data; - while(pd) { - struct config_str2list* np = pd->next; - log_assert(pd->str && pd->str2); - if(!respip_data_cfg(set, pd->str, pd->str2)) { - config_deldblstrlist(pd); - return 0; - } - free(pd->str); - free(pd->str2); - free(pd); - pd = np; - } - addr_tree_init_parents(&set->ip_tree); - - return 1; -} - -int -respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg) -{ - int ret = respip_set_apply_cfg(set, cfg->tagname, cfg->num_tags, - cfg->respip_tags, cfg->respip_actions, cfg->respip_data); - cfg->respip_data = NULL; - cfg->respip_actions = NULL; - cfg->respip_tags = NULL; - return ret; -} - -/** Iterate through raw view data and apply the view-specific respip - * configuration; at this point we should have already seen all the views, - * so if any of the views that respip data refer to does not exist, that's - * an error. This additional iteration through view configuration data - * is expected to not have significant performance impact (or rather, its - * performance impact is not expected to be prohibitive in the configuration - * processing phase). - */ -int -respip_views_apply_cfg(struct views* vs, struct config_file* cfg, - int* have_view_respip_cfg) -{ - struct config_view* cv; - struct view* v; - int ret; - - for(cv = cfg->views; cv; cv = cv->next) { - - /** if no respip config for this view then there's - * nothing to do; note that even though respip data must go - * with respip action, we're checking for both here because - * we want to catch the case where the respip action is missing - * while the data is present */ - if(!cv->respip_actions && !cv->respip_data) - continue; - - if(!(v = views_find_view(vs, cv->name, 1))) { - log_err("view '%s' unexpectedly missing", cv->name); - return 0; - } - if(!v->respip_set) { - v->respip_set = respip_set_create(); - if(!v->respip_set) { - log_err("out of memory"); - lock_rw_unlock(&v->lock); - return 0; - } - } - ret = respip_set_apply_cfg(v->respip_set, NULL, 0, NULL, - cv->respip_actions, cv->respip_data); - lock_rw_unlock(&v->lock); - if(!ret) { - log_err("Error while applying respip configuration " - "for view '%s'", cv->name); - return 0; - } - *have_view_respip_cfg = (*have_view_respip_cfg || - v->respip_set->ip_tree.count); - cv->respip_actions = NULL; - cv->respip_data = NULL; - } - return 1; -} - -/** - * make a deep copy of 'key' in 'region'. - * This is largely derived from packed_rrset_copy_region() and - * packed_rrset_ptr_fixup(), but differs in the following points: - * - * - It doesn't assume all data in 'key' are in a contiguous memory region. - * Although that would be the case in most cases, 'key' can be passed from - * a lower-level module and it might not build the rrset to meet the - * assumption. In fact, an rrset specified as response-ip-data or generated - * in local_data_find_tag_datas() breaks the assumption. So it would be - * safer not to naively rely on the assumption. On the other hand, this - * function ensures the copied rrset data are in a contiguous region so - * that it won't cause a disruption even if an upper layer module naively - * assumes the memory layout. - * - It doesn't copy RRSIGs (if any) in 'key'. The rrset will be used in - * a reply that was already faked, so it doesn't make much sense to provide - * partial sigs even if they are valid themselves. - * - It doesn't adjust TTLs as it basically has to be a verbatim copy of 'key' - * just allocated in 'region' (the assumption is necessary TTL adjustment - * has been already done in 'key'). - * - * This function returns the copied rrset key on success, and NULL on memory - * allocation failure. - */ -struct ub_packed_rrset_key* -respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region) -{ - struct ub_packed_rrset_key* ck = regional_alloc(region, - sizeof(struct ub_packed_rrset_key)); - struct packed_rrset_data* d; - struct packed_rrset_data* data = key->entry.data; - size_t dsize, i; - uint8_t* nextrdata; - - /* derived from packed_rrset_copy_region(), but don't use - * packed_rrset_sizeof() and do exclude RRSIGs */ - if(!ck) - return NULL; - ck->id = key->id; - memset(&ck->entry, 0, sizeof(ck->entry)); - ck->entry.hash = key->entry.hash; - ck->entry.key = ck; - ck->rk = key->rk; - if(key->rk.dname) { - ck->rk.dname = regional_alloc_init(region, key->rk.dname, - key->rk.dname_len); - if(!ck->rk.dname) - return NULL; - ck->rk.dname_len = key->rk.dname_len; - } else { - ck->rk.dname = NULL; - ck->rk.dname_len = 0; - } - - if((unsigned)data->count >= 0xffff00U) - return NULL; /* guard against integer overflow in dsize */ - dsize = sizeof(struct packed_rrset_data) + data->count * - (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)); - for(i=0; icount; i++) { - if((unsigned)dsize >= 0x0fffffffU || - (unsigned)data->rr_len[i] >= 0x0fffffffU) - return NULL; /* guard against integer overflow */ - dsize += data->rr_len[i]; - } - d = regional_alloc_zero(region, dsize); - if(!d) - return NULL; - *d = *data; - d->rrsig_count = 0; - ck->entry.data = d; - - /* derived from packed_rrset_ptr_fixup() with copying the data */ - d->rr_len = (size_t*)((uint8_t*)d + sizeof(struct packed_rrset_data)); - d->rr_data = (uint8_t**)&(d->rr_len[d->count]); - d->rr_ttl = (time_t*)&(d->rr_data[d->count]); - nextrdata = (uint8_t*)&(d->rr_ttl[d->count]); - for(i=0; icount; i++) { - d->rr_len[i] = data->rr_len[i]; - d->rr_ttl[i] = data->rr_ttl[i]; - d->rr_data[i] = nextrdata; - memcpy(d->rr_data[i], data->rr_data[i], data->rr_len[i]); - nextrdata += d->rr_len[i]; - } - - return ck; -} - -int -respip_init(struct module_env* env, int id) -{ - (void)env; - (void)id; - return 1; -} - -void -respip_deinit(struct module_env* env, int id) -{ - (void)env; - (void)id; -} - -/** Convert a packed AAAA or A RRset to sockaddr. */ -static int -rdata2sockaddr(const struct packed_rrset_data* rd, uint16_t rtype, size_t i, - struct sockaddr_storage* ss, socklen_t* addrlenp) -{ - /* unbound can accept and cache odd-length AAAA/A records, so we have - * to validate the length. */ - if(rtype == LDNS_RR_TYPE_A && rd->rr_len[i] == 6) { - struct sockaddr_in* sa4 = (struct sockaddr_in*)ss; - - memset(sa4, 0, sizeof(*sa4)); - sa4->sin_family = AF_INET; - memcpy(&sa4->sin_addr, rd->rr_data[i] + 2, - sizeof(sa4->sin_addr)); - *addrlenp = sizeof(*sa4); - return 1; - } else if(rtype == LDNS_RR_TYPE_AAAA && rd->rr_len[i] == 18) { - struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ss; - - memset(sa6, 0, sizeof(*sa6)); - sa6->sin6_family = AF_INET6; - memcpy(&sa6->sin6_addr, rd->rr_data[i] + 2, - sizeof(sa6->sin6_addr)); - *addrlenp = sizeof(*sa6); - return 1; - } - return 0; -} - -/** - * Search the given 'iptree' for response address information that matches - * any of the IP addresses in an AAAA or A in the answer section of the - * response (stored in 'rep'). If found, a pointer to the matched resp_addr - * structure will be returned, and '*rrset_id' is set to the index in - * rep->rrsets for the RRset that contains the matching IP address record - * (the index is normally 0, but can be larger than that if this is a CNAME - * chain or type-ANY response). - * Returns resp_addr holding read lock. - */ -static struct resp_addr* -respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs, - size_t* rrset_id, size_t* rr_id) -{ - size_t i; - struct resp_addr* ra; - struct sockaddr_storage ss; - socklen_t addrlen; - - lock_rw_rdlock(&rs->lock); - for(i=0; ian_numrrsets; i++) { - size_t j; - const struct packed_rrset_data* rd; - uint16_t rtype = ntohs(rep->rrsets[i]->rk.type); - - if(rtype != LDNS_RR_TYPE_A && rtype != LDNS_RR_TYPE_AAAA) - continue; - rd = rep->rrsets[i]->entry.data; - for(j = 0; j < rd->count; j++) { - if(!rdata2sockaddr(rd, rtype, j, &ss, &addrlen)) - continue; - ra = (struct resp_addr*)addr_tree_lookup(&rs->ip_tree, - &ss, addrlen); - if(ra) { - *rrset_id = i; - *rr_id = j; - lock_rw_rdlock(&ra->lock); - lock_rw_unlock(&rs->lock); - return ra; - } - } - } - lock_rw_unlock(&rs->lock); - return NULL; -} - -/** - * See if response-ip or tag data should override the original answer rrset - * (which is rep->rrsets[rrset_id]) and if so override it. - * This is (mostly) equivalent to localzone.c:local_data_answer() but for - * response-ip actions. - * Note that this function distinguishes error conditions from "success but - * not overridden". This is because we want to avoid accidentally applying - * the "no data" action in case of error. - * @param action: action to apply - * @param data: RRset to use for override - * @param qtype: original query type - * @param rep: original reply message - * @param rrset_id: the rrset ID in 'rep' to which the action should apply - * @param new_repp: see respip_rewrite_reply - * @param tag: if >= 0 the tag ID used to determine the action and data - * @param tag_datas: data corresponding to 'tag'. - * @param tag_datas_size: size of 'tag_datas' - * @param tagname: array of tag names, used for logging - * @param num_tags: size of 'tagname', used for logging - * @param redirect_rrsetp: ptr to redirect record - * @param region: region for building new reply - * @return 1 if overridden, 0 if not overridden, -1 on error. - */ -static int -respip_data_answer(enum respip_action action, - struct ub_packed_rrset_key* data, - uint16_t qtype, const struct reply_info* rep, - size_t rrset_id, struct reply_info** new_repp, int tag, - struct config_strlist** tag_datas, size_t tag_datas_size, - char* const* tagname, int num_tags, - struct ub_packed_rrset_key** redirect_rrsetp, struct regional* region) -{ - struct ub_packed_rrset_key* rp = data; - struct reply_info* new_rep; - *redirect_rrsetp = NULL; - - if(action == respip_redirect && tag != -1 && - (size_t)tagrrsets[rrset_id]->rk.dname; - dataqinfo.qname_len = rep->rrsets[rrset_id]->rk.dname_len; - dataqinfo.qtype = ntohs(rep->rrsets[rrset_id]->rk.type); - dataqinfo.qclass = ntohs(rep->rrsets[rrset_id]->rk.rrset_class); - - memset(&r, 0, sizeof(r)); - if(local_data_find_tag_datas(&dataqinfo, tag_datas[tag], &r, - region)) { - verbose(VERB_ALGO, - "response-ip redirect with tag data [%d] %s", - tag, (tagrk.dname = rep->rrsets[rrset_id]->rk.dname; - rp->rk.dname_len = rep->rrsets[rrset_id]->rk.dname_len; - } - - /* Build a new reply with redirect rrset. We keep any preceding CNAMEs - * and replace the address rrset that triggers the action. If it's - * type ANY query, however, no other answer records should be kept - * (note that it can't be a CNAME chain in this case due to - * sanitizing). */ - if(qtype == LDNS_RR_TYPE_ANY) - rrset_id = 0; - new_rep = make_new_reply_info(rep, region, rrset_id + 1, rrset_id); - if(!new_rep) - return -1; - rp->rk.flags |= PACKED_RRSET_FIXEDTTL; /* avoid adjusting TTL */ - new_rep->rrsets[rrset_id] = rp; - - *redirect_rrsetp = rp; - *new_repp = new_rep; - return 1; -} - -/** - * apply response ip action in case where no action data is provided. - * this is similar to localzone.c:lz_zone_answer() but simplified due to - * the characteristics of response ip: - * - 'deny' variants will be handled at the caller side - * - no specific processing for 'transparent' variants: unlike local zones, - * there is no such a case of 'no data but name existing'. so all variants - * just mean 'transparent if no data'. - * @param qtype: query type - * @param action: found action - * @param rep: - * @param new_repp - * @param rrset_id - * @param region: region for building new reply - * @return 1 on success, 0 on error. - */ -static int -respip_nodata_answer(uint16_t qtype, enum respip_action action, - const struct reply_info *rep, size_t rrset_id, - struct reply_info** new_repp, struct regional* region) -{ - struct reply_info* new_rep; - - if(action == respip_refuse || action == respip_always_refuse) { - new_rep = make_new_reply_info(rep, region, 0, 0); - if(!new_rep) - return 0; - FLAGS_SET_RCODE(new_rep->flags, LDNS_RCODE_REFUSED); - *new_repp = new_rep; - return 1; - } else if(action == respip_static || action == respip_redirect || - action == respip_always_nxdomain || - action == respip_always_nodata || - action == respip_inform_redirect) { - /* Since we don't know about other types of the owner name, - * we generally return NOERROR/NODATA unless an NXDOMAIN action - * is explicitly specified. */ - int rcode = (action == respip_always_nxdomain)? - LDNS_RCODE_NXDOMAIN:LDNS_RCODE_NOERROR; - /* We should empty the answer section except for any preceding - * CNAMEs (in that case rrset_id > 0). Type-ANY case is - * special as noted in respip_data_answer(). */ - if(qtype == LDNS_RR_TYPE_ANY) - rrset_id = 0; - new_rep = make_new_reply_info(rep, region, rrset_id, rrset_id); - if(!new_rep) - return 0; - FLAGS_SET_RCODE(new_rep->flags, rcode); - *new_repp = new_rep; - return 1; - } - - return 1; -} - -/** Populate action info structure with the results of response-ip action - * processing, iff as the result of response-ip processing we are actually - * taking some action. Only action is set if action_only is true. - * Returns true on success, false on failure. - */ -static int -populate_action_info(struct respip_action_info* actinfo, - enum respip_action action, const struct resp_addr* raddr, - const struct ub_packed_rrset_key* ATTR_UNUSED(rrset), - int ATTR_UNUSED(tag), const struct respip_set* ATTR_UNUSED(ipset), - int ATTR_UNUSED(action_only), struct regional* region, int rpz_used, - int rpz_log, char* log_name, int rpz_cname_override) -{ - if(action == respip_none || !raddr) - return 1; - actinfo->action = action; - actinfo->rpz_used = rpz_used; - actinfo->rpz_log = rpz_log; - actinfo->log_name = log_name; - actinfo->rpz_cname_override = rpz_cname_override; - - /* for inform variants, make a copy of the matched address block for - * later logging. We make a copy to proactively avoid disruption if - * and when we allow a dynamic update to the respip tree. */ - if(action == respip_inform || action == respip_inform_deny || - rpz_used) { - struct respip_addr_info* a = - regional_alloc_zero(region, sizeof(*a)); - if(!a) { - log_err("out of memory"); - return 0; - } - a->addr = raddr->node.addr; - a->addrlen = raddr->node.addrlen; - a->net = raddr->node.net; - actinfo->addrinfo = a; - } - - return 1; -} - -static int -respip_use_rpz(struct resp_addr* raddr, struct rpz* r, - enum respip_action* action, - struct ub_packed_rrset_key** data, int* rpz_log, char** log_name, - int* rpz_cname_override, struct regional* region, int* is_rpz, - int* rpz_passthru) -{ - if(rpz_passthru && *rpz_passthru) - return 0; - if(r->action_override == RPZ_DISABLED_ACTION) { - *is_rpz = 0; - return 1; - } - else if(r->action_override == RPZ_NO_OVERRIDE_ACTION) - *action = raddr->action; - else - *action = rpz_action_to_respip_action(r->action_override); - if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION && - r->cname_override) { - *data = r->cname_override; - *rpz_cname_override = 1; - } - if(*action == respip_always_transparent /* RPZ_PASSTHRU_ACTION */ - && rpz_passthru) - *rpz_passthru = 1; - *rpz_log = r->log; - if(r->log_name) - if(!(*log_name = regional_strdup(region, r->log_name))) - return 0; - *is_rpz = 1; - return 1; -} - -int -respip_rewrite_reply(const struct query_info* qinfo, - const struct respip_client_info* cinfo, const struct reply_info* rep, - struct reply_info** new_repp, struct respip_action_info* actinfo, - struct ub_packed_rrset_key** alias_rrset, int search_only, - struct regional* region, struct auth_zones* az, int* rpz_passthru) -{ - const uint8_t* ctaglist; - size_t ctaglen; - const uint8_t* tag_actions; - size_t tag_actions_size; - struct config_strlist** tag_datas; - size_t tag_datas_size; - struct view* view = NULL; - struct respip_set* ipset = NULL; - size_t rrset_id = 0, rr_id = 0; - enum respip_action action = respip_none; - int tag = -1; - struct resp_addr* raddr = NULL; - int ret = 1; - struct ub_packed_rrset_key* redirect_rrset = NULL; - struct rpz* r; - struct auth_zone* a = NULL; - struct ub_packed_rrset_key* data = NULL; - int rpz_used = 0; - int rpz_log = 0; - int rpz_cname_override = 0; - char* log_name = NULL; - - if(!cinfo) - goto done; - ctaglist = cinfo->taglist; - ctaglen = cinfo->taglen; - tag_actions = cinfo->tag_actions; - tag_actions_size = cinfo->tag_actions_size; - tag_datas = cinfo->tag_datas; - tag_datas_size = cinfo->tag_datas_size; - view = cinfo->view; - ipset = cinfo->respip_set; - - log_assert(ipset); - - /** Try to use response-ip config from the view first; use - * global response-ip config if we don't have the view or we don't - * have the matching per-view config (and the view allows the use - * of global data in this case). - * Note that we lock the view even if we only use view members that - * currently don't change after creation. This is for safety for - * future possible changes as the view documentation seems to expect - * any of its member can change in the view's lifetime. - * Note also that we assume 'view' is valid in this function, which - * should be safe (see unbound bug #1191) */ - if(view) { - lock_rw_rdlock(&view->lock); - if(view->respip_set) { - if((raddr = respip_addr_lookup(rep, - view->respip_set, &rrset_id, &rr_id))) { - /** for per-view respip directives the action - * can only be direct (i.e. not tag-based) */ - action = raddr->action; - } - } - if(!raddr && !view->isfirst) - goto done; - if(!raddr && view->isfirst) { - lock_rw_unlock(&view->lock); - view = NULL; - } - } - if(!raddr && (raddr = respip_addr_lookup(rep, ipset, - &rrset_id, &rr_id))) { - action = (enum respip_action)local_data_find_tag_action( - raddr->taglist, raddr->taglen, ctaglist, ctaglen, - tag_actions, tag_actions_size, - (enum localzone_type)raddr->action, &tag, - ipset->tagname, ipset->num_tags); - } - lock_rw_rdlock(&az->rpz_lock); - for(a = az->rpz_first; a && !raddr && !(rpz_passthru && *rpz_passthru); a = a->rpz_az_next) { - lock_rw_rdlock(&a->lock); - r = a->rpz; - if(!r->taglist || taglist_intersect(r->taglist, - r->taglistlen, ctaglist, ctaglen)) { - if((raddr = respip_addr_lookup(rep, - r->respip_set, &rrset_id, &rr_id))) { - if(!respip_use_rpz(raddr, r, &action, &data, - &rpz_log, &log_name, &rpz_cname_override, - region, &rpz_used, rpz_passthru)) { - log_err("out of memory"); - lock_rw_unlock(&raddr->lock); - lock_rw_unlock(&a->lock); - lock_rw_unlock(&az->rpz_lock); - return 0; - } - if(rpz_used) { - if(verbosity >= VERB_ALGO) { - struct sockaddr_storage ss; - socklen_t ss_len = 0; - char nm[256], ip[256]; - char qn[255+1]; - if(!rdata2sockaddr(rep->rrsets[rrset_id]->entry.data, ntohs(rep->rrsets[rrset_id]->rk.type), rr_id, &ss, &ss_len)) - snprintf(ip, sizeof(ip), "invalidRRdata"); - else - addr_to_str(&ss, ss_len, ip, sizeof(ip)); - dname_str(qinfo->qname, qn); - addr_to_str(&raddr->node.addr, - raddr->node.addrlen, - nm, sizeof(nm)); - verbose(VERB_ALGO, "respip: rpz: response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action))); - } - /* break to make sure 'a' stays pointed - * to used auth_zone, and keeps lock */ - break; - } - lock_rw_unlock(&raddr->lock); - raddr = NULL; - actinfo->rpz_disabled++; - } - } - lock_rw_unlock(&a->lock); - } - lock_rw_unlock(&az->rpz_lock); - if(raddr && !search_only) { - int result = 0; - - /* first, see if we have response-ip or tag action for the - * action except for 'always' variants. */ - if(action != respip_always_refuse - && action != respip_always_transparent - && action != respip_always_nxdomain - && action != respip_always_nodata - && action != respip_always_deny - && (result = respip_data_answer(action, - (data) ? data : raddr->data, qinfo->qtype, rep, - rrset_id, new_repp, tag, tag_datas, tag_datas_size, - ipset->tagname, ipset->num_tags, &redirect_rrset, - region)) < 0) { - ret = 0; - goto done; - } - - /* if no action data applied, take action specific to the - * action without data. */ - if(!result && !respip_nodata_answer(qinfo->qtype, action, rep, - rrset_id, new_repp, region)) { - ret = 0; - goto done; - } - } - done: - if(view) { - lock_rw_unlock(&view->lock); - } - if(ret) { - /* If we're redirecting the original answer to a - * CNAME, record the CNAME rrset so the caller can take - * the appropriate action. Note that we don't check the - * action type; it should normally be 'redirect', but it - * can be of other type when a data-dependent tag action - * uses redirect response-ip data. - */ - if(redirect_rrset && - redirect_rrset->rk.type == ntohs(LDNS_RR_TYPE_CNAME) && - qinfo->qtype != LDNS_RR_TYPE_ANY) - *alias_rrset = redirect_rrset; - /* on success, populate respip result structure */ - ret = populate_action_info(actinfo, action, raddr, - redirect_rrset, tag, ipset, search_only, region, - rpz_used, rpz_log, log_name, rpz_cname_override); - } - if(raddr) { - lock_rw_unlock(&raddr->lock); - } - if(rpz_used) { - lock_rw_unlock(&a->lock); - } - return ret; -} - -static int -generate_cname_request(struct module_qstate* qstate, - struct ub_packed_rrset_key* alias_rrset) -{ - struct module_qstate* subq = NULL; - struct query_info subqi; - - memset(&subqi, 0, sizeof(subqi)); - get_cname_target(alias_rrset, &subqi.qname, &subqi.qname_len); - if(!subqi.qname) - return 0; /* unexpected: not a valid CNAME RDATA */ - subqi.qtype = qstate->qinfo.qtype; - subqi.qclass = qstate->qinfo.qclass; - fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - return (*qstate->env->attach_sub)(qstate, &subqi, BIT_RD, 0, 0, &subq); -} - -void -respip_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct respip_qstate* rq = (struct respip_qstate*)qstate->minfo[id]; - - log_query_info(VERB_QUERY, "respip operate: query", &qstate->qinfo); - (void)outbound; - - if(event == module_event_new || event == module_event_pass) { - if(!rq) { - rq = regional_alloc_zero(qstate->region, sizeof(*rq)); - if(!rq) - goto servfail; - rq->state = RESPIP_INIT; - qstate->minfo[id] = rq; - } - if(rq->state == RESPIP_SUBQUERY_FINISHED) { - qstate->ext_state[id] = module_finished; - return; - } - verbose(VERB_ALGO, "respip: pass to next module"); - qstate->ext_state[id] = module_wait_module; - } else if(event == module_event_moddone) { - /* If the reply may be subject to response-ip rewriting - * according to the query type, check the actions. If a - * rewrite is necessary, we'll replace the reply in qstate - * with the new one. */ - enum module_ext_state next_state = module_finished; - - if((qstate->qinfo.qtype == LDNS_RR_TYPE_A || - qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA || - qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) && - qstate->return_msg && qstate->return_msg->rep) { - struct reply_info* new_rep = qstate->return_msg->rep; - struct ub_packed_rrset_key* alias_rrset = NULL; - struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL}; - actinfo.action = respip_none; - - if(!respip_rewrite_reply(&qstate->qinfo, - qstate->client_info, qstate->return_msg->rep, - &new_rep, &actinfo, &alias_rrset, 0, - qstate->region, qstate->env->auth_zones, - &qstate->rpz_passthru)) { - goto servfail; - } - if(actinfo.action != respip_none) { - /* save action info for logging on a - * per-front-end-query basis */ - if(!(qstate->respip_action_info = - regional_alloc_init(qstate->region, - &actinfo, sizeof(actinfo)))) - { - log_err("out of memory"); - goto servfail; - } - } else { - qstate->respip_action_info = NULL; - } - if (actinfo.action == respip_always_deny || - (new_rep == qstate->return_msg->rep && - (actinfo.action == respip_deny || - actinfo.action == respip_inform_deny))) { - /* for deny-variant actions (unless response-ip - * data is applied), mark the query state so - * the response will be dropped for all - * clients. */ - qstate->is_drop = 1; - } else if(alias_rrset) { - if(!generate_cname_request(qstate, alias_rrset)) - goto servfail; - next_state = module_wait_subquery; - } - qstate->return_msg->rep = new_rep; - } - qstate->ext_state[id] = next_state; - } else - qstate->ext_state[id] = module_finished; - - return; - - servfail: - qstate->return_rcode = LDNS_RCODE_SERVFAIL; - qstate->return_msg = NULL; -} - -int -respip_merge_cname(struct reply_info* base_rep, - const struct query_info* qinfo, const struct reply_info* tgt_rep, - const struct respip_client_info* cinfo, int must_validate, - struct reply_info** new_repp, struct regional* region, - struct auth_zones* az) -{ - struct reply_info* new_rep; - struct reply_info* tmp_rep = NULL; /* just a placeholder */ - struct ub_packed_rrset_key* alias_rrset = NULL; /* ditto */ - uint16_t tgt_rcode; - size_t i, j; - struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL}; - actinfo.action = respip_none; - - /* If the query for the CNAME target would result in an unusual rcode, - * we generally translate it as a failure for the base query - * (which would then be translated into SERVFAIL). The only exception - * is NXDOMAIN and YXDOMAIN, which are passed to the end client(s). - * The YXDOMAIN case would be rare but still possible (when - * DNSSEC-validated DNAME has been cached but synthesizing CNAME - * can't be generated due to length limitation) */ - tgt_rcode = FLAGS_GET_RCODE(tgt_rep->flags); - if((tgt_rcode != LDNS_RCODE_NOERROR && - tgt_rcode != LDNS_RCODE_NXDOMAIN && - tgt_rcode != LDNS_RCODE_YXDOMAIN) || - (must_validate && tgt_rep->security <= sec_status_bogus)) { - return 0; - } - - /* see if the target reply would be subject to a response-ip action. */ - if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo, - &alias_rrset, 1, region, az, NULL)) - return 0; - if(actinfo.action != respip_none) { - log_info("CNAME target of redirect response-ip action would " - "be subject to response-ip action, too; stripped"); - *new_repp = base_rep; - return 1; - } - - /* Append target reply to the base. Since we cannot assume - * tgt_rep->rrsets is valid throughout the lifetime of new_rep - * or it can be safely shared by multiple threads, we need to make a - * deep copy. */ - new_rep = make_new_reply_info(base_rep, region, - base_rep->an_numrrsets + tgt_rep->an_numrrsets, - base_rep->an_numrrsets); - if(!new_rep) - return 0; - for(i=0,j=base_rep->an_numrrsets; ian_numrrsets; i++,j++) { - new_rep->rrsets[j] = respip_copy_rrset(tgt_rep->rrsets[i], region); - if(!new_rep->rrsets[j]) - return 0; - } - - FLAGS_SET_RCODE(new_rep->flags, tgt_rcode); - *new_repp = new_rep; - return 1; -} - -void -respip_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) -{ - struct respip_qstate* rq = (struct respip_qstate*)super->minfo[id]; - struct reply_info* new_rep = NULL; - - rq->state = RESPIP_SUBQUERY_FINISHED; - - /* respip subquery should have always been created with a valid reply - * in super. */ - log_assert(super->return_msg && super->return_msg->rep); - - /* return_msg can be NULL when, e.g., the sub query resulted in - * SERVFAIL, in which case we regard it as a failure of the original - * query. Other checks are probably redundant, but we check them - * for safety. */ - if(!qstate->return_msg || !qstate->return_msg->rep || - qstate->return_rcode != LDNS_RCODE_NOERROR) - goto fail; - - if(!respip_merge_cname(super->return_msg->rep, &qstate->qinfo, - qstate->return_msg->rep, super->client_info, - super->env->need_to_validate, &new_rep, super->region, - qstate->env->auth_zones)) - goto fail; - super->return_msg->rep = new_rep; - return; - - fail: - super->return_rcode = LDNS_RCODE_SERVFAIL; - super->return_msg = NULL; - return; -} - -void -respip_clear(struct module_qstate* qstate, int id) -{ - qstate->minfo[id] = NULL; -} - -size_t -respip_get_mem(struct module_env* env, int id) -{ - (void)env; - (void)id; - return 0; -} - -/** - * The response-ip function block - */ -static struct module_func_block respip_block = { - "respip", - &respip_init, &respip_deinit, &respip_operate, &respip_inform_super, - &respip_clear, &respip_get_mem -}; - -struct module_func_block* -respip_get_funcblock(void) -{ - return &respip_block; -} - -enum respip_action -resp_addr_get_action(const struct resp_addr* addr) -{ - return addr ? addr->action : respip_none; -} - -struct ub_packed_rrset_key* -resp_addr_get_rrset(struct resp_addr* addr) -{ - return addr ? addr->data : NULL; -} - -int -respip_set_is_empty(const struct respip_set* set) -{ - return set ? set->ip_tree.count == 0 : 1; -} - -void -respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname, - uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - char srcip[128], respip[128], txt[512]; - unsigned port; - struct respip_addr_info* respip_addr = respip_actinfo->addrinfo; - size_t txtlen = 0; - const char* actionstr = NULL; - - if(local_alias) - qname = local_alias->rrset->rk.dname; - port = (unsigned)((addr->ss_family == AF_INET) ? - ntohs(((struct sockaddr_in*)addr)->sin_port) : - ntohs(((struct sockaddr_in6*)addr)->sin6_port)); - addr_to_str(addr, addrlen, srcip, sizeof(srcip)); - addr_to_str(&respip_addr->addr, respip_addr->addrlen, - respip, sizeof(respip)); - if(respip_actinfo->rpz_log) { - txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s", - "rpz: applied "); - if(respip_actinfo->rpz_cname_override) - actionstr = rpz_action_to_string( - RPZ_CNAME_OVERRIDE_ACTION); - else - actionstr = rpz_action_to_string( - respip_action_to_rpz_action( - respip_actinfo->action)); - } - if(respip_actinfo->log_name) { - txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, - "[%s] ", respip_actinfo->log_name); - } - snprintf(txt+txtlen, sizeof(txt)-txtlen, - "%s/%d %s %s@%u", respip, respip_addr->net, - (actionstr) ? actionstr : "inform", srcip, port); - log_nametypeclass(NO_VERBOSE, txt, qname, qtype, qclass); -} diff --git a/crates/libunbound-sys/unbound/respip/respip.h b/crates/libunbound-sys/unbound/respip/respip.h deleted file mode 100644 index e4ab5cc9..00000000 --- a/crates/libunbound-sys/unbound/respip/respip.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * respip/respip.h - IP-based response modification module - */ - -/** - * \file - * - * This file contains a module that selectively modifies query responses - * based on their AAAA/A IP addresses. - */ - -#ifndef RESPIP_RESPIP_H -#define RESPIP_RESPIP_H - -#include "util/module.h" -#include "services/localzone.h" -#include "util/locks.h" - -/** - * Conceptual set of IP addresses for response AAAA or A records that should - * trigger special actions. - */ -struct respip_set { - struct regional* region; - struct rbtree_type ip_tree; - lock_rw_type lock; /* lock on the respip tree */ - char* const* tagname; /* shallow copy of tag names, for logging */ - int num_tags; /* number of tagname entries */ -}; - - -/** An address span with response control information */ -struct resp_addr { - /** node in address tree */ - struct addr_tree_node node; - /** lock on the node item */ - lock_rw_type lock; - /** tag bitlist */ - uint8_t* taglist; - /** length of the taglist (in bytes) */ - size_t taglen; - /** action for this address span */ - enum respip_action action; - /** "local data" for this node */ - struct ub_packed_rrset_key* data; -}; - - -/** - * Forward declaration for the structure that represents a tree of view data. - */ - -struct views; - -struct respip_addr_info; - -/** - * Client-specific attributes that can affect IP-based actions. - * This is essentially a subset of acl_addr (except for respip_set) but - * defined as a separate structure to avoid dependency on the daemon-specific - * structure. - * respip_set is supposed to refer to the response-ip set for the global view. - */ -struct respip_client_info { - uint8_t* taglist; - size_t taglen; - uint8_t* tag_actions; - size_t tag_actions_size; - struct config_strlist** tag_datas; - size_t tag_datas_size; - struct view* view; - struct respip_set* respip_set; -}; - -/** - * Data items representing the result of response-ip processing. - * Note: this structure currently only define a few members, but exists - * as a separate struct mainly for the convenience of custom extensions. - */ -struct respip_action_info { - enum respip_action action; - int rpz_used; - int rpz_log; - int rpz_disabled; - char* log_name; - int rpz_cname_override; - struct respip_addr_info* addrinfo; /* set only for inform variants */ -}; - -/** - * Forward declaration for the structure that represents a node in the - * respip_set address tree - */ -struct resp_addr; - -/** - * Create response IP set. - * @return new struct or NULL on error. - */ -struct respip_set* respip_set_create(void); - -/** - * Delete response IP set. - * @param set: to delete. - */ -void respip_set_delete(struct respip_set* set); - -/** - * Apply response-ip config settings to the global (default) view. - * It assumes exclusive access to set (no internal locks). - * @param set: processed global respip config data - * @param cfg: config data. - * @return 1 on success, 0 on error. - */ -int respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg); - -/** - * Apply response-ip config settings in named views. - * @param vs: view structures with processed config data - * @param cfg: config data. - * @param have_view_respip_cfg: set to true if any named view has respip - * configuration; otherwise set to false - * @return 1 on success, 0 on error. - */ -int respip_views_apply_cfg(struct views* vs, struct config_file* cfg, - int* have_view_respip_cfg); - -/** - * Merge two replies to build a complete CNAME chain. - * It appends the content of 'tgt_rep' to 'base_rep', assuming (but not - * checking) the former ends with a CNAME and the latter resolves its target. - * A merged new reply will be built using 'region' and *new_repp will point - * to the new one on success. - * If the target reply would also be subject to a response-ip action for - * 'cinfo', this function uses 'base_rep' as the merged reply, ignoring - * 'tgt_rep'. This is for avoiding cases like a CNAME loop or failure of - * applying an action to an address. - * RRSIGs in 'tgt_rep' will be excluded in the merged reply, as the resulting - * reply is assumed to be faked due to a response-ip action and can't be - * considered secure in terms of DNSSEC. - * The caller must ensure that neither 'base_rep' nor 'tgt_rep' can be modified - * until this function returns. - * @param base_rep: the reply info containing an incomplete CNAME. - * @param qinfo: query info corresponding to 'base_rep'. - * @param tgt_rep: the reply info that completes the CNAME chain. - * @param cinfo: client info corresponding to 'base_rep'. - * @param must_validate: whether 'tgt_rep' must be DNSSEC-validated. - * @param new_repp: pointer placeholder for the merged reply. will be intact - * on error. - * @param region: allocator to build *new_repp. - * @param az: auth zones containing RPZ information. - * @return 1 on success, 0 on error. - */ -int respip_merge_cname(struct reply_info* base_rep, - const struct query_info* qinfo, const struct reply_info* tgt_rep, - const struct respip_client_info* cinfo, int must_validate, - struct reply_info** new_repp, struct regional* region, - struct auth_zones* az); - -/** - * See if any IP-based action should apply to any IP address of AAAA/A answer - * record in the reply. If so, apply the action. In some cases it rewrites - * the reply rrsets, in which case *new_repp will point to the updated reply - * info. Depending on the action, some of the rrsets in 'rep' will be - * shallow-copied into '*new_repp'; the caller must ensure that the rrsets - * in 'rep' are valid throughout the lifetime of *new_repp, and it must - * provide appropriate mutex if the rrsets can be shared by multiple threads. - * @param qinfo: query info corresponding to the reply. - * @param cinfo: client-specific info to identify the best matching action. - * can be NULL. - * @param rep: original reply info. must not be NULL. - * @param new_repp: can be set to the rewritten reply info (intact on failure). - * @param actinfo: result of response-ip processing - * @param alias_rrset: must not be NULL. - * @param search_only: if true, only check if an action would apply. actionp - * will be set (or intact) accordingly but the modified reply won't be built. - * @param az: auth zones containing RPZ information. - * @param region: allocator to build *new_repp. - * @param rpz_passthru: keeps track of query state can have passthru that - * stops further rpz processing. Or NULL for cached answer processing. - * @return 1 on success, 0 on error. - */ -int respip_rewrite_reply(const struct query_info* qinfo, - const struct respip_client_info* cinfo, - const struct reply_info *rep, struct reply_info** new_repp, - struct respip_action_info* actinfo, - struct ub_packed_rrset_key** alias_rrset, - int search_only, struct regional* region, struct auth_zones* az, - int* rpz_passthru); - -/** - * Get the response-ip function block. - * @return: function block with function pointers to response-ip methods. - */ -struct module_func_block* respip_get_funcblock(void); - -/** response-ip init */ -int respip_init(struct module_env* env, int id); - -/** response-ip deinit */ -void respip_deinit(struct module_env* env, int id); - -/** response-ip operate on a query */ -void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound); - -/** inform response-ip super */ -void respip_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** response-ip cleanup query state */ -void respip_clear(struct module_qstate* qstate, int id); - -/** - * returns address of the IP address tree of the specified respip set; - * returns NULL for NULL input; exists for test purposes only - */ -struct rbtree_type* respip_set_get_tree(struct respip_set* set); - -/** - * returns respip action for the specified node in the respip address - * returns respip_none for NULL input; exists for test purposes only - */ -enum respip_action resp_addr_get_action(const struct resp_addr* addr); - -/** - * returns rrset portion of the specified node in the respip address - * tree; returns NULL for NULL input; exists for test purposes only - */ -struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr); - -/** response-ip alloc size routine */ -size_t respip_get_mem(struct module_env* env, int id); - -/** - * respip set emptiness test - * @param set respip set to test - * @return 0 if the specified set exists (non-NULL) and is non-empty; - * otherwise returns 1 - */ -int respip_set_is_empty(const struct respip_set* set); - -/** - * print log information for a query subject to an inform or inform-deny - * response-ip action. - * @param respip_actinfo: response-ip information that causes the action - * @param qname: query name in the context, will be ignored if local_alias is - * non-NULL. - * @param qtype: query type, in host byte order. - * @param qclass: query class, in host byte order. - * @param local_alias: set to a local alias if the query matches an alias in - * a local zone. In this case its owner name will be considered the actual - * query name. - * @param addr: the client's source address and port. - * @param addrlen: the client's source address length. - */ -void respip_inform_print(struct respip_action_info* respip_actinfo, - uint8_t* qname, uint16_t qtype, uint16_t qclass, - struct local_rrset* local_alias, struct sockaddr_storage* addr, - socklen_t addrlen); - -/** - * Find resp_addr in tree, create and add to tree if it does not exist. - * @param set: struct containing the tree and region to alloc new node on. - * should hold write lock. - * @param addr: address to look up. - * @param addrlen: length of addr. - * @param net: netblock to lookup. - * @param create: create node if it does not exist when 1. - * @param ipstr: human redable ip string, for logging. - * @return newly created of found node, not holding lock. - */ -struct resp_addr* -respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr, - socklen_t addrlen, int net, int create, const char* ipstr); - -/** - * Add RR to resp_addr's RRset. Create RRset if not existing. - * @param region: region to alloc RR(set). - * @param raddr: resp_addr containing RRset. Must hold write lock. - * @param rrtype: RR type. - * @param rrclass: RR class. - * @param ttl: TTL. - * @param rdata: RDATA. - * @param rdata_len: length of rdata. - * @param rrstr: RR as string, for logging - * @param netblockstr: netblock as string, for logging - * @return 0 on error - */ -int -respip_enter_rr(struct regional* region, struct resp_addr* raddr, - uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, - size_t rdata_len, const char* rrstr, const char* netblockstr); - -/** - * Delete resp_addr node from tree. - * @param set: struct containing tree. Must hold write lock. - * @param node: node to delete. Not locked. - */ -void -respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); - -struct ub_packed_rrset_key* -respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region); -#endif /* RESPIP_RESPIP_H */ diff --git a/crates/libunbound-sys/unbound/services/authzone.c b/crates/libunbound-sys/unbound/services/authzone.c deleted file mode 100644 index cd3ef8db..00000000 --- a/crates/libunbound-sys/unbound/services/authzone.c +++ /dev/null @@ -1,8533 +0,0 @@ -/* - * services/authzone.c - authoritative zone that is locally hosted. - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the functions for an authority zone. This zone - * is queried by the iterator, just like a stub or forward zone, but then - * the data is locally held. - */ - -#include "config.h" -#include "services/authzone.h" -#include "util/data/dname.h" -#include "util/data/msgparse.h" -#include "util/data/msgreply.h" -#include "util/data/msgencode.h" -#include "util/data/packed_rrset.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "util/netevent.h" -#include "util/config_file.h" -#include "util/log.h" -#include "util/module.h" -#include "util/random.h" -#include "services/cache/dns.h" -#include "services/outside_network.h" -#include "services/listen_dnsport.h" -#include "services/mesh.h" -#include "sldns/rrdef.h" -#include "sldns/pkthdr.h" -#include "sldns/sbuffer.h" -#include "sldns/str2wire.h" -#include "sldns/wire2str.h" -#include "sldns/parseutil.h" -#include "sldns/keyraw.h" -#include "validator/val_nsec3.h" -#include "validator/val_nsec.h" -#include "validator/val_secalgo.h" -#include "validator/val_sigcrypt.h" -#include "validator/val_anchor.h" -#include "validator/val_utils.h" -#include - -/** bytes to use for NSEC3 hash buffer. 20 for sha1 */ -#define N3HASHBUFLEN 32 -/** max number of CNAMEs we are willing to follow (in one answer) */ -#define MAX_CNAME_CHAIN 8 -/** timeout for probe packets for SOA */ -#define AUTH_PROBE_TIMEOUT 100 /* msec */ -/** when to stop with SOA probes (when exponential timeouts exceed this) */ -#define AUTH_PROBE_TIMEOUT_STOP 1000 /* msec */ -/* auth transfer timeout for TCP connections, in msec */ -#define AUTH_TRANSFER_TIMEOUT 10000 /* msec */ -/* auth transfer max backoff for failed transfers and probes */ -#define AUTH_TRANSFER_MAX_BACKOFF 86400 /* sec */ -/* auth http port number */ -#define AUTH_HTTP_PORT 80 -/* auth https port number */ -#define AUTH_HTTPS_PORT 443 -/* max depth for nested $INCLUDEs */ -#define MAX_INCLUDE_DEPTH 10 -/** number of timeouts before we fallback from IXFR to AXFR, - * because some versions of servers (eg. dnsmasq) drop IXFR packets. */ -#define NUM_TIMEOUTS_FALLBACK_IXFR 3 - -/** pick up nextprobe task to start waiting to perform transfer actions */ -static void xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env, - int failure, int lookup_only); -/** move to sending the probe packets, next if fails. task_probe */ -static void xfr_probe_send_or_end(struct auth_xfer* xfr, - struct module_env* env); -/** pick up probe task with specified(or NULL) destination first, - * or transfer task if nothing to probe, or false if already in progress */ -static int xfr_start_probe(struct auth_xfer* xfr, struct module_env* env, - struct auth_master* spec); -/** delete xfer structure (not its tree entry) */ -void auth_xfer_delete(struct auth_xfer* xfr); - -/** create new dns_msg */ -static struct dns_msg* -msg_create(struct regional* region, struct query_info* qinfo) -{ - struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(!msg) - return NULL; - msg->qinfo.qname = regional_alloc_init(region, qinfo->qname, - qinfo->qname_len); - if(!msg->qinfo.qname) - return NULL; - msg->qinfo.qname_len = qinfo->qname_len; - msg->qinfo.qtype = qinfo->qtype; - msg->qinfo.qclass = qinfo->qclass; - msg->qinfo.local_alias = NULL; - /* non-packed reply_info, because it needs to grow the array */ - msg->rep = (struct reply_info*)regional_alloc_zero(region, - sizeof(struct reply_info)-sizeof(struct rrset_ref)); - if(!msg->rep) - return NULL; - msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA); - msg->rep->authoritative = 1; - msg->rep->reason_bogus = LDNS_EDE_NONE; - msg->rep->qdcount = 1; - /* rrsets is NULL, no rrsets yet */ - return msg; -} - -/** grow rrset array by one in msg */ -static int -msg_grow_array(struct regional* region, struct dns_msg* msg) -{ - if(msg->rep->rrsets == NULL) { - msg->rep->rrsets = regional_alloc_zero(region, - sizeof(struct ub_packed_rrset_key*)*(msg->rep->rrset_count+1)); - if(!msg->rep->rrsets) - return 0; - } else { - struct ub_packed_rrset_key** rrsets_old = msg->rep->rrsets; - msg->rep->rrsets = regional_alloc_zero(region, - sizeof(struct ub_packed_rrset_key*)*(msg->rep->rrset_count+1)); - if(!msg->rep->rrsets) - return 0; - memmove(msg->rep->rrsets, rrsets_old, - sizeof(struct ub_packed_rrset_key*)*msg->rep->rrset_count); - } - return 1; -} - -/** get ttl of rrset */ -static time_t -get_rrset_ttl(struct ub_packed_rrset_key* k) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - k->entry.data; - return d->ttl; -} - -/** Copy rrset into region from domain-datanode and packet rrset */ -static struct ub_packed_rrset_key* -auth_packed_rrset_copy_region(struct auth_zone* z, struct auth_data* node, - struct auth_rrset* rrset, struct regional* region, time_t adjust) -{ - struct ub_packed_rrset_key key; - memset(&key, 0, sizeof(key)); - key.entry.key = &key; - key.entry.data = rrset->data; - key.rk.dname = node->name; - key.rk.dname_len = node->namelen; - key.rk.type = htons(rrset->type); - key.rk.rrset_class = htons(z->dclass); - key.entry.hash = rrset_key_hash(&key.rk); - return packed_rrset_copy_region(&key, region, adjust); -} - -/** fix up msg->rep TTL and prefetch ttl */ -static void -msg_ttl(struct dns_msg* msg) -{ - if(msg->rep->rrset_count == 0) return; - if(msg->rep->rrset_count == 1) { - msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[0]); - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - } else if(get_rrset_ttl(msg->rep->rrsets[msg->rep->rrset_count-1]) < - msg->rep->ttl) { - msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[ - msg->rep->rrset_count-1]); - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - } -} - -/** see if rrset is a duplicate in the answer message */ -static int -msg_rrset_duplicate(struct dns_msg* msg, uint8_t* nm, size_t nmlen, - uint16_t type, uint16_t dclass) -{ - size_t i; - for(i=0; irep->rrset_count; i++) { - struct ub_packed_rrset_key* k = msg->rep->rrsets[i]; - if(ntohs(k->rk.type) == type && k->rk.dname_len == nmlen && - ntohs(k->rk.rrset_class) == dclass && - query_dname_compare(k->rk.dname, nm) == 0) - return 1; - } - return 0; -} - -/** add rrset to answer section (no auth, add rrsets yet) */ -static int -msg_add_rrset_an(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset) -{ - log_assert(msg->rep->ns_numrrsets == 0); - log_assert(msg->rep->ar_numrrsets == 0); - if(!rrset || !node) - return 1; - if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type, - z->dclass)) - return 1; - /* grow array */ - if(!msg_grow_array(region, msg)) - return 0; - /* copy it */ - if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) - return 0; - msg->rep->rrset_count++; - msg->rep->an_numrrsets++; - msg_ttl(msg); - return 1; -} - -/** add rrset to authority section (no additional section rrsets yet) */ -static int -msg_add_rrset_ns(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset) -{ - log_assert(msg->rep->ar_numrrsets == 0); - if(!rrset || !node) - return 1; - if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type, - z->dclass)) - return 1; - /* grow array */ - if(!msg_grow_array(region, msg)) - return 0; - /* copy it */ - if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) - return 0; - msg->rep->rrset_count++; - msg->rep->ns_numrrsets++; - msg_ttl(msg); - return 1; -} - -/** add rrset to additional section */ -static int -msg_add_rrset_ar(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset) -{ - if(!rrset || !node) - return 1; - if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type, - z->dclass)) - return 1; - /* grow array */ - if(!msg_grow_array(region, msg)) - return 0; - /* copy it */ - if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) - return 0; - msg->rep->rrset_count++; - msg->rep->ar_numrrsets++; - msg_ttl(msg); - return 1; -} - -struct auth_zones* auth_zones_create(void) -{ - struct auth_zones* az = (struct auth_zones*)calloc(1, sizeof(*az)); - if(!az) { - log_err("out of memory"); - return NULL; - } - rbtree_init(&az->ztree, &auth_zone_cmp); - rbtree_init(&az->xtree, &auth_xfer_cmp); - lock_rw_init(&az->lock); - lock_protect(&az->lock, &az->ztree, sizeof(az->ztree)); - lock_protect(&az->lock, &az->xtree, sizeof(az->xtree)); - /* also lock protects the rbnode's in struct auth_zone, auth_xfer */ - lock_rw_init(&az->rpz_lock); - lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first)); - return az; -} - -int auth_zone_cmp(const void* z1, const void* z2) -{ - /* first sort on class, so that hierarchy can be maintained within - * a class */ - struct auth_zone* a = (struct auth_zone*)z1; - struct auth_zone* b = (struct auth_zone*)z2; - int m; - if(a->dclass != b->dclass) { - if(a->dclass < b->dclass) - return -1; - return 1; - } - /* sorted such that higher zones sort before lower zones (their - * contents) */ - return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m); -} - -int auth_data_cmp(const void* z1, const void* z2) -{ - struct auth_data* a = (struct auth_data*)z1; - struct auth_data* b = (struct auth_data*)z2; - int m; - /* canonical sort, because DNSSEC needs that */ - return dname_canon_lab_cmp(a->name, a->namelabs, b->name, - b->namelabs, &m); -} - -int auth_xfer_cmp(const void* z1, const void* z2) -{ - /* first sort on class, so that hierarchy can be maintained within - * a class */ - struct auth_xfer* a = (struct auth_xfer*)z1; - struct auth_xfer* b = (struct auth_xfer*)z2; - int m; - if(a->dclass != b->dclass) { - if(a->dclass < b->dclass) - return -1; - return 1; - } - /* sorted such that higher zones sort before lower zones (their - * contents) */ - return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m); -} - -/** delete auth rrset node */ -static void -auth_rrset_delete(struct auth_rrset* rrset) -{ - if(!rrset) return; - free(rrset->data); - free(rrset); -} - -/** delete auth data domain node */ -static void -auth_data_delete(struct auth_data* n) -{ - struct auth_rrset* p, *np; - if(!n) return; - p = n->rrsets; - while(p) { - np = p->next; - auth_rrset_delete(p); - p = np; - } - free(n->name); - free(n); -} - -/** helper traverse to delete zones */ -static void -auth_data_del(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct auth_data* z = (struct auth_data*)n->key; - auth_data_delete(z); -} - -/** delete an auth zone structure (tree remove must be done elsewhere) */ -static void -auth_zone_delete(struct auth_zone* z, struct auth_zones* az) -{ - if(!z) return; - lock_rw_destroy(&z->lock); - traverse_postorder(&z->data, auth_data_del, NULL); - - if(az && z->rpz) { - /* keep RPZ linked list intact */ - lock_rw_wrlock(&az->rpz_lock); - if(z->rpz_az_prev) - z->rpz_az_prev->rpz_az_next = z->rpz_az_next; - else - az->rpz_first = z->rpz_az_next; - if(z->rpz_az_next) - z->rpz_az_next->rpz_az_prev = z->rpz_az_prev; - lock_rw_unlock(&az->rpz_lock); - } - if(z->rpz) - rpz_delete(z->rpz); - free(z->name); - free(z->zonefile); - free(z); -} - -struct auth_zone* -auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass) -{ - struct auth_zone* z = (struct auth_zone*)calloc(1, sizeof(*z)); - if(!z) { - return NULL; - } - z->node.key = z; - z->dclass = dclass; - z->namelen = nmlen; - z->namelabs = dname_count_labels(nm); - z->name = memdup(nm, nmlen); - if(!z->name) { - free(z); - return NULL; - } - rbtree_init(&z->data, &auth_data_cmp); - lock_rw_init(&z->lock); - lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type)- - sizeof(&z->rpz_az_next)-sizeof(&z->rpz_az_prev)); - lock_rw_wrlock(&z->lock); - /* z lock protects all, except rbtree itself and the rpz linked list - * pointers, which are protected using az->lock */ - if(!rbtree_insert(&az->ztree, &z->node)) { - lock_rw_unlock(&z->lock); - auth_zone_delete(z, NULL); - log_warn("duplicate auth zone"); - return NULL; - } - return z; -} - -struct auth_zone* -auth_zone_find(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass) -{ - struct auth_zone key; - key.node.key = &key; - key.dclass = dclass; - key.name = nm; - key.namelen = nmlen; - key.namelabs = dname_count_labels(nm); - return (struct auth_zone*)rbtree_search(&az->ztree, &key); -} - -struct auth_xfer* -auth_xfer_find(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass) -{ - struct auth_xfer key; - key.node.key = &key; - key.dclass = dclass; - key.name = nm; - key.namelen = nmlen; - key.namelabs = dname_count_labels(nm); - return (struct auth_xfer*)rbtree_search(&az->xtree, &key); -} - -/** find an auth zone or sorted less-or-equal, return true if exact */ -static int -auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass, struct auth_zone** z) -{ - struct auth_zone key; - key.node.key = &key; - key.dclass = dclass; - key.name = nm; - key.namelen = nmlen; - key.namelabs = dname_count_labels(nm); - return rbtree_find_less_equal(&az->ztree, &key, (rbnode_type**)z); -} - - -/** find the auth zone that is above the given name */ -struct auth_zone* -auth_zones_find_zone(struct auth_zones* az, uint8_t* name, size_t name_len, - uint16_t dclass) -{ - uint8_t* nm = name; - size_t nmlen = name_len; - struct auth_zone* z; - if(auth_zone_find_less_equal(az, nm, nmlen, dclass, &z)) { - /* exact match */ - return z; - } else { - /* less-or-nothing */ - if(!z) return NULL; /* nothing smaller, nothing above it */ - /* we found smaller name; smaller may be above the name, - * but not below it. */ - nm = dname_get_shared_topdomain(z->name, name); - dname_count_size_labels(nm, &nmlen); - z = NULL; - } - - /* search up */ - while(!z) { - z = auth_zone_find(az, nm, nmlen, dclass); - if(z) return z; - if(dname_is_root(nm)) break; - dname_remove_label(&nm, &nmlen); - } - return NULL; -} - -/** find or create zone with name str. caller must have lock on az. - * returns a wrlocked zone */ -static struct auth_zone* -auth_zones_find_or_add_zone(struct auth_zones* az, char* name) -{ - uint8_t nm[LDNS_MAX_DOMAINLEN+1]; - size_t nmlen = sizeof(nm); - struct auth_zone* z; - - if(sldns_str2wire_dname_buf(name, nm, &nmlen) != 0) { - log_err("cannot parse auth zone name: %s", name); - return 0; - } - z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN); - if(!z) { - /* not found, create the zone */ - z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN); - } else { - lock_rw_wrlock(&z->lock); - } - return z; -} - -/** find or create xfer zone with name str. caller must have lock on az. - * returns a locked xfer */ -static struct auth_xfer* -auth_zones_find_or_add_xfer(struct auth_zones* az, struct auth_zone* z) -{ - struct auth_xfer* x; - x = auth_xfer_find(az, z->name, z->namelen, z->dclass); - if(!x) { - /* not found, create the zone */ - x = auth_xfer_create(az, z); - } else { - lock_basic_lock(&x->lock); - } - return x; -} - -int -auth_zone_set_zonefile(struct auth_zone* z, char* zonefile) -{ - if(z->zonefile) free(z->zonefile); - if(zonefile == NULL) { - z->zonefile = NULL; - } else { - z->zonefile = strdup(zonefile); - if(!z->zonefile) { - log_err("malloc failure"); - return 0; - } - } - return 1; -} - -/** set auth zone fallback. caller must have lock on zone */ -int -auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr) -{ - if(strcmp(fallbackstr, "yes") != 0 && strcmp(fallbackstr, "no") != 0){ - log_err("auth zone fallback, expected yes or no, got %s", - fallbackstr); - return 0; - } - z->fallback_enabled = (strcmp(fallbackstr, "yes")==0); - return 1; -} - -/** create domain with the given name */ -static struct auth_data* -az_domain_create(struct auth_zone* z, uint8_t* nm, size_t nmlen) -{ - struct auth_data* n = (struct auth_data*)malloc(sizeof(*n)); - if(!n) return NULL; - memset(n, 0, sizeof(*n)); - n->node.key = n; - n->name = memdup(nm, nmlen); - if(!n->name) { - free(n); - return NULL; - } - n->namelen = nmlen; - n->namelabs = dname_count_labels(nm); - if(!rbtree_insert(&z->data, &n->node)) { - log_warn("duplicate auth domain name"); - free(n->name); - free(n); - return NULL; - } - return n; -} - -/** find domain with exactly the given name */ -static struct auth_data* -az_find_name(struct auth_zone* z, uint8_t* nm, size_t nmlen) -{ - struct auth_zone key; - key.node.key = &key; - key.name = nm; - key.namelen = nmlen; - key.namelabs = dname_count_labels(nm); - return (struct auth_data*)rbtree_search(&z->data, &key); -} - -/** Find domain name (or closest match) */ -static void -az_find_domain(struct auth_zone* z, struct query_info* qinfo, int* node_exact, - struct auth_data** node) -{ - struct auth_zone key; - key.node.key = &key; - key.name = qinfo->qname; - key.namelen = qinfo->qname_len; - key.namelabs = dname_count_labels(key.name); - *node_exact = rbtree_find_less_equal(&z->data, &key, - (rbnode_type**)node); -} - -/** find or create domain with name in zone */ -static struct auth_data* -az_domain_find_or_create(struct auth_zone* z, uint8_t* dname, - size_t dname_len) -{ - struct auth_data* n = az_find_name(z, dname, dname_len); - if(!n) { - n = az_domain_create(z, dname, dname_len); - } - return n; -} - -/** find rrset of given type in the domain */ -static struct auth_rrset* -az_domain_rrset(struct auth_data* n, uint16_t t) -{ - struct auth_rrset* rrset; - if(!n) return NULL; - rrset = n->rrsets; - while(rrset) { - if(rrset->type == t) - return rrset; - rrset = rrset->next; - } - return NULL; -} - -/** remove rrset of this type from domain */ -static void -domain_remove_rrset(struct auth_data* node, uint16_t rr_type) -{ - struct auth_rrset* rrset, *prev; - if(!node) return; - prev = NULL; - rrset = node->rrsets; - while(rrset) { - if(rrset->type == rr_type) { - /* found it, now delete it */ - if(prev) prev->next = rrset->next; - else node->rrsets = rrset->next; - auth_rrset_delete(rrset); - return; - } - prev = rrset; - rrset = rrset->next; - } -} - -/** find an rrsig index in the rrset. returns true if found */ -static int -az_rrset_find_rrsig(struct packed_rrset_data* d, uint8_t* rdata, size_t len, - size_t* index) -{ - size_t i; - for(i=d->count; icount + d->rrsig_count; i++) { - if(d->rr_len[i] != len) - continue; - if(memcmp(d->rr_data[i], rdata, len) == 0) { - *index = i; - return 1; - } - } - return 0; -} - -/** see if rdata is duplicate */ -static int -rdata_duplicate(struct packed_rrset_data* d, uint8_t* rdata, size_t len) -{ - size_t i; - for(i=0; icount + d->rrsig_count; i++) { - if(d->rr_len[i] != len) - continue; - if(memcmp(d->rr_data[i], rdata, len) == 0) - return 1; - } - return 0; -} - -/** get rrsig type covered from rdata. - * @param rdata: rdata in wireformat, starting with 16bit rdlength. - * @param rdatalen: length of rdata buffer. - * @return type covered (or 0). - */ -static uint16_t -rrsig_rdata_get_type_covered(uint8_t* rdata, size_t rdatalen) -{ - if(rdatalen < 4) - return 0; - return sldns_read_uint16(rdata+2); -} - -/** remove RR from existing RRset. Also sig, if it is a signature. - * reallocates the packed rrset for a new one, false on alloc failure */ -static int -rrset_remove_rr(struct auth_rrset* rrset, size_t index) -{ - struct packed_rrset_data* d, *old = rrset->data; - size_t i; - if(index >= old->count + old->rrsig_count) - return 0; /* index out of bounds */ - d = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(old) - ( - sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t) + - old->rr_len[index])); - if(!d) { - log_err("malloc failure"); - return 0; - } - d->ttl = old->ttl; - d->count = old->count; - d->rrsig_count = old->rrsig_count; - if(index < d->count) d->count--; - else d->rrsig_count--; - d->trust = old->trust; - d->security = old->security; - - /* set rr_len, needed for ptr_fixup */ - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - if(index > 0) - memmove(d->rr_len, old->rr_len, (index)*sizeof(size_t)); - if(index+1 < old->count+old->rrsig_count) - memmove(&d->rr_len[index], &old->rr_len[index+1], - (old->count+old->rrsig_count - (index+1))*sizeof(size_t)); - packed_rrset_ptr_fixup(d); - - /* move over ttls */ - if(index > 0) - memmove(d->rr_ttl, old->rr_ttl, (index)*sizeof(time_t)); - if(index+1 < old->count+old->rrsig_count) - memmove(&d->rr_ttl[index], &old->rr_ttl[index+1], - (old->count+old->rrsig_count - (index+1))*sizeof(time_t)); - - /* move over rr_data */ - for(i=0; icount+d->rrsig_count; i++) { - size_t oldi; - if(i < index) oldi = i; - else oldi = i+1; - memmove(d->rr_data[i], old->rr_data[oldi], d->rr_len[i]); - } - - /* recalc ttl (lowest of remaining RR ttls) */ - if(d->count + d->rrsig_count > 0) - d->ttl = d->rr_ttl[0]; - for(i=0; icount+d->rrsig_count; i++) { - if(d->rr_ttl[i] < d->ttl) - d->ttl = d->rr_ttl[i]; - } - - free(rrset->data); - rrset->data = d; - return 1; -} - -/** add RR to existing RRset. If insert_sig is true, add to rrsigs. - * This reallocates the packed rrset for a new one */ -static int -rrset_add_rr(struct auth_rrset* rrset, uint32_t rr_ttl, uint8_t* rdata, - size_t rdatalen, int insert_sig) -{ - struct packed_rrset_data* d, *old = rrset->data; - size_t total, old_total; - - d = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(old) - + sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t) - + rdatalen); - if(!d) { - log_err("out of memory"); - return 0; - } - /* copy base values */ - memcpy(d, old, sizeof(struct packed_rrset_data)); - if(!insert_sig) { - d->count++; - } else { - d->rrsig_count++; - } - old_total = old->count + old->rrsig_count; - total = d->count + d->rrsig_count; - /* set rr_len, needed for ptr_fixup */ - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - if(old->count != 0) - memmove(d->rr_len, old->rr_len, old->count*sizeof(size_t)); - if(old->rrsig_count != 0) - memmove(d->rr_len+d->count, old->rr_len+old->count, - old->rrsig_count*sizeof(size_t)); - if(!insert_sig) - d->rr_len[d->count-1] = rdatalen; - else d->rr_len[total-1] = rdatalen; - packed_rrset_ptr_fixup(d); - if((time_t)rr_ttl < d->ttl) - d->ttl = rr_ttl; - - /* copy old values into new array */ - if(old->count != 0) { - memmove(d->rr_ttl, old->rr_ttl, old->count*sizeof(time_t)); - /* all the old rr pieces are allocated sequential, so we - * can copy them in one go */ - memmove(d->rr_data[0], old->rr_data[0], - (old->rr_data[old->count-1] - old->rr_data[0]) + - old->rr_len[old->count-1]); - } - if(old->rrsig_count != 0) { - memmove(d->rr_ttl+d->count, old->rr_ttl+old->count, - old->rrsig_count*sizeof(time_t)); - memmove(d->rr_data[d->count], old->rr_data[old->count], - (old->rr_data[old_total-1] - old->rr_data[old->count]) + - old->rr_len[old_total-1]); - } - - /* insert new value */ - if(!insert_sig) { - d->rr_ttl[d->count-1] = rr_ttl; - memmove(d->rr_data[d->count-1], rdata, rdatalen); - } else { - d->rr_ttl[total-1] = rr_ttl; - memmove(d->rr_data[total-1], rdata, rdatalen); - } - - rrset->data = d; - free(old); - return 1; -} - -/** Create new rrset for node with packed rrset with one RR element */ -static struct auth_rrset* -rrset_create(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl, - uint8_t* rdata, size_t rdatalen) -{ - struct auth_rrset* rrset = (struct auth_rrset*)calloc(1, - sizeof(*rrset)); - struct auth_rrset* p, *prev; - struct packed_rrset_data* d; - if(!rrset) { - log_err("out of memory"); - return NULL; - } - rrset->type = rr_type; - - /* the rrset data structure, with one RR */ - d = (struct packed_rrset_data*)calloc(1, - sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t) + rdatalen); - if(!d) { - free(rrset); - log_err("out of memory"); - return NULL; - } - rrset->data = d; - d->ttl = rr_ttl; - d->trust = rrset_trust_prim_noglue; - d->rr_len = (size_t*)((uint8_t*)d + sizeof(struct packed_rrset_data)); - d->rr_data = (uint8_t**)&(d->rr_len[1]); - d->rr_ttl = (time_t*)&(d->rr_data[1]); - d->rr_data[0] = (uint8_t*)&(d->rr_ttl[1]); - - /* insert the RR */ - d->rr_len[0] = rdatalen; - d->rr_ttl[0] = rr_ttl; - memmove(d->rr_data[0], rdata, rdatalen); - d->count++; - - /* insert rrset into linked list for domain */ - /* find sorted place to link the rrset into the list */ - prev = NULL; - p = node->rrsets; - while(p && p->type<=rr_type) { - prev = p; - p = p->next; - } - /* so, prev is smaller, and p is larger than rr_type */ - rrset->next = p; - if(prev) prev->next = rrset; - else node->rrsets = rrset; - return rrset; -} - -/** count number (and size) of rrsigs that cover a type */ -static size_t -rrsig_num_that_cover(struct auth_rrset* rrsig, uint16_t rr_type, size_t* sigsz) -{ - struct packed_rrset_data* d = rrsig->data; - size_t i, num = 0; - *sigsz = 0; - log_assert(d && rrsig->type == LDNS_RR_TYPE_RRSIG); - for(i=0; icount+d->rrsig_count; i++) { - if(rrsig_rdata_get_type_covered(d->rr_data[i], - d->rr_len[i]) == rr_type) { - num++; - (*sigsz) += d->rr_len[i]; - } - } - return num; -} - -/** See if rrsig set has covered sigs for rrset and move them over */ -static int -rrset_moveover_rrsigs(struct auth_data* node, uint16_t rr_type, - struct auth_rrset* rrset, struct auth_rrset* rrsig) -{ - size_t sigs, sigsz, i, j, total; - struct packed_rrset_data* sigold = rrsig->data; - struct packed_rrset_data* old = rrset->data; - struct packed_rrset_data* d, *sigd; - - log_assert(rrset->type == rr_type); - log_assert(rrsig->type == LDNS_RR_TYPE_RRSIG); - sigs = rrsig_num_that_cover(rrsig, rr_type, &sigsz); - if(sigs == 0) { - /* 0 rrsigs to move over, done */ - return 1; - } - - /* allocate rrset sigsz larger for extra sigs elements, and - * allocate rrsig sigsz smaller for less sigs elements. */ - d = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(old) - + sigs*(sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t)) - + sigsz); - if(!d) { - log_err("out of memory"); - return 0; - } - /* copy base values */ - total = old->count + old->rrsig_count; - memcpy(d, old, sizeof(struct packed_rrset_data)); - d->rrsig_count += sigs; - /* setup rr_len */ - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - if(total != 0) - memmove(d->rr_len, old->rr_len, total*sizeof(size_t)); - j = d->count+d->rrsig_count-sigs; - for(i=0; icount+sigold->rrsig_count; i++) { - if(rrsig_rdata_get_type_covered(sigold->rr_data[i], - sigold->rr_len[i]) == rr_type) { - d->rr_len[j] = sigold->rr_len[i]; - j++; - } - } - packed_rrset_ptr_fixup(d); - - /* copy old values into new array */ - if(total != 0) { - memmove(d->rr_ttl, old->rr_ttl, total*sizeof(time_t)); - /* all the old rr pieces are allocated sequential, so we - * can copy them in one go */ - memmove(d->rr_data[0], old->rr_data[0], - (old->rr_data[total-1] - old->rr_data[0]) + - old->rr_len[total-1]); - } - - /* move over the rrsigs to the larger rrset*/ - j = d->count+d->rrsig_count-sigs; - for(i=0; icount+sigold->rrsig_count; i++) { - if(rrsig_rdata_get_type_covered(sigold->rr_data[i], - sigold->rr_len[i]) == rr_type) { - /* move this one over to location j */ - d->rr_ttl[j] = sigold->rr_ttl[i]; - memmove(d->rr_data[j], sigold->rr_data[i], - sigold->rr_len[i]); - if(d->rr_ttl[j] < d->ttl) - d->ttl = d->rr_ttl[j]; - j++; - } - } - - /* put it in and deallocate the old rrset */ - rrset->data = d; - free(old); - - /* now make rrsig set smaller */ - if(sigold->count+sigold->rrsig_count == sigs) { - /* remove all sigs from rrsig, remove it entirely */ - domain_remove_rrset(node, LDNS_RR_TYPE_RRSIG); - return 1; - } - log_assert(packed_rrset_sizeof(sigold) > sigs*(sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t)) + sigsz); - sigd = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(sigold) - - sigs*(sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t)) - - sigsz); - if(!sigd) { - /* no need to free up d, it has already been placed in the - * node->rrset structure */ - log_err("out of memory"); - return 0; - } - /* copy base values */ - memcpy(sigd, sigold, sizeof(struct packed_rrset_data)); - /* in sigd the RRSIGs are stored in the base of the RR, in count */ - sigd->count -= sigs; - /* setup rr_len */ - sigd->rr_len = (size_t*)((uint8_t*)sigd + - sizeof(struct packed_rrset_data)); - j = 0; - for(i=0; icount+sigold->rrsig_count; i++) { - if(rrsig_rdata_get_type_covered(sigold->rr_data[i], - sigold->rr_len[i]) != rr_type) { - sigd->rr_len[j] = sigold->rr_len[i]; - j++; - } - } - packed_rrset_ptr_fixup(sigd); - - /* copy old values into new rrsig array */ - j = 0; - for(i=0; icount+sigold->rrsig_count; i++) { - if(rrsig_rdata_get_type_covered(sigold->rr_data[i], - sigold->rr_len[i]) != rr_type) { - /* move this one over to location j */ - sigd->rr_ttl[j] = sigold->rr_ttl[i]; - memmove(sigd->rr_data[j], sigold->rr_data[i], - sigold->rr_len[i]); - if(j==0) sigd->ttl = sigd->rr_ttl[j]; - else { - if(sigd->rr_ttl[j] < sigd->ttl) - sigd->ttl = sigd->rr_ttl[j]; - } - j++; - } - } - - /* put it in and deallocate the old rrset */ - rrsig->data = sigd; - free(sigold); - - return 1; -} - -/** copy the rrsigs from the rrset to the rrsig rrset, because the rrset - * is going to be deleted. reallocates the RRSIG rrset data. */ -static int -rrsigs_copy_from_rrset_to_rrsigset(struct auth_rrset* rrset, - struct auth_rrset* rrsigset) -{ - size_t i; - if(rrset->data->rrsig_count == 0) - return 1; - - /* move them over one by one, because there might be duplicates, - * duplicates are ignored */ - for(i=rrset->data->count; - idata->count+rrset->data->rrsig_count; i++) { - uint8_t* rdata = rrset->data->rr_data[i]; - size_t rdatalen = rrset->data->rr_len[i]; - time_t rr_ttl = rrset->data->rr_ttl[i]; - - if(rdata_duplicate(rrsigset->data, rdata, rdatalen)) { - continue; - } - if(!rrset_add_rr(rrsigset, rr_ttl, rdata, rdatalen, 0)) - return 0; - } - return 1; -} - -/** Add rr to node, ignores duplicate RRs, - * rdata points to buffer with rdatalen octets, starts with 2bytelength. */ -static int -az_domain_add_rr(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl, - uint8_t* rdata, size_t rdatalen, int* duplicate) -{ - struct auth_rrset* rrset; - /* packed rrsets have their rrsigs along with them, sort them out */ - if(rr_type == LDNS_RR_TYPE_RRSIG) { - uint16_t ctype = rrsig_rdata_get_type_covered(rdata, rdatalen); - if((rrset=az_domain_rrset(node, ctype))!= NULL) { - /* a node of the correct type exists, add the RRSIG - * to the rrset of the covered data type */ - if(rdata_duplicate(rrset->data, rdata, rdatalen)) { - if(duplicate) *duplicate = 1; - return 1; - } - if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 1)) - return 0; - } else if((rrset=az_domain_rrset(node, rr_type))!= NULL) { - /* add RRSIG to rrset of type RRSIG */ - if(rdata_duplicate(rrset->data, rdata, rdatalen)) { - if(duplicate) *duplicate = 1; - return 1; - } - if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 0)) - return 0; - } else { - /* create rrset of type RRSIG */ - if(!rrset_create(node, rr_type, rr_ttl, rdata, - rdatalen)) - return 0; - } - } else { - /* normal RR type */ - if((rrset=az_domain_rrset(node, rr_type))!= NULL) { - /* add data to existing node with data type */ - if(rdata_duplicate(rrset->data, rdata, rdatalen)) { - if(duplicate) *duplicate = 1; - return 1; - } - if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 0)) - return 0; - } else { - struct auth_rrset* rrsig; - /* create new node with data type */ - if(!(rrset=rrset_create(node, rr_type, rr_ttl, rdata, - rdatalen))) - return 0; - - /* see if node of type RRSIG has signatures that - * cover the data type, and move them over */ - /* and then make the RRSIG type smaller */ - if((rrsig=az_domain_rrset(node, LDNS_RR_TYPE_RRSIG)) - != NULL) { - if(!rrset_moveover_rrsigs(node, rr_type, - rrset, rrsig)) - return 0; - } - } - } - return 1; -} - -/** insert RR into zone, ignore duplicates */ -static int -az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len, - size_t dname_len, int* duplicate) -{ - struct auth_data* node; - uint8_t* dname = rr; - uint16_t rr_type = sldns_wirerr_get_type(rr, rr_len, dname_len); - uint16_t rr_class = sldns_wirerr_get_class(rr, rr_len, dname_len); - uint32_t rr_ttl = sldns_wirerr_get_ttl(rr, rr_len, dname_len); - size_t rdatalen = ((size_t)sldns_wirerr_get_rdatalen(rr, rr_len, - dname_len))+2; - /* rdata points to rdata prefixed with uint16 rdatalength */ - uint8_t* rdata = sldns_wirerr_get_rdatawl(rr, rr_len, dname_len); - - if(rr_class != z->dclass) { - log_err("wrong class for RR"); - return 0; - } - if(!(node=az_domain_find_or_create(z, dname, dname_len))) { - log_err("cannot create domain"); - return 0; - } - if(!az_domain_add_rr(node, rr_type, rr_ttl, rdata, rdatalen, - duplicate)) { - log_err("cannot add RR to domain"); - return 0; - } - if(z->rpz) { - if(!(rpz_insert_rr(z->rpz, z->name, z->namelen, dname, - dname_len, rr_type, rr_class, rr_ttl, rdata, rdatalen, - rr, rr_len))) - return 0; - } - return 1; -} - -/** Remove rr from node, ignores nonexisting RRs, - * rdata points to buffer with rdatalen octets, starts with 2bytelength. */ -static int -az_domain_remove_rr(struct auth_data* node, uint16_t rr_type, - uint8_t* rdata, size_t rdatalen, int* nonexist) -{ - struct auth_rrset* rrset; - size_t index = 0; - - /* find the plain RR of the given type */ - if((rrset=az_domain_rrset(node, rr_type))!= NULL) { - if(packed_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) { - if(rrset->data->count == 1 && - rrset->data->rrsig_count == 0) { - /* last RR, delete the rrset */ - domain_remove_rrset(node, rr_type); - } else if(rrset->data->count == 1 && - rrset->data->rrsig_count != 0) { - /* move RRSIGs to the RRSIG rrset, or - * this one becomes that RRset */ - struct auth_rrset* rrsigset = az_domain_rrset( - node, LDNS_RR_TYPE_RRSIG); - if(rrsigset) { - /* move left over rrsigs to the - * existing rrset of type RRSIG */ - rrsigs_copy_from_rrset_to_rrsigset( - rrset, rrsigset); - /* and then delete the rrset */ - domain_remove_rrset(node, rr_type); - } else { - /* no rrset of type RRSIG, this - * set is now of that type, - * just remove the rr */ - if(!rrset_remove_rr(rrset, index)) - return 0; - rrset->type = LDNS_RR_TYPE_RRSIG; - rrset->data->count = rrset->data->rrsig_count; - rrset->data->rrsig_count = 0; - } - } else { - /* remove the RR from the rrset */ - if(!rrset_remove_rr(rrset, index)) - return 0; - } - return 1; - } - /* rr not found in rrset */ - } - - /* is it a type RRSIG, look under the covered type */ - if(rr_type == LDNS_RR_TYPE_RRSIG) { - uint16_t ctype = rrsig_rdata_get_type_covered(rdata, rdatalen); - if((rrset=az_domain_rrset(node, ctype))!= NULL) { - if(az_rrset_find_rrsig(rrset->data, rdata, rdatalen, - &index)) { - /* rrsig should have d->count > 0, be - * over some rr of that type */ - /* remove the rrsig from the rrsigs list of the - * rrset */ - if(!rrset_remove_rr(rrset, index)) - return 0; - return 1; - } - } - /* also RRSIG not found */ - } - - /* nothing found to delete */ - if(nonexist) *nonexist = 1; - return 1; -} - -/** remove RR from zone, ignore if it does not exist, false on alloc failure*/ -static int -az_remove_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len, - size_t dname_len, int* nonexist) -{ - struct auth_data* node; - uint8_t* dname = rr; - uint16_t rr_type = sldns_wirerr_get_type(rr, rr_len, dname_len); - uint16_t rr_class = sldns_wirerr_get_class(rr, rr_len, dname_len); - size_t rdatalen = ((size_t)sldns_wirerr_get_rdatalen(rr, rr_len, - dname_len))+2; - /* rdata points to rdata prefixed with uint16 rdatalength */ - uint8_t* rdata = sldns_wirerr_get_rdatawl(rr, rr_len, dname_len); - - if(rr_class != z->dclass) { - log_err("wrong class for RR"); - /* really also a nonexisting entry, because no records - * of that class in the zone, but return an error because - * getting records of the wrong class is a failure of the - * zone transfer */ - return 0; - } - node = az_find_name(z, dname, dname_len); - if(!node) { - /* node with that name does not exist */ - /* nonexisting entry, because no such name */ - *nonexist = 1; - return 1; - } - if(!az_domain_remove_rr(node, rr_type, rdata, rdatalen, nonexist)) { - /* alloc failure or so */ - return 0; - } - /* remove the node, if necessary */ - /* an rrsets==NULL entry is not kept around for empty nonterminals, - * and also parent nodes are not kept around, so we just delete it */ - if(node->rrsets == NULL) { - (void)rbtree_delete(&z->data, node); - auth_data_delete(node); - } - if(z->rpz) { - rpz_remove_rr(z->rpz, z->name, z->namelen, dname, dname_len, - rr_type, rr_class, rdata, rdatalen); - } - return 1; -} - -/** decompress an RR into the buffer where it'll be an uncompressed RR - * with uncompressed dname and uncompressed rdata (dnames) */ -static int -decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt, - size_t pktlen, uint8_t* dname, uint16_t rr_type, uint16_t rr_class, - uint32_t rr_ttl, uint8_t* rr_data, uint16_t rr_rdlen) -{ - sldns_buffer pktbuf; - size_t dname_len = 0; - size_t rdlenpos; - size_t rdlen; - uint8_t* rd; - const sldns_rr_descriptor* desc; - sldns_buffer_init_frm_data(&pktbuf, pkt, pktlen); - sldns_buffer_clear(buf); - - /* decompress dname */ - sldns_buffer_set_position(&pktbuf, - (size_t)(dname - sldns_buffer_current(&pktbuf))); - dname_len = pkt_dname_len(&pktbuf); - if(dname_len == 0) return 0; /* parse fail on dname */ - if(!sldns_buffer_available(buf, dname_len)) return 0; - dname_pkt_copy(&pktbuf, sldns_buffer_current(buf), dname); - sldns_buffer_skip(buf, (ssize_t)dname_len); - - /* type, class, ttl and rdatalength fields */ - if(!sldns_buffer_available(buf, 10)) return 0; - sldns_buffer_write_u16(buf, rr_type); - sldns_buffer_write_u16(buf, rr_class); - sldns_buffer_write_u32(buf, rr_ttl); - rdlenpos = sldns_buffer_position(buf); - sldns_buffer_write_u16(buf, 0); /* rd length position */ - - /* decompress rdata */ - desc = sldns_rr_descript(rr_type); - rd = rr_data; - rdlen = rr_rdlen; - if(rdlen > 0 && desc && desc->_dname_count > 0) { - int count = (int)desc->_dname_count; - int rdf = 0; - size_t len; /* how much rdata to plain copy */ - size_t uncompressed_len, compressed_len; - size_t oldpos; - /* decompress dnames. */ - while(rdlen > 0 && count) { - switch(desc->_wireformat[rdf]) { - case LDNS_RDF_TYPE_DNAME: - sldns_buffer_set_position(&pktbuf, - (size_t)(rd - - sldns_buffer_begin(&pktbuf))); - oldpos = sldns_buffer_position(&pktbuf); - /* moves pktbuf to right after the - * compressed dname, and returns uncompressed - * dname length */ - uncompressed_len = pkt_dname_len(&pktbuf); - if(!uncompressed_len) - return 0; /* parse error in dname */ - if(!sldns_buffer_available(buf, - uncompressed_len)) - /* dname too long for buffer */ - return 0; - dname_pkt_copy(&pktbuf, - sldns_buffer_current(buf), rd); - sldns_buffer_skip(buf, (ssize_t)uncompressed_len); - compressed_len = sldns_buffer_position( - &pktbuf) - oldpos; - rd += compressed_len; - rdlen -= compressed_len; - count--; - len = 0; - break; - case LDNS_RDF_TYPE_STR: - len = rd[0] + 1; - break; - default: - len = get_rdf_size(desc->_wireformat[rdf]); - break; - } - if(len) { - if(!sldns_buffer_available(buf, len)) - return 0; /* too long for buffer */ - sldns_buffer_write(buf, rd, len); - rd += len; - rdlen -= len; - } - rdf++; - } - } - /* copy remaining data */ - if(rdlen > 0) { - if(!sldns_buffer_available(buf, rdlen)) return 0; - sldns_buffer_write(buf, rd, rdlen); - } - /* fixup rdlength */ - sldns_buffer_write_u16_at(buf, rdlenpos, - sldns_buffer_position(buf)-rdlenpos-2); - sldns_buffer_flip(buf); - return 1; -} - -/** insert RR into zone, from packet, decompress RR, - * if duplicate is nonNULL set the flag but otherwise ignore duplicates */ -static int -az_insert_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen, - struct sldns_buffer* scratch_buffer, uint8_t* dname, uint16_t rr_type, - uint16_t rr_class, uint32_t rr_ttl, uint8_t* rr_data, - uint16_t rr_rdlen, int* duplicate) -{ - uint8_t* rr; - size_t rr_len; - size_t dname_len; - if(!decompress_rr_into_buffer(scratch_buffer, pkt, pktlen, dname, - rr_type, rr_class, rr_ttl, rr_data, rr_rdlen)) { - log_err("could not decompress RR"); - return 0; - } - rr = sldns_buffer_begin(scratch_buffer); - rr_len = sldns_buffer_limit(scratch_buffer); - dname_len = dname_valid(rr, rr_len); - return az_insert_rr(z, rr, rr_len, dname_len, duplicate); -} - -/** remove RR from zone, from packet, decompress RR, - * if nonexist is nonNULL set the flag but otherwise ignore nonexisting entries*/ -static int -az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen, - struct sldns_buffer* scratch_buffer, uint8_t* dname, uint16_t rr_type, - uint16_t rr_class, uint32_t rr_ttl, uint8_t* rr_data, - uint16_t rr_rdlen, int* nonexist) -{ - uint8_t* rr; - size_t rr_len; - size_t dname_len; - if(!decompress_rr_into_buffer(scratch_buffer, pkt, pktlen, dname, - rr_type, rr_class, rr_ttl, rr_data, rr_rdlen)) { - log_err("could not decompress RR"); - return 0; - } - rr = sldns_buffer_begin(scratch_buffer); - rr_len = sldns_buffer_limit(scratch_buffer); - dname_len = dname_valid(rr, rr_len); - return az_remove_rr(z, rr, rr_len, dname_len, nonexist); -} - -/** - * Parse zonefile - * @param z: zone to read in. - * @param in: file to read from (just opened). - * @param rr: buffer to use for RRs, 64k. - * passed so that recursive includes can use the same buffer and do - * not grow the stack too much. - * @param rrbuflen: sizeof rr buffer. - * @param state: parse state with $ORIGIN, $TTL and 'prev-dname' and so on, - * that is kept between includes. - * The lineno is set at 1 and then increased by the function. - * @param fname: file name. - * @param depth: recursion depth for includes - * @param cfg: config for chroot. - * returns false on failure, has printed an error message - */ -static int -az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen, - struct sldns_file_parse_state* state, char* fname, int depth, - struct config_file* cfg) -{ - size_t rr_len, dname_len; - int status; - state->lineno = 1; - - while(!feof(in)) { - rr_len = rrbuflen; - dname_len = 0; - status = sldns_fp2wire_rr_buf(in, rr, &rr_len, &dname_len, - state); - if(status == LDNS_WIREPARSE_ERR_INCLUDE && rr_len == 0) { - /* we have $INCLUDE or $something */ - if(strncmp((char*)rr, "$INCLUDE ", 9) == 0 || - strncmp((char*)rr, "$INCLUDE\t", 9) == 0) { - FILE* inc; - int lineno_orig = state->lineno; - char* incfile = (char*)rr + 8; - if(depth > MAX_INCLUDE_DEPTH) { - log_err("%s:%d max include depth" - "exceeded", fname, state->lineno); - return 0; - } - /* skip spaces */ - while(*incfile == ' ' || *incfile == '\t') - incfile++; - /* adjust for chroot on include file */ - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(incfile, cfg->chrootdir, - strlen(cfg->chrootdir)) == 0) - incfile += strlen(cfg->chrootdir); - incfile = strdup(incfile); - if(!incfile) { - log_err("malloc failure"); - return 0; - } - verbose(VERB_ALGO, "opening $INCLUDE %s", - incfile); - inc = fopen(incfile, "r"); - if(!inc) { - log_err("%s:%d cannot open include " - "file %s: %s", fname, - lineno_orig, incfile, - strerror(errno)); - free(incfile); - return 0; - } - /* recurse read that file now */ - if(!az_parse_file(z, inc, rr, rrbuflen, - state, incfile, depth+1, cfg)) { - log_err("%s:%d cannot parse include " - "file %s", fname, - lineno_orig, incfile); - fclose(inc); - free(incfile); - return 0; - } - fclose(inc); - verbose(VERB_ALGO, "done with $INCLUDE %s", - incfile); - free(incfile); - state->lineno = lineno_orig; - } - continue; - } - if(status != 0) { - log_err("parse error %s %d:%d: %s", fname, - state->lineno, LDNS_WIREPARSE_OFFSET(status), - sldns_get_errorstr_parse(status)); - return 0; - } - if(rr_len == 0) { - /* EMPTY line, TTL or ORIGIN */ - continue; - } - /* insert wirerr in rrbuf */ - if(!az_insert_rr(z, rr, rr_len, dname_len, NULL)) { - char buf[17]; - sldns_wire2str_type_buf(sldns_wirerr_get_type(rr, - rr_len, dname_len), buf, sizeof(buf)); - log_err("%s:%d cannot insert RR of type %s", - fname, state->lineno, buf); - return 0; - } - } - return 1; -} - -int -auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - struct sldns_file_parse_state state; - char* zfilename; - FILE* in; - if(!z || !z->zonefile || z->zonefile[0]==0) - return 1; /* no file, or "", nothing to read */ - - zfilename = z->zonefile; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(zfilename, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - zfilename += strlen(cfg->chrootdir); - if(verbosity >= VERB_ALGO) { - char nm[255+1]; - dname_str(z->name, nm); - verbose(VERB_ALGO, "read zonefile %s for %s", zfilename, nm); - } - in = fopen(zfilename, "r"); - if(!in) { - char* n = sldns_wire2str_dname(z->name, z->namelen); - if(z->zone_is_slave && errno == ENOENT) { - /* we fetch the zone contents later, no file yet */ - verbose(VERB_ALGO, "no zonefile %s for %s", - zfilename, n?n:"error"); - free(n); - return 1; - } - log_err("cannot open zonefile %s for %s: %s", - zfilename, n?n:"error", strerror(errno)); - free(n); - return 0; - } - - /* clear the data tree */ - traverse_postorder(&z->data, auth_data_del, NULL); - rbtree_init(&z->data, &auth_data_cmp); - /* clear the RPZ policies */ - if(z->rpz) - rpz_clear(z->rpz); - - memset(&state, 0, sizeof(state)); - /* default TTL to 3600 */ - state.default_ttl = 3600; - /* set $ORIGIN to the zone name */ - if(z->namelen <= sizeof(state.origin)) { - memcpy(state.origin, z->name, z->namelen); - state.origin_len = z->namelen; - } - /* parse the (toplevel) file */ - if(!az_parse_file(z, in, rr, sizeof(rr), &state, zfilename, 0, cfg)) { - char* n = sldns_wire2str_dname(z->name, z->namelen); - log_err("error parsing zonefile %s for %s", - zfilename, n?n:"error"); - free(n); - fclose(in); - return 0; - } - fclose(in); - - if(z->rpz) - rpz_finish_config(z->rpz); - return 1; -} - -/** write buffer to file and check return codes */ -static int -write_out(FILE* out, const char* str, size_t len) -{ - size_t r; - if(len == 0) - return 1; - r = fwrite(str, 1, len, out); - if(r == 0) { - log_err("write failed: %s", strerror(errno)); - return 0; - } else if(r < len) { - log_err("write failed: too short (disk full?)"); - return 0; - } - return 1; -} - -/** convert auth rr to string */ -static int -auth_rr_to_string(uint8_t* nm, size_t nmlen, uint16_t tp, uint16_t cl, - struct packed_rrset_data* data, size_t i, char* s, size_t buflen) -{ - int w = 0; - size_t slen = buflen, datlen; - uint8_t* dat; - if(i >= data->count) tp = LDNS_RR_TYPE_RRSIG; - dat = nm; - datlen = nmlen; - w += sldns_wire2str_dname_scan(&dat, &datlen, &s, &slen, NULL, 0, NULL); - w += sldns_str_print(&s, &slen, "\t"); - w += sldns_str_print(&s, &slen, "%lu\t", (unsigned long)data->rr_ttl[i]); - w += sldns_wire2str_class_print(&s, &slen, cl); - w += sldns_str_print(&s, &slen, "\t"); - w += sldns_wire2str_type_print(&s, &slen, tp); - w += sldns_str_print(&s, &slen, "\t"); - datlen = data->rr_len[i]-2; - dat = data->rr_data[i]+2; - w += sldns_wire2str_rdata_scan(&dat, &datlen, &s, &slen, tp, NULL, 0, NULL); - - if(tp == LDNS_RR_TYPE_DNSKEY) { - w += sldns_str_print(&s, &slen, " ;{id = %u}", - sldns_calc_keytag_raw(data->rr_data[i]+2, - data->rr_len[i]-2)); - } - w += sldns_str_print(&s, &slen, "\n"); - - if(w >= (int)buflen) { - log_nametypeclass(NO_VERBOSE, "RR too long to print", nm, tp, cl); - return 0; - } - return 1; -} - -/** write rrset to file */ -static int -auth_zone_write_rrset(struct auth_zone* z, struct auth_data* node, - struct auth_rrset* r, FILE* out) -{ - size_t i, count = r->data->count + r->data->rrsig_count; - char buf[LDNS_RR_BUF_SIZE]; - for(i=0; iname, node->namelen, r->type, - z->dclass, r->data, i, buf, sizeof(buf))) { - verbose(VERB_ALGO, "failed to rr2str rr %d", (int)i); - continue; - } - if(!write_out(out, buf, strlen(buf))) - return 0; - } - return 1; -} - -/** write domain to file */ -static int -auth_zone_write_domain(struct auth_zone* z, struct auth_data* n, FILE* out) -{ - struct auth_rrset* r; - /* if this is zone apex, write SOA first */ - if(z->namelen == n->namelen) { - struct auth_rrset* soa = az_domain_rrset(n, LDNS_RR_TYPE_SOA); - if(soa) { - if(!auth_zone_write_rrset(z, n, soa, out)) - return 0; - } - } - /* write all the RRsets for this domain */ - for(r = n->rrsets; r; r = r->next) { - if(z->namelen == n->namelen && - r->type == LDNS_RR_TYPE_SOA) - continue; /* skip SOA here */ - if(!auth_zone_write_rrset(z, n, r, out)) - return 0; - } - return 1; -} - -int auth_zone_write_file(struct auth_zone* z, const char* fname) -{ - FILE* out; - struct auth_data* n; - out = fopen(fname, "w"); - if(!out) { - log_err("could not open %s: %s", fname, strerror(errno)); - return 0; - } - RBTREE_FOR(n, struct auth_data*, &z->data) { - if(!auth_zone_write_domain(z, n, out)) { - log_err("could not write domain to %s", fname); - fclose(out); - return 0; - } - } - fclose(out); - return 1; -} - -/** offline verify for zonemd, while reading a zone file to immediately - * spot bad hashes in zonefile as they are read. - * Creates temp buffers, but uses anchors and validation environment - * from the module_env. */ -static void -zonemd_offline_verify(struct auth_zone* z, struct module_env* env_for_val, - struct module_stack* mods) -{ - struct module_env env; - time_t now = 0; - if(!z->zonemd_check) - return; - env = *env_for_val; - env.scratch_buffer = sldns_buffer_new(env.cfg->msg_buffer_size); - if(!env.scratch_buffer) { - log_err("out of memory"); - goto clean_exit; - } - env.scratch = regional_create(); - if(!env.now) { - env.now = &now; - now = time(NULL); - } - if(!env.scratch) { - log_err("out of memory"); - goto clean_exit; - } - auth_zone_verify_zonemd(z, &env, mods, NULL, 1, 0); - -clean_exit: - /* clean up and exit */ - sldns_buffer_free(env.scratch_buffer); - regional_destroy(env.scratch); -} - -/** read all auth zones from file (if they have) */ -static int -auth_zones_read_zones(struct auth_zones* az, struct config_file* cfg, - struct module_env* env, struct module_stack* mods) -{ - struct auth_zone* z; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_wrlock(&z->lock); - if(!auth_zone_read_zonefile(z, cfg)) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); - return 0; - } - if(z->zonefile && z->zonefile[0]!=0 && env) - zonemd_offline_verify(z, env, mods); - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&az->lock); - return 1; -} - -/** fetch the content of a ZONEMD RR from the rdata */ -static int zonemd_fetch_parameters(struct auth_rrset* zonemd_rrset, size_t i, - uint32_t* serial, int* scheme, int* hashalgo, uint8_t** hash, - size_t* hashlen) -{ - size_t rr_len; - uint8_t* rdata; - if(i >= zonemd_rrset->data->count) - return 0; - rr_len = zonemd_rrset->data->rr_len[i]; - if(rr_len < 2+4+1+1) - return 0; /* too short, for rdlen+serial+scheme+algo */ - rdata = zonemd_rrset->data->rr_data[i]; - *serial = sldns_read_uint32(rdata+2); - *scheme = rdata[6]; - *hashalgo = rdata[7]; - *hashlen = rr_len - 8; - if(*hashlen == 0) - *hash = NULL; - else *hash = rdata+8; - return 1; -} - -/** - * See if the ZONEMD scheme, hash occurs more than once. - * @param zonemd_rrset: the zonemd rrset to check with the RRs in it. - * @param index: index of the original, this is allowed to have that - * scheme and hashalgo, but other RRs should not have it. - * @param scheme: the scheme to check for. - * @param hashalgo: the hash algorithm to check for. - * @return true if it occurs more than once. - */ -static int zonemd_is_duplicate_scheme_hash(struct auth_rrset* zonemd_rrset, - size_t index, int scheme, int hashalgo) -{ - size_t j; - for(j=0; jdata->count; j++) { - uint32_t serial2 = 0; - int scheme2 = 0, hashalgo2 = 0; - uint8_t* hash2 = NULL; - size_t hashlen2 = 0; - if(index == j) { - /* this is the original */ - continue; - } - if(!zonemd_fetch_parameters(zonemd_rrset, j, &serial2, - &scheme2, &hashalgo2, &hash2, &hashlen2)) { - /* malformed, skip it */ - continue; - } - if(scheme == scheme2 && hashalgo == hashalgo2) { - /* duplicate scheme, hash */ - verbose(VERB_ALGO, "zonemd duplicate for scheme %d " - "and hash %d", scheme, hashalgo); - return 1; - } - } - return 0; -} - -/** - * Check ZONEMDs if present for the auth zone. Depending on config - * it can warn or fail on that. Checks the hash of the ZONEMD. - * @param z: auth zone to check for. - * caller must hold lock on zone. - * @param env: module env for temp buffers. - * @param reason: returned on failure. - * @return false on failure, true if hash checks out. - */ -static int auth_zone_zonemd_check_hash(struct auth_zone* z, - struct module_env* env, char** reason) -{ - /* loop over ZONEMDs and see which one is valid. if not print - * failure (depending on config) */ - struct auth_data* apex; - struct auth_rrset* zonemd_rrset; - size_t i; - struct regional* region = NULL; - struct sldns_buffer* buf = NULL; - uint32_t soa_serial = 0; - char* unsupported_reason = NULL; - int only_unsupported = 1; - region = env->scratch; - regional_free_all(region); - buf = env->scratch_buffer; - if(!auth_zone_get_serial(z, &soa_serial)) { - *reason = "zone has no SOA serial"; - return 0; - } - - apex = az_find_name(z, z->name, z->namelen); - if(!apex) { - *reason = "zone has no apex"; - return 0; - } - zonemd_rrset = az_domain_rrset(apex, LDNS_RR_TYPE_ZONEMD); - if(!zonemd_rrset || zonemd_rrset->data->count==0) { - *reason = "zone has no ZONEMD"; - return 0; /* no RRset or no RRs in rrset */ - } - - /* we have a ZONEMD, check if it is correct */ - for(i=0; idata->count; i++) { - uint32_t serial = 0; - int scheme = 0, hashalgo = 0; - uint8_t* hash = NULL; - size_t hashlen = 0; - if(!zonemd_fetch_parameters(zonemd_rrset, i, &serial, &scheme, - &hashalgo, &hash, &hashlen)) { - /* malformed RR */ - *reason = "ZONEMD rdata malformed"; - only_unsupported = 0; - continue; - } - /* check for duplicates */ - if(zonemd_is_duplicate_scheme_hash(zonemd_rrset, i, scheme, - hashalgo)) { - /* duplicate hash of the same scheme,hash - * is not allowed. */ - *reason = "ZONEMD RRSet contains more than one RR " - "with the same scheme and hash algorithm"; - only_unsupported = 0; - continue; - } - regional_free_all(region); - if(serial != soa_serial) { - *reason = "ZONEMD serial is wrong"; - only_unsupported = 0; - continue; - } - *reason = NULL; - if(auth_zone_generate_zonemd_check(z, scheme, hashalgo, - hash, hashlen, region, buf, reason)) { - /* success */ - if(*reason) { - if(!unsupported_reason) - unsupported_reason = *reason; - /* continue to check for valid ZONEMD */ - if(verbosity >= VERB_ALGO) { - char zstr[255+1]; - dname_str(z->name, zstr); - verbose(VERB_ALGO, "auth-zone %s ZONEMD %d %d is unsupported: %s", zstr, (int)scheme, (int)hashalgo, *reason); - } - *reason = NULL; - continue; - } - if(verbosity >= VERB_ALGO) { - char zstr[255+1]; - dname_str(z->name, zstr); - if(!*reason) - verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr); - } - return 1; - } - only_unsupported = 0; - /* try next one */ - } - /* have we seen no failures but only unsupported algo, - * and one unsupported algorithm, or more. */ - if(only_unsupported && unsupported_reason) { - /* only unsupported algorithms, with valid serial, not - * malformed. Did not see supported algorithms, failed or - * successful ones. */ - *reason = unsupported_reason; - return 1; - } - /* fail, we may have reason */ - if(!*reason) - *reason = "no ZONEMD records found"; - if(verbosity >= VERB_ALGO) { - char zstr[255+1]; - dname_str(z->name, zstr); - verbose(VERB_ALGO, "auth-zone %s ZONEMD failed: %s", zstr, *reason); - } - return 0; -} - -/** find the apex SOA RRset, if it exists */ -struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z) -{ - struct auth_data* apex; - struct auth_rrset* soa; - apex = az_find_name(z, z->name, z->namelen); - if(!apex) return NULL; - soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); - return soa; -} - -/** find serial number of zone or false if none */ -int -auth_zone_get_serial(struct auth_zone* z, uint32_t* serial) -{ - struct auth_data* apex; - struct auth_rrset* soa; - struct packed_rrset_data* d; - apex = az_find_name(z, z->name, z->namelen); - if(!apex) return 0; - soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); - if(!soa || soa->data->count==0) - return 0; /* no RRset or no RRs in rrset */ - if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */ - d = soa->data; - *serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20)); - return 1; -} - -/** Find auth_zone SOA and populate the values in xfr(soa values). */ -int -xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr) -{ - struct auth_data* apex; - struct auth_rrset* soa; - struct packed_rrset_data* d; - apex = az_find_name(z, z->name, z->namelen); - if(!apex) return 0; - soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); - if(!soa || soa->data->count==0) - return 0; /* no RRset or no RRs in rrset */ - if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */ - /* SOA record ends with serial, refresh, retry, expiry, minimum, - * as 4 byte fields */ - d = soa->data; - xfr->have_zone = 1; - xfr->serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20)); - xfr->refresh = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-16)); - xfr->retry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-12)); - xfr->expiry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-8)); - /* soa minimum at d->rr_len[0]-4 */ - return 1; -} - -/** - * Setup auth_xfer zone - * This populates the have_zone, soa values, and so on times. - * Doesn't do network traffic yet, can set option flags. - * @param z: locked by caller, and modified for setup - * @param x: locked by caller, and modified. - * @return false on failure. - */ -static int -auth_xfer_setup(struct auth_zone* z, struct auth_xfer* x) -{ - /* for a zone without zone transfers, x==NULL, so skip them, - * i.e. the zone config is fixed with no masters or urls */ - if(!z || !x) return 1; - if(!xfr_find_soa(z, x)) { - return 1; - } - /* nothing for probe, nextprobe and transfer tasks */ - return 1; -} - -/** - * Setup all zones - * @param az: auth zones structure - * @return false on failure. - */ -static int -auth_zones_setup_zones(struct auth_zones* az) -{ - struct auth_zone* z; - struct auth_xfer* x; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_wrlock(&z->lock); - x = auth_xfer_find(az, z->name, z->namelen, z->dclass); - if(x) { - lock_basic_lock(&x->lock); - } - if(!auth_xfer_setup(z, x)) { - if(x) { - lock_basic_unlock(&x->lock); - } - lock_rw_unlock(&z->lock); - lock_rw_unlock(&az->lock); - return 0; - } - if(x) { - lock_basic_unlock(&x->lock); - } - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&az->lock); - return 1; -} - -/** set config items and create zones */ -static int -auth_zones_cfg(struct auth_zones* az, struct config_auth* c) -{ - struct auth_zone* z; - struct auth_xfer* x = NULL; - - /* create zone */ - if(c->isrpz) { - /* if the rpz lock is needed, grab it before the other - * locks to avoid a lock dependency cycle */ - lock_rw_wrlock(&az->rpz_lock); - } - lock_rw_wrlock(&az->lock); - if(!(z=auth_zones_find_or_add_zone(az, c->name))) { - lock_rw_unlock(&az->lock); - if(c->isrpz) { - lock_rw_unlock(&az->rpz_lock); - } - return 0; - } - if(c->masters || c->urls) { - if(!(x=auth_zones_find_or_add_xfer(az, z))) { - lock_rw_unlock(&az->lock); - lock_rw_unlock(&z->lock); - if(c->isrpz) { - lock_rw_unlock(&az->rpz_lock); - } - return 0; - } - } - if(c->for_downstream) - az->have_downstream = 1; - lock_rw_unlock(&az->lock); - - /* set options */ - z->zone_deleted = 0; - if(!auth_zone_set_zonefile(z, c->zonefile)) { - if(x) { - lock_basic_unlock(&x->lock); - } - lock_rw_unlock(&z->lock); - if(c->isrpz) { - lock_rw_unlock(&az->rpz_lock); - } - return 0; - } - z->for_downstream = c->for_downstream; - z->for_upstream = c->for_upstream; - z->fallback_enabled = c->fallback_enabled; - z->zonemd_check = c->zonemd_check; - z->zonemd_reject_absence = c->zonemd_reject_absence; - if(c->isrpz && !z->rpz){ - if(!(z->rpz = rpz_create(c))){ - fatal_exit("Could not setup RPZ zones"); - return 0; - } - lock_protect(&z->lock, &z->rpz->local_zones, sizeof(*z->rpz)); - /* the az->rpz_lock is locked above */ - z->rpz_az_next = az->rpz_first; - if(az->rpz_first) - az->rpz_first->rpz_az_prev = z; - az->rpz_first = z; - } - if(c->isrpz) { - lock_rw_unlock(&az->rpz_lock); - } - - /* xfer zone */ - if(x) { - z->zone_is_slave = 1; - /* set options on xfer zone */ - if(!xfer_set_masters(&x->task_probe->masters, c, 0)) { - lock_basic_unlock(&x->lock); - lock_rw_unlock(&z->lock); - return 0; - } - if(!xfer_set_masters(&x->task_transfer->masters, c, 1)) { - lock_basic_unlock(&x->lock); - lock_rw_unlock(&z->lock); - return 0; - } - lock_basic_unlock(&x->lock); - } - - lock_rw_unlock(&z->lock); - return 1; -} - -/** set all auth zones deleted, then in auth_zones_cfg, it marks them - * as nondeleted (if they are still in the config), and then later - * we can find deleted zones */ -static void -az_setall_deleted(struct auth_zones* az) -{ - struct auth_zone* z; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_wrlock(&z->lock); - z->zone_deleted = 1; - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&az->lock); -} - -/** find zones that are marked deleted and delete them. - * This is called from apply_cfg, and there are no threads and no - * workers, so the xfr can just be deleted. */ -static void -az_delete_deleted_zones(struct auth_zones* az) -{ - struct auth_zone* z; - struct auth_zone* delete_list = NULL, *next; - struct auth_xfer* xfr; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_wrlock(&z->lock); - if(z->zone_deleted) { - /* we cannot alter the rbtree right now, but - * we can put it on a linked list and then - * delete it */ - z->delete_next = delete_list; - delete_list = z; - } - lock_rw_unlock(&z->lock); - } - /* now we are out of the tree loop and we can loop and delete - * the zones */ - z = delete_list; - while(z) { - next = z->delete_next; - xfr = auth_xfer_find(az, z->name, z->namelen, z->dclass); - if(xfr) { - (void)rbtree_delete(&az->xtree, &xfr->node); - auth_xfer_delete(xfr); - } - (void)rbtree_delete(&az->ztree, &z->node); - auth_zone_delete(z, az); - z = next; - } - lock_rw_unlock(&az->lock); -} - -int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg, - int setup, int* is_rpz, struct module_env* env, - struct module_stack* mods) -{ - struct config_auth* p; - az_setall_deleted(az); - for(p = cfg->auths; p; p = p->next) { - if(!p->name || p->name[0] == 0) { - log_warn("auth-zone without a name, skipped"); - continue; - } - *is_rpz = (*is_rpz || p->isrpz); - if(!auth_zones_cfg(az, p)) { - log_err("cannot config auth zone %s", p->name); - return 0; - } - } - az_delete_deleted_zones(az); - if(!auth_zones_read_zones(az, cfg, env, mods)) - return 0; - if(setup) { - if(!auth_zones_setup_zones(az)) - return 0; - } - return 1; -} - -/** delete chunks - * @param at: transfer structure with chunks list. The chunks and their - * data are freed. - */ -static void -auth_chunks_delete(struct auth_transfer* at) -{ - if(at->chunks_first) { - struct auth_chunk* c, *cn; - c = at->chunks_first; - while(c) { - cn = c->next; - free(c->data); - free(c); - c = cn; - } - } - at->chunks_first = NULL; - at->chunks_last = NULL; -} - -/** free master addr list */ -static void -auth_free_master_addrs(struct auth_addr* list) -{ - struct auth_addr *n; - while(list) { - n = list->next; - free(list); - list = n; - } -} - -/** free the masters list */ -static void -auth_free_masters(struct auth_master* list) -{ - struct auth_master* n; - while(list) { - n = list->next; - auth_free_master_addrs(list->list); - free(list->host); - free(list->file); - free(list); - list = n; - } -} - -/** delete auth xfer structure - * @param xfr: delete this xfer and its tasks. - */ -void -auth_xfer_delete(struct auth_xfer* xfr) -{ - if(!xfr) return; - lock_basic_destroy(&xfr->lock); - free(xfr->name); - if(xfr->task_nextprobe) { - comm_timer_delete(xfr->task_nextprobe->timer); - free(xfr->task_nextprobe); - } - if(xfr->task_probe) { - auth_free_masters(xfr->task_probe->masters); - comm_point_delete(xfr->task_probe->cp); - comm_timer_delete(xfr->task_probe->timer); - free(xfr->task_probe); - } - if(xfr->task_transfer) { - auth_free_masters(xfr->task_transfer->masters); - comm_point_delete(xfr->task_transfer->cp); - comm_timer_delete(xfr->task_transfer->timer); - if(xfr->task_transfer->chunks_first) { - auth_chunks_delete(xfr->task_transfer); - } - free(xfr->task_transfer); - } - auth_free_masters(xfr->allow_notify_list); - free(xfr); -} - -/** helper traverse to delete zones */ -static void -auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct auth_zone* z = (struct auth_zone*)n->key; - auth_zone_delete(z, NULL); -} - -/** helper traverse to delete xfer zones */ -static void -auth_xfer_del(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct auth_xfer* z = (struct auth_xfer*)n->key; - auth_xfer_delete(z); -} - -void auth_zones_delete(struct auth_zones* az) -{ - if(!az) return; - lock_rw_destroy(&az->lock); - lock_rw_destroy(&az->rpz_lock); - traverse_postorder(&az->ztree, auth_zone_del, NULL); - traverse_postorder(&az->xtree, auth_xfer_del, NULL); - free(az); -} - -/** true if domain has only nsec3 */ -static int -domain_has_only_nsec3(struct auth_data* n) -{ - struct auth_rrset* rrset = n->rrsets; - int nsec3_seen = 0; - while(rrset) { - if(rrset->type == LDNS_RR_TYPE_NSEC3) { - nsec3_seen = 1; - } else if(rrset->type != LDNS_RR_TYPE_RRSIG) { - return 0; - } - rrset = rrset->next; - } - return nsec3_seen; -} - -/** see if the domain has a wildcard child '*.domain' */ -static struct auth_data* -az_find_wildcard_domain(struct auth_zone* z, uint8_t* nm, size_t nmlen) -{ - uint8_t wc[LDNS_MAX_DOMAINLEN]; - if(nmlen+2 > sizeof(wc)) - return NULL; /* result would be too long */ - wc[0] = 1; /* length of wildcard label */ - wc[1] = (uint8_t)'*'; /* wildcard label */ - memmove(wc+2, nm, nmlen); - return az_find_name(z, wc, nmlen+2); -} - -/** find wildcard between qname and cename */ -static struct auth_data* -az_find_wildcard(struct auth_zone* z, struct query_info* qinfo, - struct auth_data* ce) -{ - uint8_t* nm = qinfo->qname; - size_t nmlen = qinfo->qname_len; - struct auth_data* node; - if(!dname_subdomain_c(nm, z->name)) - return NULL; /* out of zone */ - while((node=az_find_wildcard_domain(z, nm, nmlen))==NULL) { - /* see if we can go up to find the wildcard */ - if(nmlen == z->namelen) - return NULL; /* top of zone reached */ - if(ce && nmlen == ce->namelen) - return NULL; /* ce reached */ - if(dname_is_root(nm)) - return NULL; /* cannot go up */ - dname_remove_label(&nm, &nmlen); - } - return node; -} - -/** domain is not exact, find first candidate ce (name that matches - * a part of qname) in tree */ -static struct auth_data* -az_find_candidate_ce(struct auth_zone* z, struct query_info* qinfo, - struct auth_data* n) -{ - uint8_t* nm; - size_t nmlen; - if(n) { - nm = dname_get_shared_topdomain(qinfo->qname, n->name); - } else { - nm = qinfo->qname; - } - dname_count_size_labels(nm, &nmlen); - n = az_find_name(z, nm, nmlen); - /* delete labels and go up on name */ - while(!n) { - if(dname_is_root(nm)) - return NULL; /* cannot go up */ - dname_remove_label(&nm, &nmlen); - n = az_find_name(z, nm, nmlen); - } - return n; -} - -/** go up the auth tree to next existing name. */ -static struct auth_data* -az_domain_go_up(struct auth_zone* z, struct auth_data* n) -{ - uint8_t* nm = n->name; - size_t nmlen = n->namelen; - while(!dname_is_root(nm)) { - dname_remove_label(&nm, &nmlen); - if((n=az_find_name(z, nm, nmlen)) != NULL) - return n; - } - return NULL; -} - -/** Find the closest encloser, an name that exists and is above the - * qname. - * return true if the node (param node) is existing, nonobscured and - * can be used to generate answers from. It is then also node_exact. - * returns false if the node is not good enough (or it wasn't node_exact) - * in this case the ce can be filled. - * if ce is NULL, no ce exists, and likely the zone is completely empty, - * not even with a zone apex. - * if ce is nonNULL it is the closest enclosing upper name (that exists - * itself for answer purposes). That name may have DNAME, NS or wildcard - * rrset is the closest DNAME or NS rrset that was found. - */ -static int -az_find_ce(struct auth_zone* z, struct query_info* qinfo, - struct auth_data* node, int node_exact, struct auth_data** ce, - struct auth_rrset** rrset) -{ - struct auth_data* n = node; - *ce = NULL; - *rrset = NULL; - if(!node_exact) { - /* if not exact, lookup closest exact match */ - n = az_find_candidate_ce(z, qinfo, n); - } else { - /* if exact, the node itself is the first candidate ce */ - *ce = n; - } - - /* no direct answer from nsec3-only domains */ - if(n && domain_has_only_nsec3(n)) { - node_exact = 0; - *ce = NULL; - } - - /* with exact matches, walk up the labels until we find the - * delegation, or DNAME or zone end */ - while(n) { - /* see if the current candidate has issues */ - /* not zone apex and has type NS */ - if(n->namelen != z->namelen && - (*rrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) && - /* delegate here, but DS at exact the dp has notype */ - (qinfo->qtype != LDNS_RR_TYPE_DS || - n->namelen != qinfo->qname_len)) { - /* referral */ - /* this is ce and the lowernode is nonexisting */ - *ce = n; - return 0; - } - /* not equal to qname and has type DNAME */ - if(n->namelen != qinfo->qname_len && - (*rrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) { - /* this is ce and the lowernode is nonexisting */ - *ce = n; - return 0; - } - - if(*ce == NULL && !domain_has_only_nsec3(n)) { - /* if not found yet, this exact name must be - * our lowest match (but not nsec3onlydomain) */ - *ce = n; - } - - /* walk up the tree by removing labels from name and lookup */ - n = az_domain_go_up(z, n); - } - /* found no problems, if it was an exact node, it is fine to use */ - return node_exact; -} - -/** add additional A/AAAA from domain names in rrset rdata (+offset) - * offset is number of bytes in rdata where the dname is located. */ -static int -az_add_additionals_from(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_rrset* rrset, size_t offset) -{ - struct packed_rrset_data* d = rrset->data; - size_t i; - if(!d) return 0; - for(i=0; icount; i++) { - size_t dlen; - struct auth_data* domain; - struct auth_rrset* ref; - if(d->rr_len[i] < 2+offset) - continue; /* too short */ - if(!(dlen = dname_valid(d->rr_data[i]+2+offset, - d->rr_len[i]-2-offset))) - continue; /* malformed */ - domain = az_find_name(z, d->rr_data[i]+2+offset, dlen); - if(!domain) - continue; - if((ref=az_domain_rrset(domain, LDNS_RR_TYPE_A)) != NULL) { - if(!msg_add_rrset_ar(z, region, msg, domain, ref)) - return 0; - } - if((ref=az_domain_rrset(domain, LDNS_RR_TYPE_AAAA)) != NULL) { - if(!msg_add_rrset_ar(z, region, msg, domain, ref)) - return 0; - } - } - return 1; -} - -/** add negative SOA record (with negative TTL) */ -static int -az_add_negative_soa(struct auth_zone* z, struct regional* region, - struct dns_msg* msg) -{ - time_t minimum; - size_t i; - struct packed_rrset_data* d; - struct auth_rrset* soa; - struct auth_data* apex = az_find_name(z, z->name, z->namelen); - if(!apex) return 0; - soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); - if(!soa) return 0; - /* must be first to put in message; we want to fix the TTL with - * one RRset here, otherwise we'd need to loop over the RRs to get - * the resulting lower TTL */ - log_assert(msg->rep->rrset_count == 0); - if(!msg_add_rrset_ns(z, region, msg, apex, soa)) return 0; - /* fixup TTL */ - d = (struct packed_rrset_data*)msg->rep->rrsets[msg->rep->rrset_count-1]->entry.data; - /* last 4 bytes are minimum ttl in network format */ - if(d->count == 0) return 0; - if(d->rr_len[0] < 2+4) return 0; - minimum = (time_t)sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-4)); - minimum = d->ttlttl:minimum; - d->ttl = minimum; - for(i=0; i < d->count + d->rrsig_count; i++) - d->rr_ttl[i] = minimum; - msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[0]); - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - return 1; -} - -/** See if the query goes to empty nonterminal (that has no auth_data, - * but there are nodes underneath. We already checked that there are - * not NS, or DNAME above, so that we only need to check if some node - * exists below (with nonempty rr list), return true if emptynonterminal */ -static int -az_empty_nonterminal(struct auth_zone* z, struct query_info* qinfo, - struct auth_data* node) -{ - struct auth_data* next; - if(!node) { - /* no smaller was found, use first (smallest) node as the - * next one */ - next = (struct auth_data*)rbtree_first(&z->data); - } else { - next = (struct auth_data*)rbtree_next(&node->node); - } - while(next && (rbnode_type*)next != RBTREE_NULL && next->rrsets == NULL) { - /* the next name has empty rrsets, is an empty nonterminal - * itself, see if there exists something below it */ - next = (struct auth_data*)rbtree_next(&node->node); - } - if((rbnode_type*)next == RBTREE_NULL || !next) { - /* there is no next node, so something below it cannot - * exist */ - return 0; - } - /* a next node exists, if there was something below the query, - * this node has to be it. See if it is below the query name */ - if(dname_strict_subdomain_c(next->name, qinfo->qname)) - return 1; - return 0; -} - -/** create synth cname target name in buffer, or fail if too long */ -static size_t -synth_cname_buf(uint8_t* qname, size_t qname_len, size_t dname_len, - uint8_t* dtarg, size_t dtarglen, uint8_t* buf, size_t buflen) -{ - size_t newlen = qname_len + dtarglen - dname_len; - if(newlen > buflen) { - /* YXDOMAIN error */ - return 0; - } - /* new name is concatenation of qname front (without DNAME owner) - * and DNAME target name */ - memcpy(buf, qname, qname_len-dname_len); - memmove(buf+(qname_len-dname_len), dtarg, dtarglen); - return newlen; -} - -/** create synthetic CNAME rrset for in a DNAME answer in region, - * false on alloc failure, cname==NULL when name too long. */ -static int -create_synth_cname(uint8_t* qname, size_t qname_len, struct regional* region, - struct auth_data* node, struct auth_rrset* dname, uint16_t dclass, - struct ub_packed_rrset_key** cname) -{ - uint8_t buf[LDNS_MAX_DOMAINLEN]; - uint8_t* dtarg; - size_t dtarglen, newlen; - struct packed_rrset_data* d; - - /* get DNAME target name */ - if(dname->data->count < 1) return 0; - if(dname->data->rr_len[0] < 3) return 0; /* at least rdatalen +1 */ - dtarg = dname->data->rr_data[0]+2; - dtarglen = dname->data->rr_len[0]-2; - if(sldns_read_uint16(dname->data->rr_data[0]) != dtarglen) - return 0; /* rdatalen in DNAME rdata is malformed */ - if(dname_valid(dtarg, dtarglen) != dtarglen) - return 0; /* DNAME RR has malformed rdata */ - if(qname_len == 0) - return 0; /* too short */ - if(qname_len <= node->namelen) - return 0; /* qname too short for dname removal */ - - /* synthesize a CNAME */ - newlen = synth_cname_buf(qname, qname_len, node->namelen, - dtarg, dtarglen, buf, sizeof(buf)); - if(newlen == 0) { - /* YXDOMAIN error */ - *cname = NULL; - return 1; - } - *cname = (struct ub_packed_rrset_key*)regional_alloc(region, - sizeof(struct ub_packed_rrset_key)); - if(!*cname) - return 0; /* out of memory */ - memset(&(*cname)->entry, 0, sizeof((*cname)->entry)); - (*cname)->entry.key = (*cname); - (*cname)->rk.type = htons(LDNS_RR_TYPE_CNAME); - (*cname)->rk.rrset_class = htons(dclass); - (*cname)->rk.flags = 0; - (*cname)->rk.dname = regional_alloc_init(region, qname, qname_len); - if(!(*cname)->rk.dname) - return 0; /* out of memory */ - (*cname)->rk.dname_len = qname_len; - (*cname)->entry.hash = rrset_key_hash(&(*cname)->rk); - d = (struct packed_rrset_data*)regional_alloc_zero(region, - sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t) - + newlen); - if(!d) - return 0; /* out of memory */ - (*cname)->entry.data = d; - d->ttl = 0; /* 0 for synthesized CNAME TTL */ - d->count = 1; - d->rrsig_count = 0; - d->trust = rrset_trust_ans_noAA; - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - d->rr_len[0] = newlen + sizeof(uint16_t); - packed_rrset_ptr_fixup(d); - d->rr_ttl[0] = d->ttl; - sldns_write_uint16(d->rr_data[0], newlen); - memmove(d->rr_data[0] + sizeof(uint16_t), buf, newlen); - return 1; -} - -/** add a synthesized CNAME to the answer section */ -static int -add_synth_cname(struct auth_zone* z, uint8_t* qname, size_t qname_len, - struct regional* region, struct dns_msg* msg, struct auth_data* dname, - struct auth_rrset* rrset) -{ - struct ub_packed_rrset_key* cname; - /* synthesize a CNAME */ - if(!create_synth_cname(qname, qname_len, region, dname, rrset, - z->dclass, &cname)) { - /* out of memory */ - return 0; - } - if(!cname) { - /* cname cannot be create because of YXDOMAIN */ - msg->rep->flags |= LDNS_RCODE_YXDOMAIN; - return 1; - } - /* add cname to message */ - if(!msg_grow_array(region, msg)) - return 0; - msg->rep->rrsets[msg->rep->rrset_count] = cname; - msg->rep->rrset_count++; - msg->rep->an_numrrsets++; - msg_ttl(msg); - return 1; -} - -/** Change a dname to a different one, for wildcard namechange */ -static void -az_change_dnames(struct dns_msg* msg, uint8_t* oldname, uint8_t* newname, - size_t newlen, int an_only) -{ - size_t i; - size_t start = 0, end = msg->rep->rrset_count; - if(!an_only) start = msg->rep->an_numrrsets; - if(an_only) end = msg->rep->an_numrrsets; - for(i=start; irep->rrsets[i]->rk.dname, oldname) - == 0) { - msg->rep->rrsets[i]->rk.dname = newname; - msg->rep->rrsets[i]->rk.dname_len = newlen; - msg->rep->rrsets[i]->entry.hash = rrset_key_hash(&msg->rep->rrsets[i]->rk); - } - } -} - -/** find NSEC record covering the query */ -static struct auth_rrset* -az_find_nsec_cover(struct auth_zone* z, struct auth_data** node) -{ - uint8_t* nm = (*node)->name; - size_t nmlen = (*node)->namelen; - struct auth_rrset* rrset; - /* find the NSEC for the smallest-or-equal node */ - /* if node == NULL, we did not find a smaller name. But the zone - * name is the smallest name and should have an NSEC. So there is - * no NSEC to return (for a properly signed zone) */ - /* for empty nonterminals, the auth-data node should not exist, - * and thus we don't need to go rbtree_previous here to find - * a domain with an NSEC record */ - /* but there could be glue, and if this is node, then it has no NSEC. - * Go up to find nonglue (previous) NSEC-holding nodes */ - while((rrset=az_domain_rrset(*node, LDNS_RR_TYPE_NSEC)) == NULL) { - if(dname_is_root(nm)) return NULL; - if(nmlen == z->namelen) return NULL; - dname_remove_label(&nm, &nmlen); - /* adjust *node for the nsec rrset to find in */ - *node = az_find_name(z, nm, nmlen); - } - return rrset; -} - -/** Find NSEC and add for wildcard denial */ -static int -az_nsec_wildcard_denial(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, uint8_t* cenm, size_t cenmlen) -{ - struct query_info qinfo; - int node_exact; - struct auth_data* node; - struct auth_rrset* nsec; - uint8_t wc[LDNS_MAX_DOMAINLEN]; - if(cenmlen+2 > sizeof(wc)) - return 0; /* result would be too long */ - wc[0] = 1; /* length of wildcard label */ - wc[1] = (uint8_t)'*'; /* wildcard label */ - memmove(wc+2, cenm, cenmlen); - - /* we have '*.ce' in wc wildcard name buffer */ - /* get nsec cover for that */ - qinfo.qname = wc; - qinfo.qname_len = cenmlen+2; - qinfo.qtype = 0; - qinfo.qclass = 0; - az_find_domain(z, &qinfo, &node_exact, &node); - if((nsec=az_find_nsec_cover(z, &node)) != NULL) { - if(!msg_add_rrset_ns(z, region, msg, node, nsec)) return 0; - } - return 1; -} - -/** Find the NSEC3PARAM rrset (if any) and if true you have the parameters */ -static int -az_nsec3_param(struct auth_zone* z, int* algo, size_t* iter, uint8_t** salt, - size_t* saltlen) -{ - struct auth_data* apex; - struct auth_rrset* param; - size_t i; - apex = az_find_name(z, z->name, z->namelen); - if(!apex) return 0; - param = az_domain_rrset(apex, LDNS_RR_TYPE_NSEC3PARAM); - if(!param || param->data->count==0) - return 0; /* no RRset or no RRs in rrset */ - /* find out which NSEC3PARAM RR has supported parameters */ - /* skip unknown flags (dynamic signer is recalculating nsec3 chain) */ - for(i=0; idata->count; i++) { - uint8_t* rdata = param->data->rr_data[i]+2; - size_t rdatalen = param->data->rr_len[i]; - if(rdatalen < 2+5) - continue; /* too short */ - if(!nsec3_hash_algo_size_supported((int)(rdata[0]))) - continue; /* unsupported algo */ - if(rdatalen < (size_t)(2+5+(size_t)rdata[4])) - continue; /* salt missing */ - if((rdata[1]&NSEC3_UNKNOWN_FLAGS)!=0) - continue; /* unknown flags */ - *algo = (int)(rdata[0]); - *iter = sldns_read_uint16(rdata+2); - *saltlen = rdata[4]; - if(*saltlen == 0) - *salt = NULL; - else *salt = rdata+5; - return 1; - } - /* no supported params */ - return 0; -} - -/** Hash a name with nsec3param into buffer, it has zone name appended. - * return length of hash */ -static size_t -az_nsec3_hash(uint8_t* buf, size_t buflen, uint8_t* nm, size_t nmlen, - int algo, size_t iter, uint8_t* salt, size_t saltlen) -{ - size_t hlen = nsec3_hash_algo_size_supported(algo); - /* buffer has domain name, nsec3hash, and 256 is for max saltlen - * (salt has 0-255 length) */ - unsigned char p[LDNS_MAX_DOMAINLEN+1+N3HASHBUFLEN+256]; - size_t i; - if(nmlen+saltlen > sizeof(p) || hlen+saltlen > sizeof(p)) - return 0; - if(hlen > buflen) - return 0; /* somehow too large for destination buffer */ - /* hashfunc(name, salt) */ - memmove(p, nm, nmlen); - query_dname_tolower(p); - if(salt && saltlen > 0) - memmove(p+nmlen, salt, saltlen); - (void)secalgo_nsec3_hash(algo, p, nmlen+saltlen, (unsigned char*)buf); - for(i=0; i 0) - memmove(p+hlen, salt, saltlen); - (void)secalgo_nsec3_hash(algo, p, hlen+saltlen, - (unsigned char*)buf); - } - return hlen; -} - -/** Hash name and return b32encoded hashname for lookup, zone name appended */ -static int -az_nsec3_hashname(struct auth_zone* z, uint8_t* hashname, size_t* hashnmlen, - uint8_t* nm, size_t nmlen, int algo, size_t iter, uint8_t* salt, - size_t saltlen) -{ - uint8_t hash[N3HASHBUFLEN]; - size_t hlen; - int ret; - hlen = az_nsec3_hash(hash, sizeof(hash), nm, nmlen, algo, iter, - salt, saltlen); - if(!hlen) return 0; - /* b32 encode */ - if(*hashnmlen < hlen*2+1+z->namelen) /* approx b32 as hexb16 */ - return 0; - ret = sldns_b32_ntop_extended_hex(hash, hlen, (char*)(hashname+1), - (*hashnmlen)-1); - if(ret<1) - return 0; - hashname[0] = (uint8_t)ret; - ret++; - if((*hashnmlen) - ret < z->namelen) - return 0; - memmove(hashname+ret, z->name, z->namelen); - *hashnmlen = z->namelen+(size_t)ret; - return 1; -} - -/** Find the datanode that covers the nsec3hash-name */ -static struct auth_data* -az_nsec3_findnode(struct auth_zone* z, uint8_t* hashnm, size_t hashnmlen) -{ - struct query_info qinfo; - struct auth_data* node; - int node_exact; - qinfo.qclass = 0; - qinfo.qtype = 0; - qinfo.qname = hashnm; - qinfo.qname_len = hashnmlen; - /* because canonical ordering and b32 nsec3 ordering are the same. - * this is a good lookup to find the nsec3 name. */ - az_find_domain(z, &qinfo, &node_exact, &node); - /* but we may have to skip non-nsec3 nodes */ - /* this may be a lot, the way to speed that up is to have a - * separate nsec3 tree with nsec3 nodes */ - while(node && (rbnode_type*)node != RBTREE_NULL && - !az_domain_rrset(node, LDNS_RR_TYPE_NSEC3)) { - node = (struct auth_data*)rbtree_previous(&node->node); - } - if((rbnode_type*)node == RBTREE_NULL) - node = NULL; - return node; -} - -/** Find cover for hashed(nm, nmlen) (or NULL) */ -static struct auth_data* -az_nsec3_find_cover(struct auth_zone* z, uint8_t* nm, size_t nmlen, - int algo, size_t iter, uint8_t* salt, size_t saltlen) -{ - struct auth_data* node; - uint8_t hname[LDNS_MAX_DOMAINLEN]; - size_t hlen = sizeof(hname); - if(!az_nsec3_hashname(z, hname, &hlen, nm, nmlen, algo, iter, - salt, saltlen)) - return NULL; - node = az_nsec3_findnode(z, hname, hlen); - if(node) - return node; - /* we did not find any, perhaps because the NSEC3 hash is before - * the first hash, we have to find the 'last hash' in the zone */ - node = (struct auth_data*)rbtree_last(&z->data); - while(node && (rbnode_type*)node != RBTREE_NULL && - !az_domain_rrset(node, LDNS_RR_TYPE_NSEC3)) { - node = (struct auth_data*)rbtree_previous(&node->node); - } - if((rbnode_type*)node == RBTREE_NULL) - node = NULL; - return node; -} - -/** Find exact match for hashed(nm, nmlen) NSEC3 record or NULL */ -static struct auth_data* -az_nsec3_find_exact(struct auth_zone* z, uint8_t* nm, size_t nmlen, - int algo, size_t iter, uint8_t* salt, size_t saltlen) -{ - struct auth_data* node; - uint8_t hname[LDNS_MAX_DOMAINLEN]; - size_t hlen = sizeof(hname); - if(!az_nsec3_hashname(z, hname, &hlen, nm, nmlen, algo, iter, - salt, saltlen)) - return NULL; - node = az_find_name(z, hname, hlen); - if(az_domain_rrset(node, LDNS_RR_TYPE_NSEC3)) - return node; - return NULL; -} - -/** Return nextcloser name (as a ref into the qname). This is one label - * more than the cenm (cename must be a suffix of qname) */ -static void -az_nsec3_get_nextcloser(uint8_t* cenm, uint8_t* qname, size_t qname_len, - uint8_t** nx, size_t* nxlen) -{ - int celabs = dname_count_labels(cenm); - int qlabs = dname_count_labels(qname); - int strip = qlabs - celabs -1; - log_assert(dname_strict_subdomain(qname, qlabs, cenm, celabs)); - *nx = qname; - *nxlen = qname_len; - if(strip>0) - dname_remove_labels(nx, nxlen, strip); -} - -/** Find the closest encloser that has exact NSEC3. - * updated cenm to the new name. If it went up no-exact-ce is true. */ -static struct auth_data* -az_nsec3_find_ce(struct auth_zone* z, uint8_t** cenm, size_t* cenmlen, - int* no_exact_ce, int algo, size_t iter, uint8_t* salt, size_t saltlen) -{ - struct auth_data* node; - while((node = az_nsec3_find_exact(z, *cenm, *cenmlen, - algo, iter, salt, saltlen)) == NULL) { - if(*cenmlen == z->namelen) { - /* next step up would take us out of the zone. fail */ - return NULL; - } - *no_exact_ce = 1; - dname_remove_label(cenm, cenmlen); - } - return node; -} - -/* Insert NSEC3 record in authority section, if NULL does nothing */ -static int -az_nsec3_insert(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node) -{ - struct auth_rrset* nsec3; - if(!node) return 1; /* no node, skip this */ - nsec3 = az_domain_rrset(node, LDNS_RR_TYPE_NSEC3); - if(!nsec3) return 1; /* if no nsec3 RR, skip it */ - if(!msg_add_rrset_ns(z, region, msg, node, nsec3)) return 0; - return 1; -} - -/** add NSEC3 records to the zone for the nsec3 proof. - * Specify with the flags with parts of the proof are required. - * the ce is the exact matching name (for notype) but also delegation points. - * qname is the one where the nextcloser name can be derived from. - * If NSEC3 is not properly there (in the zone) nothing is added. - * always enabled: include nsec3 proving about the Closest Encloser. - * that is an exact match that should exist for it. - * If that does not exist, a higher exact match + nxproof is enabled - * (for some sort of opt-out empty nonterminal cases). - * nodataproof: search for exact match and include that instead. - * ceproof: include ce proof NSEC3 (omitted for wildcard replies). - * nxproof: include denial of the qname. - * wcproof: include denial of wildcard (wildcard.ce). - */ -static int -az_add_nsec3_proof(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, uint8_t* cenm, size_t cenmlen, uint8_t* qname, - size_t qname_len, int nodataproof, int ceproof, int nxproof, - int wcproof) -{ - int algo; - size_t iter, saltlen; - uint8_t* salt; - int no_exact_ce = 0; - struct auth_data* node; - - /* find parameters of nsec3 proof */ - if(!az_nsec3_param(z, &algo, &iter, &salt, &saltlen)) - return 1; /* no nsec3 */ - if(nodataproof) { - /* see if the node has a hash of itself for the nodata - * proof nsec3, this has to be an exact match nsec3. */ - struct auth_data* match; - match = az_nsec3_find_exact(z, qname, qname_len, algo, - iter, salt, saltlen); - if(match) { - if(!az_nsec3_insert(z, region, msg, match)) - return 0; - /* only nodata NSEC3 needed, no CE or others. */ - return 1; - } - } - /* find ce that has an NSEC3 */ - if(ceproof) { - node = az_nsec3_find_ce(z, &cenm, &cenmlen, &no_exact_ce, - algo, iter, salt, saltlen); - if(no_exact_ce) nxproof = 1; - if(!az_nsec3_insert(z, region, msg, node)) - return 0; - } - - if(nxproof) { - uint8_t* nx; - size_t nxlen; - /* create nextcloser domain name */ - az_nsec3_get_nextcloser(cenm, qname, qname_len, &nx, &nxlen); - /* find nsec3 that matches or covers it */ - node = az_nsec3_find_cover(z, nx, nxlen, algo, iter, salt, - saltlen); - if(!az_nsec3_insert(z, region, msg, node)) - return 0; - } - if(wcproof) { - /* create wildcard name *.ce */ - uint8_t wc[LDNS_MAX_DOMAINLEN]; - size_t wclen; - if(cenmlen+2 > sizeof(wc)) - return 0; /* result would be too long */ - wc[0] = 1; /* length of wildcard label */ - wc[1] = (uint8_t)'*'; /* wildcard label */ - memmove(wc+2, cenm, cenmlen); - wclen = cenmlen+2; - /* find nsec3 that matches or covers it */ - node = az_nsec3_find_cover(z, wc, wclen, algo, iter, salt, - saltlen); - if(!az_nsec3_insert(z, region, msg, node)) - return 0; - } - return 1; -} - -/** generate answer for positive answer */ -static int -az_generate_positive_answer(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset) -{ - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - /* see if we want additional rrs */ - if(rrset->type == LDNS_RR_TYPE_MX) { - if(!az_add_additionals_from(z, region, msg, rrset, 2)) - return 0; - } else if(rrset->type == LDNS_RR_TYPE_SRV) { - if(!az_add_additionals_from(z, region, msg, rrset, 6)) - return 0; - } else if(rrset->type == LDNS_RR_TYPE_NS) { - if(!az_add_additionals_from(z, region, msg, rrset, 0)) - return 0; - } - return 1; -} - -/** generate answer for type ANY answer */ -static int -az_generate_any_answer(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node) -{ - struct auth_rrset* rrset; - int added = 0; - /* add a couple (at least one) RRs */ - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_SOA)) != NULL) { - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - added++; - } - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_MX)) != NULL) { - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - added++; - } - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_A)) != NULL) { - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - added++; - } - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_AAAA)) != NULL) { - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - added++; - } - if(added == 0 && node && node->rrsets) { - if(!msg_add_rrset_an(z, region, msg, node, - node->rrsets)) return 0; - } - return 1; -} - -/** follow cname chain and add more data to the answer section */ -static int -follow_cname_chain(struct auth_zone* z, uint16_t qtype, - struct regional* region, struct dns_msg* msg, - struct packed_rrset_data* d) -{ - int maxchain = 0; - /* see if we can add the target of the CNAME into the answer */ - while(maxchain++ < MAX_CNAME_CHAIN) { - struct auth_data* node; - struct auth_rrset* rrset; - size_t clen; - /* d has cname rdata */ - if(d->count == 0) break; /* no CNAME */ - if(d->rr_len[0] < 2+1) break; /* too small */ - if((clen=dname_valid(d->rr_data[0]+2, d->rr_len[0]-2))==0) - break; /* malformed */ - if(!dname_subdomain_c(d->rr_data[0]+2, z->name)) - break; /* target out of zone */ - if((node = az_find_name(z, d->rr_data[0]+2, clen))==NULL) - break; /* no such target name */ - if((rrset=az_domain_rrset(node, qtype))!=NULL) { - /* done we found the target */ - if(!msg_add_rrset_an(z, region, msg, node, rrset)) - return 0; - break; - } - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_CNAME))==NULL) - break; /* no further CNAME chain, notype */ - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - d = rrset->data; - } - return 1; -} - -/** generate answer for cname answer */ -static int -az_generate_cname_answer(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg* msg, - struct auth_data* node, struct auth_rrset* rrset) -{ - if(!msg_add_rrset_an(z, region, msg, node, rrset)) return 0; - if(!rrset) return 1; - if(!follow_cname_chain(z, qinfo->qtype, region, msg, rrset->data)) - return 0; - return 1; -} - -/** generate answer for notype answer */ -static int -az_generate_notype_answer(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* node) -{ - struct auth_rrset* rrset; - if(!az_add_negative_soa(z, region, msg)) return 0; - /* DNSSEC denial NSEC */ - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_NSEC))!=NULL) { - if(!msg_add_rrset_ns(z, region, msg, node, rrset)) return 0; - } else if(node) { - /* DNSSEC denial NSEC3 */ - if(!az_add_nsec3_proof(z, region, msg, node->name, - node->namelen, msg->qinfo.qname, - msg->qinfo.qname_len, 1, 1, 0, 0)) - return 0; - } - return 1; -} - -/** generate answer for referral answer */ -static int -az_generate_referral_answer(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* ce, struct auth_rrset* rrset) -{ - struct auth_rrset* ds, *nsec; - /* turn off AA flag, referral is nonAA because it leaves the zone */ - log_assert(ce); - msg->rep->flags &= ~BIT_AA; - if(!msg_add_rrset_ns(z, region, msg, ce, rrset)) return 0; - /* add DS or deny it */ - if((ds=az_domain_rrset(ce, LDNS_RR_TYPE_DS))!=NULL) { - if(!msg_add_rrset_ns(z, region, msg, ce, ds)) return 0; - } else { - /* deny the DS */ - if((nsec=az_domain_rrset(ce, LDNS_RR_TYPE_NSEC))!=NULL) { - if(!msg_add_rrset_ns(z, region, msg, ce, nsec)) - return 0; - } else { - if(!az_add_nsec3_proof(z, region, msg, ce->name, - ce->namelen, msg->qinfo.qname, - msg->qinfo.qname_len, 1, 1, 0, 0)) - return 0; - } - } - /* add additional rrs for type NS */ - if(!az_add_additionals_from(z, region, msg, rrset, 0)) return 0; - return 1; -} - -/** generate answer for DNAME answer */ -static int -az_generate_dname_answer(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg* msg, struct auth_data* ce, - struct auth_rrset* rrset) -{ - log_assert(ce); - /* add the DNAME and then a CNAME */ - if(!msg_add_rrset_an(z, region, msg, ce, rrset)) return 0; - if(!add_synth_cname(z, qinfo->qname, qinfo->qname_len, region, - msg, ce, rrset)) return 0; - if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_YXDOMAIN) - return 1; - if(msg->rep->rrset_count == 0 || - !msg->rep->rrsets[msg->rep->rrset_count-1]) - return 0; - if(!follow_cname_chain(z, qinfo->qtype, region, msg, - (struct packed_rrset_data*)msg->rep->rrsets[ - msg->rep->rrset_count-1]->entry.data)) - return 0; - return 1; -} - -/** generate answer for wildcard answer */ -static int -az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg* msg, struct auth_data* ce, - struct auth_data* wildcard, struct auth_data* node) -{ - struct auth_rrset* rrset, *nsec; - int insert_ce = 0; - if((rrset=az_domain_rrset(wildcard, qinfo->qtype)) != NULL) { - /* wildcard has type, add it */ - if(!msg_add_rrset_an(z, region, msg, wildcard, rrset)) - return 0; - az_change_dnames(msg, wildcard->name, msg->qinfo.qname, - msg->qinfo.qname_len, 1); - } else if((rrset=az_domain_rrset(wildcard, LDNS_RR_TYPE_CNAME))!=NULL) { - /* wildcard has cname instead, do that */ - if(!msg_add_rrset_an(z, region, msg, wildcard, rrset)) - return 0; - az_change_dnames(msg, wildcard->name, msg->qinfo.qname, - msg->qinfo.qname_len, 1); - if(!follow_cname_chain(z, qinfo->qtype, region, msg, - rrset->data)) - return 0; - } else if(qinfo->qtype == LDNS_RR_TYPE_ANY && wildcard->rrsets) { - /* add ANY rrsets from wildcard node */ - if(!az_generate_any_answer(z, region, msg, wildcard)) - return 0; - az_change_dnames(msg, wildcard->name, msg->qinfo.qname, - msg->qinfo.qname_len, 1); - } else { - /* wildcard has nodata, notype answer */ - /* call other notype routine for dnssec notype denials */ - if(!az_generate_notype_answer(z, region, msg, wildcard)) - return 0; - /* because the notype, there is no positive data with an - * RRSIG that indicates the wildcard position. Thus the - * wildcard qname denial needs to have a CE nsec3. */ - insert_ce = 1; - } - - /* ce and node for dnssec denial of wildcard original name */ - if((nsec=az_find_nsec_cover(z, &node)) != NULL) { - if(!msg_add_rrset_ns(z, region, msg, node, nsec)) return 0; - } else if(ce) { - uint8_t* wildup = wildcard->name; - size_t wilduplen= wildcard->namelen; - dname_remove_label(&wildup, &wilduplen); - if(!az_add_nsec3_proof(z, region, msg, wildup, - wilduplen, msg->qinfo.qname, - msg->qinfo.qname_len, 0, insert_ce, 1, 0)) - return 0; - } - - /* fixup name of wildcard from *.zone to qname, use already allocated - * pointer to msg qname */ - az_change_dnames(msg, wildcard->name, msg->qinfo.qname, - msg->qinfo.qname_len, 0); - return 1; -} - -/** generate answer for nxdomain answer */ -static int -az_generate_nxdomain_answer(struct auth_zone* z, struct regional* region, - struct dns_msg* msg, struct auth_data* ce, struct auth_data* node) -{ - struct auth_rrset* nsec; - msg->rep->flags |= LDNS_RCODE_NXDOMAIN; - if(!az_add_negative_soa(z, region, msg)) return 0; - if((nsec=az_find_nsec_cover(z, &node)) != NULL) { - if(!msg_add_rrset_ns(z, region, msg, node, nsec)) return 0; - if(ce && !az_nsec_wildcard_denial(z, region, msg, ce->name, - ce->namelen)) return 0; - } else if(ce) { - if(!az_add_nsec3_proof(z, region, msg, ce->name, - ce->namelen, msg->qinfo.qname, - msg->qinfo.qname_len, 0, 1, 1, 1)) - return 0; - } - return 1; -} - -/** Create answers when an exact match exists for the domain name */ -static int -az_generate_answer_with_node(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg* msg, struct auth_data* node) -{ - struct auth_rrset* rrset; - /* positive answer, rrset we are looking for exists */ - if((rrset=az_domain_rrset(node, qinfo->qtype)) != NULL) { - return az_generate_positive_answer(z, region, msg, node, rrset); - } - /* CNAME? */ - if((rrset=az_domain_rrset(node, LDNS_RR_TYPE_CNAME)) != NULL) { - return az_generate_cname_answer(z, qinfo, region, msg, - node, rrset); - } - /* type ANY ? */ - if(qinfo->qtype == LDNS_RR_TYPE_ANY) { - return az_generate_any_answer(z, region, msg, node); - } - /* NOERROR/NODATA (no such type at domain name) */ - return az_generate_notype_answer(z, region, msg, node); -} - -/** Generate answer without an existing-node that we can use. - * So it'll be a referral, DNAME or nxdomain */ -static int -az_generate_answer_nonexistnode(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg* msg, struct auth_data* ce, - struct auth_rrset* rrset, struct auth_data* node) -{ - struct auth_data* wildcard; - - /* we do not have an exact matching name (that exists) */ - /* see if we have a NS or DNAME in the ce */ - if(ce && rrset && rrset->type == LDNS_RR_TYPE_NS) { - return az_generate_referral_answer(z, region, msg, ce, rrset); - } - if(ce && rrset && rrset->type == LDNS_RR_TYPE_DNAME) { - return az_generate_dname_answer(z, qinfo, region, msg, ce, - rrset); - } - /* if there is an empty nonterminal, wildcard and nxdomain don't - * happen, it is a notype answer */ - if(az_empty_nonterminal(z, qinfo, node)) { - return az_generate_notype_answer(z, region, msg, node); - } - /* see if we have a wildcard under the ce */ - if((wildcard=az_find_wildcard(z, qinfo, ce)) != NULL) { - return az_generate_wildcard_answer(z, qinfo, region, msg, - ce, wildcard, node); - } - /* generate nxdomain answer */ - return az_generate_nxdomain_answer(z, region, msg, ce, node); -} - -/** Lookup answer in a zone. */ -static int -auth_zone_generate_answer(struct auth_zone* z, struct query_info* qinfo, - struct regional* region, struct dns_msg** msg, int* fallback) -{ - struct auth_data* node, *ce; - struct auth_rrset* rrset; - int node_exact, node_exists; - /* does the zone want fallback in case of failure? */ - *fallback = z->fallback_enabled; - if(!(*msg=msg_create(region, qinfo))) return 0; - - /* lookup if there is a matching domain name for the query */ - az_find_domain(z, qinfo, &node_exact, &node); - - /* see if node exists for generating answers from (i.e. not glue and - * obscured by NS or DNAME or NSEC3-only), and also return the - * closest-encloser from that, closest node that should be used - * to generate answers from that is above the query */ - node_exists = az_find_ce(z, qinfo, node, node_exact, &ce, &rrset); - - if(verbosity >= VERB_ALGO) { - char zname[256], qname[256], nname[256], cename[256], - tpstr[32], rrstr[32]; - sldns_wire2str_dname_buf(qinfo->qname, qinfo->qname_len, qname, - sizeof(qname)); - sldns_wire2str_type_buf(qinfo->qtype, tpstr, sizeof(tpstr)); - sldns_wire2str_dname_buf(z->name, z->namelen, zname, - sizeof(zname)); - if(node) - sldns_wire2str_dname_buf(node->name, node->namelen, - nname, sizeof(nname)); - else snprintf(nname, sizeof(nname), "NULL"); - if(ce) - sldns_wire2str_dname_buf(ce->name, ce->namelen, - cename, sizeof(cename)); - else snprintf(cename, sizeof(cename), "NULL"); - if(rrset) sldns_wire2str_type_buf(rrset->type, rrstr, - sizeof(rrstr)); - else snprintf(rrstr, sizeof(rrstr), "NULL"); - log_info("auth_zone %s query %s %s, domain %s %s %s, " - "ce %s, rrset %s", zname, qname, tpstr, nname, - (node_exact?"exact":"notexact"), - (node_exists?"exist":"notexist"), cename, rrstr); - } - - if(node_exists) { - /* the node is fine, generate answer from node */ - return az_generate_answer_with_node(z, qinfo, region, *msg, - node); - } - return az_generate_answer_nonexistnode(z, qinfo, region, *msg, - ce, rrset, node); -} - -int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo, - struct regional* region, struct dns_msg** msg, int* fallback, - uint8_t* dp_nm, size_t dp_nmlen) -{ - int r; - struct auth_zone* z; - /* find the zone that should contain the answer. */ - lock_rw_rdlock(&az->lock); - z = auth_zone_find(az, dp_nm, dp_nmlen, qinfo->qclass); - if(!z) { - lock_rw_unlock(&az->lock); - /* no auth zone, fallback to internet */ - *fallback = 1; - return 0; - } - lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); - - /* if not for upstream queries, fallback */ - if(!z->for_upstream) { - lock_rw_unlock(&z->lock); - *fallback = 1; - return 0; - } - if(z->zone_expired) { - *fallback = z->fallback_enabled; - lock_rw_unlock(&z->lock); - return 0; - } - /* see what answer that zone would generate */ - r = auth_zone_generate_answer(z, qinfo, region, msg, fallback); - lock_rw_unlock(&z->lock); - return r; -} - -/** encode auth answer */ -static void -auth_answer_encode(struct query_info* qinfo, struct module_env* env, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, struct dns_msg* msg) -{ - uint16_t udpsize; - udpsize = edns->udp_size; - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - - if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep, - (int)FLAGS_GET_RCODE(msg->rep->flags), edns, repinfo, temp, env->now_tv) - || !reply_info_answer_encode(qinfo, msg->rep, - *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), - buf, 0, 0, temp, udpsize, edns, - (int)(edns->bits&EDNS_DO), 0)) { - error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, - *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), edns); - } -} - -/** encode auth error answer */ -static void -auth_error_encode(struct query_info* qinfo, struct module_env* env, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, int rcode) -{ - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - - if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, - rcode, edns, repinfo, temp, env->now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(buf, rcode|BIT_AA, qinfo, - *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), edns); -} - -int auth_zones_answer(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp) -{ - struct dns_msg* msg = NULL; - struct auth_zone* z; - int r; - int fallback = 0; - - lock_rw_rdlock(&az->lock); - if(!az->have_downstream) { - /* no downstream auth zones */ - lock_rw_unlock(&az->lock); - return 0; - } - if(qinfo->qtype == LDNS_RR_TYPE_DS) { - uint8_t* delname = qinfo->qname; - size_t delnamelen = qinfo->qname_len; - dname_remove_label(&delname, &delnamelen); - z = auth_zones_find_zone(az, delname, delnamelen, - qinfo->qclass); - } else { - z = auth_zones_find_zone(az, qinfo->qname, qinfo->qname_len, - qinfo->qclass); - } - if(!z) { - /* no zone above it */ - lock_rw_unlock(&az->lock); - return 0; - } - lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); - if(!z->for_downstream) { - lock_rw_unlock(&z->lock); - return 0; - } - if(z->zone_expired) { - if(z->fallback_enabled) { - lock_rw_unlock(&z->lock); - return 0; - } - lock_rw_unlock(&z->lock); - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); - auth_error_encode(qinfo, env, edns, repinfo, buf, temp, - LDNS_RCODE_SERVFAIL); - return 1; - } - - /* answer it from zone z */ - r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback); - lock_rw_unlock(&z->lock); - if(!r && fallback) { - /* fallback to regular answering (recursive) */ - return 0; - } - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); - - /* encode answer */ - if(!r) - auth_error_encode(qinfo, env, edns, repinfo, buf, temp, - LDNS_RCODE_SERVFAIL); - else auth_answer_encode(qinfo, env, edns, repinfo, buf, temp, msg); - - return 1; -} - -int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass) -{ - int r; - struct auth_zone* z; - lock_rw_rdlock(&az->lock); - z = auth_zone_find(az, nm, nmlen, dclass); - if(!z) { - lock_rw_unlock(&az->lock); - /* no such auth zone, fallback */ - return 1; - } - lock_rw_rdlock(&z->lock); - lock_rw_unlock(&az->lock); - r = z->fallback_enabled || (!z->for_upstream); - lock_rw_unlock(&z->lock); - return r; -} - -int -auth_zone_parse_notify_serial(sldns_buffer* pkt, uint32_t *serial) -{ - struct query_info q; - uint16_t rdlen; - memset(&q, 0, sizeof(q)); - sldns_buffer_set_position(pkt, 0); - if(!query_info_parse(&q, pkt)) return 0; - if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0) return 0; - /* skip name of RR in answer section */ - if(sldns_buffer_remaining(pkt) < 1) return 0; - if(pkt_dname_len(pkt) == 0) return 0; - /* check type */ - if(sldns_buffer_remaining(pkt) < 10 /* type,class,ttl,rdatalen*/) - return 0; - if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_SOA) return 0; - sldns_buffer_skip(pkt, 2); /* class */ - sldns_buffer_skip(pkt, 4); /* ttl */ - rdlen = sldns_buffer_read_u16(pkt); /* rdatalen */ - if(sldns_buffer_remaining(pkt) < rdlen) return 0; - if(rdlen < 22) return 0; /* bad soa length */ - sldns_buffer_skip(pkt, (ssize_t)(rdlen-20)); - *serial = sldns_buffer_read_u32(pkt); - /* return true when has serial in answer section */ - return 1; -} - -/** see if addr appears in the list */ -static int -addr_in_list(struct auth_addr* list, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - struct auth_addr* p; - for(p=list; p; p=p->next) { - if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) - return 1; - } - return 0; -} - -/** check if an address matches a master specification (or one of its - * addresses in the addr list) */ -static int -addr_matches_master(struct auth_master* master, struct sockaddr_storage* addr, - socklen_t addrlen, struct auth_master** fromhost) -{ - struct sockaddr_storage a; - socklen_t alen = 0; - int net = 0; - if(addr_in_list(master->list, addr, addrlen)) { - *fromhost = master; - return 1; - } - /* compare address (but not port number, that is the destination - * port of the master, the port number of the received notify is - * allowed to by any port on that master) */ - if(extstrtoaddr(master->host, &a, &alen, UNBOUND_DNS_PORT) && - sockaddr_cmp_addr(addr, addrlen, &a, alen)==0) { - *fromhost = master; - return 1; - } - /* prefixes, addr/len, like 10.0.0.0/8 */ - /* not http and has a / and there is one / */ - if(master->allow_notify && !master->http && - strchr(master->host, '/') != NULL && - strchr(master->host, '/') == strrchr(master->host, '/') && - netblockstrtoaddr(master->host, UNBOUND_DNS_PORT, &a, &alen, - &net) && alen == addrlen) { - if(addr_in_common(addr, (addr_is_ip6(addr, addrlen)?128:32), - &a, net, alen) >= net) { - *fromhost = NULL; /* prefix does not have destination - to send the probe or transfer with */ - return 1; /* matches the netblock */ - } - } - return 0; -} - -/** check access list for notifies */ -static int -az_xfr_allowed_notify(struct auth_xfer* xfr, struct sockaddr_storage* addr, - socklen_t addrlen, struct auth_master** fromhost) -{ - struct auth_master* p; - for(p=xfr->allow_notify_list; p; p=p->next) { - if(addr_matches_master(p, addr, addrlen, fromhost)) { - return 1; - } - } - return 0; -} - -/** see if the serial means the zone has to be updated, i.e. the serial - * is newer than the zone serial, or we have no zone */ -static int -xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial) -{ - if(!xfr->have_zone) - return 1; /* no zone, anything is better */ - if(xfr->zone_expired) - return 1; /* expired, the sent serial is better than expired - data */ - if(compare_serial(xfr->serial, serial) < 0) - return 1; /* our serial is smaller than the sent serial, - the data is newer, fetch it */ - return 0; -} - -/** note notify serial, updates the notify information in the xfr struct */ -static void -xfr_note_notify_serial(struct auth_xfer* xfr, int has_serial, uint32_t serial) -{ - if(xfr->notify_received && xfr->notify_has_serial && has_serial) { - /* see if this serial is newer */ - if(compare_serial(xfr->notify_serial, serial) < 0) - xfr->notify_serial = serial; - } else if(xfr->notify_received && xfr->notify_has_serial && - !has_serial) { - /* remove serial, we have notify without serial */ - xfr->notify_has_serial = 0; - xfr->notify_serial = 0; - } else if(xfr->notify_received && !xfr->notify_has_serial) { - /* we already have notify without serial, keep it - * that way; no serial check when current operation - * is done */ - } else { - xfr->notify_received = 1; - xfr->notify_has_serial = has_serial; - xfr->notify_serial = serial; - } -} - -/** process a notify serial, start new probe or note serial. xfr is locked */ -static void -xfr_process_notify(struct auth_xfer* xfr, struct module_env* env, - int has_serial, uint32_t serial, struct auth_master* fromhost) -{ - /* if the serial of notify is older than we have, don't fetch - * a zone, we already have it */ - if(has_serial && !xfr_serial_means_update(xfr, serial)) { - lock_basic_unlock(&xfr->lock); - return; - } - /* start new probe with this addr src, or note serial */ - if(!xfr_start_probe(xfr, env, fromhost)) { - /* not started because already in progress, note the serial */ - xfr_note_notify_serial(xfr, has_serial, serial); - lock_basic_unlock(&xfr->lock); - } - /* successful end of start_probe unlocked xfr->lock */ -} - -int auth_zones_notify(struct auth_zones* az, struct module_env* env, - uint8_t* nm, size_t nmlen, uint16_t dclass, - struct sockaddr_storage* addr, socklen_t addrlen, int has_serial, - uint32_t serial, int* refused) -{ - struct auth_xfer* xfr; - struct auth_master* fromhost = NULL; - /* see which zone this is */ - lock_rw_rdlock(&az->lock); - xfr = auth_xfer_find(az, nm, nmlen, dclass); - if(!xfr) { - lock_rw_unlock(&az->lock); - /* no such zone, refuse the notify */ - *refused = 1; - return 0; - } - lock_basic_lock(&xfr->lock); - lock_rw_unlock(&az->lock); - - /* check access list for notifies */ - if(!az_xfr_allowed_notify(xfr, addr, addrlen, &fromhost)) { - lock_basic_unlock(&xfr->lock); - /* notify not allowed, refuse the notify */ - *refused = 1; - return 0; - } - - /* process the notify */ - xfr_process_notify(xfr, env, has_serial, serial, fromhost); - return 1; -} - -int auth_zones_startprobesequence(struct auth_zones* az, - struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass) -{ - struct auth_xfer* xfr; - lock_rw_rdlock(&az->lock); - xfr = auth_xfer_find(az, nm, nmlen, dclass); - if(!xfr) { - lock_rw_unlock(&az->lock); - return 0; - } - lock_basic_lock(&xfr->lock); - lock_rw_unlock(&az->lock); - - xfr_process_notify(xfr, env, 0, 0, NULL); - return 1; -} - -/** set a zone expired */ -static void -auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env, - int expired) -{ - struct auth_zone* z; - - /* expire xfr */ - lock_basic_lock(&xfr->lock); - xfr->zone_expired = expired; - lock_basic_unlock(&xfr->lock); - - /* find auth_zone */ - lock_rw_rdlock(&env->auth_zones->lock); - z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, - xfr->dclass); - if(!z) { - lock_rw_unlock(&env->auth_zones->lock); - return; - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&env->auth_zones->lock); - - /* expire auth_zone */ - z->zone_expired = expired; - lock_rw_unlock(&z->lock); -} - -/** find master (from notify or probe) in list of masters */ -static struct auth_master* -find_master_by_host(struct auth_master* list, char* host) -{ - struct auth_master* p; - for(p=list; p; p=p->next) { - if(strcmp(p->host, host) == 0) - return p; - } - return NULL; -} - -/** delete the looked up auth_addrs for all the masters in the list */ -static void -xfr_masterlist_free_addrs(struct auth_master* list) -{ - struct auth_master* m; - for(m=list; m; m=m->next) { - if(m->list) { - auth_free_master_addrs(m->list); - m->list = NULL; - } - } -} - -/** copy a list of auth_addrs */ -static struct auth_addr* -auth_addr_list_copy(struct auth_addr* source) -{ - struct auth_addr* list = NULL, *last = NULL; - struct auth_addr* p; - for(p=source; p; p=p->next) { - struct auth_addr* a = (struct auth_addr*)memdup(p, sizeof(*p)); - if(!a) { - log_err("malloc failure"); - auth_free_master_addrs(list); - return NULL; - } - a->next = NULL; - if(last) last->next = a; - if(!list) list = a; - last = a; - } - return list; -} - -/** copy a master to a new structure, NULL on alloc failure */ -static struct auth_master* -auth_master_copy(struct auth_master* o) -{ - struct auth_master* m; - if(!o) return NULL; - m = (struct auth_master*)memdup(o, sizeof(*o)); - if(!m) { - log_err("malloc failure"); - return NULL; - } - m->next = NULL; - if(m->host) { - m->host = strdup(m->host); - if(!m->host) { - free(m); - log_err("malloc failure"); - return NULL; - } - } - if(m->file) { - m->file = strdup(m->file); - if(!m->file) { - free(m->host); - free(m); - log_err("malloc failure"); - return NULL; - } - } - if(m->list) { - m->list = auth_addr_list_copy(m->list); - if(!m->list) { - free(m->file); - free(m->host); - free(m); - return NULL; - } - } - return m; -} - -/** copy the master addresses from the task_probe lookups to the allow_notify - * list of masters */ -static void -probe_copy_masters_for_allow_notify(struct auth_xfer* xfr) -{ - struct auth_master* list = NULL, *last = NULL; - struct auth_master* p; - /* build up new list with copies */ - for(p = xfr->task_transfer->masters; p; p=p->next) { - struct auth_master* m = auth_master_copy(p); - if(!m) { - auth_free_masters(list); - /* failed because of malloc failure, use old list */ - return; - } - m->next = NULL; - if(last) last->next = m; - if(!list) list = m; - last = m; - } - /* success, replace list */ - auth_free_masters(xfr->allow_notify_list); - xfr->allow_notify_list = list; -} - -/** start the lookups for task_transfer */ -static void -xfr_transfer_start_lookups(struct auth_xfer* xfr) -{ - /* delete all the looked up addresses in the list */ - xfr->task_transfer->scan_addr = NULL; - xfr_masterlist_free_addrs(xfr->task_transfer->masters); - - /* start lookup at the first master */ - xfr->task_transfer->lookup_target = xfr->task_transfer->masters; - xfr->task_transfer->lookup_aaaa = 0; -} - -/** move to the next lookup of hostname for task_transfer */ -static void -xfr_transfer_move_to_next_lookup(struct auth_xfer* xfr, struct module_env* env) -{ - if(!xfr->task_transfer->lookup_target) - return; /* already at end of list */ - if(!xfr->task_transfer->lookup_aaaa && env->cfg->do_ip6) { - /* move to lookup AAAA */ - xfr->task_transfer->lookup_aaaa = 1; - return; - } - xfr->task_transfer->lookup_target = - xfr->task_transfer->lookup_target->next; - xfr->task_transfer->lookup_aaaa = 0; - if(!env->cfg->do_ip4 && xfr->task_transfer->lookup_target!=NULL) - xfr->task_transfer->lookup_aaaa = 1; -} - -/** start the lookups for task_probe */ -static void -xfr_probe_start_lookups(struct auth_xfer* xfr) -{ - /* delete all the looked up addresses in the list */ - xfr->task_probe->scan_addr = NULL; - xfr_masterlist_free_addrs(xfr->task_probe->masters); - - /* start lookup at the first master */ - xfr->task_probe->lookup_target = xfr->task_probe->masters; - xfr->task_probe->lookup_aaaa = 0; -} - -/** move to the next lookup of hostname for task_probe */ -static void -xfr_probe_move_to_next_lookup(struct auth_xfer* xfr, struct module_env* env) -{ - if(!xfr->task_probe->lookup_target) - return; /* already at end of list */ - if(!xfr->task_probe->lookup_aaaa && env->cfg->do_ip6) { - /* move to lookup AAAA */ - xfr->task_probe->lookup_aaaa = 1; - return; - } - xfr->task_probe->lookup_target = xfr->task_probe->lookup_target->next; - xfr->task_probe->lookup_aaaa = 0; - if(!env->cfg->do_ip4 && xfr->task_probe->lookup_target!=NULL) - xfr->task_probe->lookup_aaaa = 1; -} - -/** start the iteration of the task_transfer list of masters */ -static void -xfr_transfer_start_list(struct auth_xfer* xfr, struct auth_master* spec) -{ - if(spec) { - xfr->task_transfer->scan_specific = find_master_by_host( - xfr->task_transfer->masters, spec->host); - if(xfr->task_transfer->scan_specific) { - xfr->task_transfer->scan_target = NULL; - xfr->task_transfer->scan_addr = NULL; - if(xfr->task_transfer->scan_specific->list) - xfr->task_transfer->scan_addr = - xfr->task_transfer->scan_specific->list; - return; - } - } - /* no specific (notified) host to scan */ - xfr->task_transfer->scan_specific = NULL; - xfr->task_transfer->scan_addr = NULL; - /* pick up first scan target */ - xfr->task_transfer->scan_target = xfr->task_transfer->masters; - if(xfr->task_transfer->scan_target && xfr->task_transfer-> - scan_target->list) - xfr->task_transfer->scan_addr = - xfr->task_transfer->scan_target->list; -} - -/** start the iteration of the task_probe list of masters */ -static void -xfr_probe_start_list(struct auth_xfer* xfr, struct auth_master* spec) -{ - if(spec) { - xfr->task_probe->scan_specific = find_master_by_host( - xfr->task_probe->masters, spec->host); - if(xfr->task_probe->scan_specific) { - xfr->task_probe->scan_target = NULL; - xfr->task_probe->scan_addr = NULL; - if(xfr->task_probe->scan_specific->list) - xfr->task_probe->scan_addr = - xfr->task_probe->scan_specific->list; - return; - } - } - /* no specific (notified) host to scan */ - xfr->task_probe->scan_specific = NULL; - xfr->task_probe->scan_addr = NULL; - /* pick up first scan target */ - xfr->task_probe->scan_target = xfr->task_probe->masters; - if(xfr->task_probe->scan_target && xfr->task_probe->scan_target->list) - xfr->task_probe->scan_addr = - xfr->task_probe->scan_target->list; -} - -/** pick up the master that is being scanned right now, task_transfer */ -static struct auth_master* -xfr_transfer_current_master(struct auth_xfer* xfr) -{ - if(xfr->task_transfer->scan_specific) - return xfr->task_transfer->scan_specific; - return xfr->task_transfer->scan_target; -} - -/** pick up the master that is being scanned right now, task_probe */ -static struct auth_master* -xfr_probe_current_master(struct auth_xfer* xfr) -{ - if(xfr->task_probe->scan_specific) - return xfr->task_probe->scan_specific; - return xfr->task_probe->scan_target; -} - -/** true if at end of list, task_transfer */ -static int -xfr_transfer_end_of_list(struct auth_xfer* xfr) -{ - return !xfr->task_transfer->scan_specific && - !xfr->task_transfer->scan_target; -} - -/** true if at end of list, task_probe */ -static int -xfr_probe_end_of_list(struct auth_xfer* xfr) -{ - return !xfr->task_probe->scan_specific && !xfr->task_probe->scan_target; -} - -/** move to next master in list, task_transfer */ -static void -xfr_transfer_nextmaster(struct auth_xfer* xfr) -{ - if(!xfr->task_transfer->scan_specific && - !xfr->task_transfer->scan_target) - return; - if(xfr->task_transfer->scan_addr) { - xfr->task_transfer->scan_addr = - xfr->task_transfer->scan_addr->next; - if(xfr->task_transfer->scan_addr) - return; - } - if(xfr->task_transfer->scan_specific) { - xfr->task_transfer->scan_specific = NULL; - xfr->task_transfer->scan_target = xfr->task_transfer->masters; - if(xfr->task_transfer->scan_target && xfr->task_transfer-> - scan_target->list) - xfr->task_transfer->scan_addr = - xfr->task_transfer->scan_target->list; - return; - } - if(!xfr->task_transfer->scan_target) - return; - xfr->task_transfer->scan_target = xfr->task_transfer->scan_target->next; - if(xfr->task_transfer->scan_target && xfr->task_transfer-> - scan_target->list) - xfr->task_transfer->scan_addr = - xfr->task_transfer->scan_target->list; - return; -} - -/** move to next master in list, task_probe */ -static void -xfr_probe_nextmaster(struct auth_xfer* xfr) -{ - if(!xfr->task_probe->scan_specific && !xfr->task_probe->scan_target) - return; - if(xfr->task_probe->scan_addr) { - xfr->task_probe->scan_addr = xfr->task_probe->scan_addr->next; - if(xfr->task_probe->scan_addr) - return; - } - if(xfr->task_probe->scan_specific) { - xfr->task_probe->scan_specific = NULL; - xfr->task_probe->scan_target = xfr->task_probe->masters; - if(xfr->task_probe->scan_target && xfr->task_probe-> - scan_target->list) - xfr->task_probe->scan_addr = - xfr->task_probe->scan_target->list; - return; - } - if(!xfr->task_probe->scan_target) - return; - xfr->task_probe->scan_target = xfr->task_probe->scan_target->next; - if(xfr->task_probe->scan_target && xfr->task_probe-> - scan_target->list) - xfr->task_probe->scan_addr = - xfr->task_probe->scan_target->list; - return; -} - -/** create SOA probe packet for xfr */ -static void -xfr_create_soa_probe_packet(struct auth_xfer* xfr, sldns_buffer* buf, - uint16_t id) -{ - struct query_info qinfo; - - memset(&qinfo, 0, sizeof(qinfo)); - qinfo.qname = xfr->name; - qinfo.qname_len = xfr->namelen; - qinfo.qtype = LDNS_RR_TYPE_SOA; - qinfo.qclass = xfr->dclass; - qinfo_query_encode(buf, &qinfo); - sldns_buffer_write_u16_at(buf, 0, id); -} - -/** create IXFR/AXFR packet for xfr */ -static void -xfr_create_ixfr_packet(struct auth_xfer* xfr, sldns_buffer* buf, uint16_t id, - struct auth_master* master) -{ - struct query_info qinfo; - uint32_t serial; - int have_zone; - have_zone = xfr->have_zone; - serial = xfr->serial; - - memset(&qinfo, 0, sizeof(qinfo)); - qinfo.qname = xfr->name; - qinfo.qname_len = xfr->namelen; - xfr->task_transfer->got_xfr_serial = 0; - xfr->task_transfer->rr_scan_num = 0; - xfr->task_transfer->incoming_xfr_serial = 0; - xfr->task_transfer->on_ixfr_is_axfr = 0; - xfr->task_transfer->on_ixfr = 1; - qinfo.qtype = LDNS_RR_TYPE_IXFR; - if(!have_zone || xfr->task_transfer->ixfr_fail || !master->ixfr) { - qinfo.qtype = LDNS_RR_TYPE_AXFR; - xfr->task_transfer->ixfr_fail = 0; - xfr->task_transfer->on_ixfr = 0; - } - - qinfo.qclass = xfr->dclass; - qinfo_query_encode(buf, &qinfo); - sldns_buffer_write_u16_at(buf, 0, id); - - /* append serial for IXFR */ - if(qinfo.qtype == LDNS_RR_TYPE_IXFR) { - size_t end = sldns_buffer_limit(buf); - sldns_buffer_clear(buf); - sldns_buffer_set_position(buf, end); - /* auth section count 1 */ - sldns_buffer_write_u16_at(buf, LDNS_NSCOUNT_OFF, 1); - /* write SOA */ - sldns_buffer_write_u8(buf, 0xC0); /* compressed ptr to qname */ - sldns_buffer_write_u8(buf, 0x0C); - sldns_buffer_write_u16(buf, LDNS_RR_TYPE_SOA); - sldns_buffer_write_u16(buf, qinfo.qclass); - sldns_buffer_write_u32(buf, 0); /* ttl */ - sldns_buffer_write_u16(buf, 22); /* rdata length */ - sldns_buffer_write_u8(buf, 0); /* . */ - sldns_buffer_write_u8(buf, 0); /* . */ - sldns_buffer_write_u32(buf, serial); /* serial */ - sldns_buffer_write_u32(buf, 0); /* refresh */ - sldns_buffer_write_u32(buf, 0); /* retry */ - sldns_buffer_write_u32(buf, 0); /* expire */ - sldns_buffer_write_u32(buf, 0); /* minimum */ - sldns_buffer_flip(buf); - } -} - -/** check if returned packet is OK */ -static int -check_packet_ok(sldns_buffer* pkt, uint16_t qtype, struct auth_xfer* xfr, - uint32_t* serial) -{ - /* parse to see if packet worked, valid reply */ - - /* check serial number of SOA */ - if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) - return 0; - - /* check ID */ - if(LDNS_ID_WIRE(sldns_buffer_begin(pkt)) != xfr->task_probe->id) - return 0; - - /* check flag bits and rcode */ - if(!LDNS_QR_WIRE(sldns_buffer_begin(pkt))) - return 0; - if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) - return 0; - if(LDNS_RCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_RCODE_NOERROR) - return 0; - - /* check qname */ - if(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) != 1) - return 0; - sldns_buffer_skip(pkt, LDNS_HEADER_SIZE); - if(sldns_buffer_remaining(pkt) < xfr->namelen) - return 0; - if(query_dname_compare(sldns_buffer_current(pkt), xfr->name) != 0) - return 0; - sldns_buffer_skip(pkt, (ssize_t)xfr->namelen); - - /* check qtype, qclass */ - if(sldns_buffer_remaining(pkt) < 4) - return 0; - if(sldns_buffer_read_u16(pkt) != qtype) - return 0; - if(sldns_buffer_read_u16(pkt) != xfr->dclass) - return 0; - - if(serial) { - uint16_t rdlen; - /* read serial number, from answer section SOA */ - if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0) - return 0; - /* read from first record SOA record */ - if(sldns_buffer_remaining(pkt) < 1) - return 0; - if(dname_pkt_compare(pkt, sldns_buffer_current(pkt), - xfr->name) != 0) - return 0; - if(!pkt_dname_len(pkt)) - return 0; - /* type, class, ttl, rdatalen */ - if(sldns_buffer_remaining(pkt) < 4+4+2) - return 0; - if(sldns_buffer_read_u16(pkt) != qtype) - return 0; - if(sldns_buffer_read_u16(pkt) != xfr->dclass) - return 0; - sldns_buffer_skip(pkt, 4); /* ttl */ - rdlen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdlen) - return 0; - if(sldns_buffer_remaining(pkt) < 1) - return 0; - if(!pkt_dname_len(pkt)) /* soa name */ - return 0; - if(sldns_buffer_remaining(pkt) < 1) - return 0; - if(!pkt_dname_len(pkt)) /* soa name */ - return 0; - if(sldns_buffer_remaining(pkt) < 20) - return 0; - *serial = sldns_buffer_read_u32(pkt); - } - return 1; -} - -/** read one line from chunks into buffer at current position */ -static int -chunkline_get_line(struct auth_chunk** chunk, size_t* chunk_pos, - sldns_buffer* buf) -{ - int readsome = 0; - while(*chunk) { - /* more text in this chunk? */ - if(*chunk_pos < (*chunk)->len) { - readsome = 1; - while(*chunk_pos < (*chunk)->len) { - char c = (char)((*chunk)->data[*chunk_pos]); - (*chunk_pos)++; - if(sldns_buffer_remaining(buf) < 2) { - /* buffer too short */ - verbose(VERB_ALGO, "http chunkline, " - "line too long"); - return 0; - } - sldns_buffer_write_u8(buf, (uint8_t)c); - if(c == '\n') { - /* we are done */ - return 1; - } - } - } - /* move to next chunk */ - *chunk = (*chunk)->next; - *chunk_pos = 0; - } - /* no more text */ - if(readsome) return 1; - return 0; -} - -/** count number of open and closed parenthesis in a chunkline */ -static int -chunkline_count_parens(sldns_buffer* buf, size_t start) -{ - size_t end = sldns_buffer_position(buf); - size_t i; - int count = 0; - int squote = 0, dquote = 0; - for(i=start; i 0) { - chunkline_remove_trailcomment(buf, pos); - pos = sldns_buffer_position(buf); - if(!chunkline_get_line(chunk, chunk_pos, buf)) { - if(sldns_buffer_position(buf) < sldns_buffer_limit(buf)) - sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf), 0); - else sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf)-1, 0); - sldns_buffer_flip(buf); - return 0; - } - parens += chunkline_count_parens(buf, pos); - } - - if(sldns_buffer_remaining(buf) < 1) { - verbose(VERB_ALGO, "http chunkline: " - "line too long"); - return 0; - } - sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf), 0); - sldns_buffer_flip(buf); - return 1; -} - -/** process $ORIGIN for http, 0 nothing, 1 done, 2 error */ -static int -http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate) -{ - char* line = (char*)sldns_buffer_begin(buf); - if(strncmp(line, "$ORIGIN", 7) == 0 && - isspace((unsigned char)line[7])) { - int s; - pstate->origin_len = sizeof(pstate->origin); - s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), - pstate->origin, &pstate->origin_len); - if(s) { - pstate->origin_len = 0; - return 2; - } - return 1; - } - return 0; -} - -/** process $TTL for http, 0 nothing, 1 done, 2 error */ -static int -http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate) -{ - char* line = (char*)sldns_buffer_begin(buf); - if(strncmp(line, "$TTL", 4) == 0 && - isspace((unsigned char)line[4])) { - const char* end = NULL; - int overflow = 0; - pstate->default_ttl = sldns_str2period( - sldns_strip_ws(line+5), &end, &overflow); - if(overflow) { - return 2; - } - return 1; - } - return 0; -} - -/** find noncomment RR line in chunks, collates lines if ( ) format */ -static int -chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos, - sldns_buffer* buf, struct sldns_file_parse_state* pstate) -{ - int ret; - while(chunkline_get_line_collated(chunk, chunk_pos, buf)) { - if(chunkline_is_comment_line_or_empty(buf)) { - /* a comment, go to next line */ - continue; - } - if((ret=http_parse_origin(buf, pstate))!=0) { - if(ret == 2) - return 0; - continue; /* $ORIGIN has been handled */ - } - if((ret=http_parse_ttl(buf, pstate))!=0) { - if(ret == 2) - return 0; - continue; /* $TTL has been handled */ - } - return 1; - } - /* no noncomments, fail */ - return 0; -} - -/** check syntax of chunklist zonefile, parse first RR, return false on - * failure and return a string in the scratch buffer (first RR string) - * on failure. */ -static int -http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t rr_len, dname_len = 0; - struct sldns_file_parse_state pstate; - struct auth_chunk* chunk; - size_t chunk_pos; - int e; - memset(&pstate, 0, sizeof(pstate)); - pstate.default_ttl = 3600; - if(xfr->namelen < sizeof(pstate.origin)) { - pstate.origin_len = xfr->namelen; - memmove(pstate.origin, xfr->name, xfr->namelen); - } - chunk = xfr->task_transfer->chunks_first; - chunk_pos = 0; - if(!chunkline_non_comment_RR(&chunk, &chunk_pos, buf, &pstate)) { - return 0; - } - rr_len = sizeof(rr); - e=sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr, &rr_len, - &dname_len, pstate.default_ttl, - pstate.origin_len?pstate.origin:NULL, pstate.origin_len, - pstate.prev_rr_len?pstate.prev_rr:NULL, pstate.prev_rr_len); - if(e != 0) { - log_err("parse failure on first RR[%d]: %s", - LDNS_WIREPARSE_OFFSET(e), - sldns_get_errorstr_parse(LDNS_WIREPARSE_ERROR(e))); - return 0; - } - /* check that class is correct */ - if(sldns_wirerr_get_class(rr, rr_len, dname_len) != xfr->dclass) { - log_err("parse failure: first record in downloaded zonefile " - "from wrong RR class"); - return 0; - } - return 1; -} - -/** sum sizes of chunklist */ -static size_t -chunklist_sum(struct auth_chunk* list) -{ - struct auth_chunk* p; - size_t s = 0; - for(p=list; p; p=p->next) { - s += p->len; - } - return s; -} - -/** remove newlines from collated line */ -static void -chunkline_newline_removal(sldns_buffer* buf) -{ - size_t i, end=sldns_buffer_limit(buf); - for(i=0; idefault_ttl, - pstate->origin_len?pstate->origin:NULL, pstate->origin_len, - pstate->prev_rr_len?pstate->prev_rr:NULL, pstate->prev_rr_len); - if(e != 0) { - log_err("%s/%s parse failure RR[%d]: %s in '%s'", - xfr->task_transfer->master->host, - xfr->task_transfer->master->file, - LDNS_WIREPARSE_OFFSET(e), - sldns_get_errorstr_parse(LDNS_WIREPARSE_ERROR(e)), - line); - return 0; - } - if(rr_len == 0) - return 1; /* empty line or so */ - - /* set prev */ - if(dname_len < sizeof(pstate->prev_rr)) { - memmove(pstate->prev_rr, rr, dname_len); - pstate->prev_rr_len = dname_len; - } - - return az_insert_rr(z, rr, rr_len, dname_len, NULL); -} - -/** RR list iterator, returns RRs from answer section one by one from the - * dns packets in the chunklist */ -static void -chunk_rrlist_start(struct auth_xfer* xfr, struct auth_chunk** rr_chunk, - int* rr_num, size_t* rr_pos) -{ - *rr_chunk = xfr->task_transfer->chunks_first; - *rr_num = 0; - *rr_pos = 0; -} - -/** RR list iterator, see if we are at the end of the list */ -static int -chunk_rrlist_end(struct auth_chunk* rr_chunk, int rr_num) -{ - while(rr_chunk) { - if(rr_chunk->len < LDNS_HEADER_SIZE) - return 1; - if(rr_num < (int)LDNS_ANCOUNT(rr_chunk->data)) - return 0; - /* no more RRs in this chunk */ - /* continue with next chunk, see if it has RRs */ - rr_chunk = rr_chunk->next; - rr_num = 0; - } - return 1; -} - -/** RR list iterator, move to next RR */ -static void -chunk_rrlist_gonext(struct auth_chunk** rr_chunk, int* rr_num, - size_t* rr_pos, size_t rr_nextpos) -{ - /* already at end of chunks? */ - if(!*rr_chunk) - return; - /* move within this chunk */ - if((*rr_chunk)->len >= LDNS_HEADER_SIZE && - (*rr_num)+1 < (int)LDNS_ANCOUNT((*rr_chunk)->data)) { - (*rr_num) += 1; - *rr_pos = rr_nextpos; - return; - } - /* no more RRs in this chunk */ - /* continue with next chunk, see if it has RRs */ - if(*rr_chunk) - *rr_chunk = (*rr_chunk)->next; - while(*rr_chunk) { - *rr_num = 0; - *rr_pos = 0; - if((*rr_chunk)->len >= LDNS_HEADER_SIZE && - LDNS_ANCOUNT((*rr_chunk)->data) > 0) { - return; - } - *rr_chunk = (*rr_chunk)->next; - } -} - -/** RR iterator, get current RR information, false on parse error */ -static int -chunk_rrlist_get_current(struct auth_chunk* rr_chunk, int rr_num, - size_t rr_pos, uint8_t** rr_dname, uint16_t* rr_type, - uint16_t* rr_class, uint32_t* rr_ttl, uint16_t* rr_rdlen, - uint8_t** rr_rdata, size_t* rr_nextpos) -{ - sldns_buffer pkt; - /* integrity checks on position */ - if(!rr_chunk) return 0; - if(rr_chunk->len < LDNS_HEADER_SIZE) return 0; - if(rr_num >= (int)LDNS_ANCOUNT(rr_chunk->data)) return 0; - if(rr_pos >= rr_chunk->len) return 0; - - /* fetch rr information */ - sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len); - if(rr_pos == 0) { - size_t i; - /* skip question section */ - sldns_buffer_set_position(&pkt, LDNS_HEADER_SIZE); - for(i=0; idata); i++) { - if(pkt_dname_len(&pkt) == 0) return 0; - if(sldns_buffer_remaining(&pkt) < 4) return 0; - sldns_buffer_skip(&pkt, 4); /* type and class */ - } - } else { - sldns_buffer_set_position(&pkt, rr_pos); - } - *rr_dname = sldns_buffer_current(&pkt); - if(pkt_dname_len(&pkt) == 0) return 0; - if(sldns_buffer_remaining(&pkt) < 10) return 0; - *rr_type = sldns_buffer_read_u16(&pkt); - *rr_class = sldns_buffer_read_u16(&pkt); - *rr_ttl = sldns_buffer_read_u32(&pkt); - *rr_rdlen = sldns_buffer_read_u16(&pkt); - if(sldns_buffer_remaining(&pkt) < (*rr_rdlen)) return 0; - *rr_rdata = sldns_buffer_current(&pkt); - sldns_buffer_skip(&pkt, (ssize_t)(*rr_rdlen)); - *rr_nextpos = sldns_buffer_position(&pkt); - return 1; -} - -/** print log message where we are in parsing the zone transfer */ -static void -log_rrlist_position(const char* label, struct auth_chunk* rr_chunk, - uint8_t* rr_dname, uint16_t rr_type, size_t rr_counter) -{ - sldns_buffer pkt; - size_t dlen; - uint8_t buf[256]; - char str[256]; - char typestr[32]; - sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len); - sldns_buffer_set_position(&pkt, (size_t)(rr_dname - - sldns_buffer_begin(&pkt))); - if((dlen=pkt_dname_len(&pkt)) == 0) return; - if(dlen >= sizeof(buf)) return; - dname_pkt_copy(&pkt, buf, rr_dname); - dname_str(buf, str); - (void)sldns_wire2str_type_buf(rr_type, typestr, sizeof(typestr)); - verbose(VERB_ALGO, "%s at[%d] %s %s", label, (int)rr_counter, - str, typestr); -} - -/** check that start serial is OK for ixfr. we are at rr_counter == 0, - * and we are going to check rr_counter == 1 (has to be type SOA) serial */ -static int -ixfr_start_serial(struct auth_chunk* rr_chunk, int rr_num, size_t rr_pos, - uint8_t* rr_dname, uint16_t rr_type, uint16_t rr_class, - uint32_t rr_ttl, uint16_t rr_rdlen, uint8_t* rr_rdata, - size_t rr_nextpos, uint32_t transfer_serial, uint32_t xfr_serial) -{ - uint32_t startserial; - /* move forward on RR */ - chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos); - if(chunk_rrlist_end(rr_chunk, rr_num)) { - /* no second SOA */ - verbose(VERB_OPS, "IXFR has no second SOA record"); - return 0; - } - if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos, - &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen, - &rr_rdata, &rr_nextpos)) { - verbose(VERB_OPS, "IXFR cannot parse second SOA record"); - /* failed to parse RR */ - return 0; - } - if(rr_type != LDNS_RR_TYPE_SOA) { - verbose(VERB_OPS, "IXFR second record is not type SOA"); - return 0; - } - if(rr_rdlen < 22) { - verbose(VERB_OPS, "IXFR, second SOA has short rdlength"); - return 0; /* bad SOA rdlen */ - } - startserial = sldns_read_uint32(rr_rdata+rr_rdlen-20); - if(startserial == transfer_serial) { - /* empty AXFR, not an IXFR */ - verbose(VERB_OPS, "IXFR second serial same as first"); - return 0; - } - if(startserial != xfr_serial) { - /* wrong start serial, it does not match the serial in - * memory */ - verbose(VERB_OPS, "IXFR is from serial %u to %u but %u " - "in memory, rejecting the zone transfer", - (unsigned)startserial, (unsigned)transfer_serial, - (unsigned)xfr_serial); - return 0; - } - /* everything OK in second SOA serial */ - return 1; -} - -/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */ -static int -apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z, - struct sldns_buffer* scratch_buffer) -{ - struct auth_chunk* rr_chunk; - int rr_num; - size_t rr_pos; - uint8_t* rr_dname, *rr_rdata; - uint16_t rr_type, rr_class, rr_rdlen; - uint32_t rr_ttl; - size_t rr_nextpos; - int have_transfer_serial = 0; - uint32_t transfer_serial = 0; - size_t rr_counter = 0; - int delmode = 0; - int softfail = 0; - - /* start RR iterator over chunklist of packets */ - chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos); - while(!chunk_rrlist_end(rr_chunk, rr_num)) { - if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos, - &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen, - &rr_rdata, &rr_nextpos)) { - /* failed to parse RR */ - return 0; - } - if(verbosity>=7) log_rrlist_position("apply ixfr", - rr_chunk, rr_dname, rr_type, rr_counter); - /* twiddle add/del mode and check for start and end */ - if(rr_counter == 0 && rr_type != LDNS_RR_TYPE_SOA) - return 0; - if(rr_counter == 1 && rr_type != LDNS_RR_TYPE_SOA) { - /* this is an AXFR returned from the IXFR master */ - /* but that should already have been detected, by - * on_ixfr_is_axfr */ - return 0; - } - if(rr_type == LDNS_RR_TYPE_SOA) { - uint32_t serial; - if(rr_rdlen < 22) return 0; /* bad SOA rdlen */ - serial = sldns_read_uint32(rr_rdata+rr_rdlen-20); - if(have_transfer_serial == 0) { - have_transfer_serial = 1; - transfer_serial = serial; - delmode = 1; /* gets negated below */ - /* check second RR before going any further */ - if(!ixfr_start_serial(rr_chunk, rr_num, rr_pos, - rr_dname, rr_type, rr_class, rr_ttl, - rr_rdlen, rr_rdata, rr_nextpos, - transfer_serial, xfr->serial)) { - return 0; - } - } else if(transfer_serial == serial) { - have_transfer_serial++; - if(rr_counter == 1) { - /* empty AXFR, with SOA; SOA; */ - /* should have been detected by - * on_ixfr_is_axfr */ - return 0; - } - if(have_transfer_serial == 3) { - /* see serial three times for end */ - /* eg. IXFR: - * SOA 3 start - * SOA 1 second RR, followed by del - * SOA 2 followed by add - * SOA 2 followed by del - * SOA 3 followed by add - * SOA 3 end */ - /* ended by SOA record */ - xfr->serial = transfer_serial; - break; - } - } - /* twiddle add/del mode */ - /* switch from delete part to add part and back again - * just before the soa, it gets deleted and added too - * this means we switch to delete mode for the final - * SOA(so skip that one) */ - delmode = !delmode; - } - /* process this RR */ - /* if the RR is deleted twice or added twice, then we - * softfail, and continue with the rest of the IXFR, so - * that we serve something fairly nice during the refetch */ - if(verbosity>=7) log_rrlist_position((delmode?"del":"add"), - rr_chunk, rr_dname, rr_type, rr_counter); - if(delmode) { - /* delete this RR */ - int nonexist = 0; - if(!az_remove_rr_decompress(z, rr_chunk->data, - rr_chunk->len, scratch_buffer, rr_dname, - rr_type, rr_class, rr_ttl, rr_rdata, rr_rdlen, - &nonexist)) { - /* failed, malloc error or so */ - return 0; - } - if(nonexist) { - /* it was removal of a nonexisting RR */ - if(verbosity>=4) log_rrlist_position( - "IXFR error nonexistent RR", - rr_chunk, rr_dname, rr_type, rr_counter); - softfail = 1; - } - } else if(rr_counter != 0) { - /* skip first SOA RR for addition, it is added in - * the addition part near the end of the ixfr, when - * that serial is seen the second time. */ - int duplicate = 0; - /* add this RR */ - if(!az_insert_rr_decompress(z, rr_chunk->data, - rr_chunk->len, scratch_buffer, rr_dname, - rr_type, rr_class, rr_ttl, rr_rdata, rr_rdlen, - &duplicate)) { - /* failed, malloc error or so */ - return 0; - } - if(duplicate) { - /* it was a duplicate */ - if(verbosity>=4) log_rrlist_position( - "IXFR error duplicate RR", - rr_chunk, rr_dname, rr_type, rr_counter); - softfail = 1; - } - } - - rr_counter++; - chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos); - } - if(softfail) { - verbose(VERB_ALGO, "IXFR did not apply cleanly, fetching full zone"); - return 0; - } - return 1; -} - -/** apply AXFR to zone in memory. z is locked. false on failure(mallocfail) */ -static int -apply_axfr(struct auth_xfer* xfr, struct auth_zone* z, - struct sldns_buffer* scratch_buffer) -{ - struct auth_chunk* rr_chunk; - int rr_num; - size_t rr_pos; - uint8_t* rr_dname, *rr_rdata; - uint16_t rr_type, rr_class, rr_rdlen; - uint32_t rr_ttl; - uint32_t serial = 0; - size_t rr_nextpos; - size_t rr_counter = 0; - int have_end_soa = 0; - - /* clear the data tree */ - traverse_postorder(&z->data, auth_data_del, NULL); - rbtree_init(&z->data, &auth_data_cmp); - /* clear the RPZ policies */ - if(z->rpz) - rpz_clear(z->rpz); - - xfr->have_zone = 0; - xfr->serial = 0; - - /* insert all RRs in to the zone */ - /* insert the SOA only once, skip the last one */ - /* start RR iterator over chunklist of packets */ - chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos); - while(!chunk_rrlist_end(rr_chunk, rr_num)) { - if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos, - &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen, - &rr_rdata, &rr_nextpos)) { - /* failed to parse RR */ - return 0; - } - if(verbosity>=7) log_rrlist_position("apply_axfr", - rr_chunk, rr_dname, rr_type, rr_counter); - if(rr_type == LDNS_RR_TYPE_SOA) { - if(rr_counter != 0) { - /* end of the axfr */ - have_end_soa = 1; - break; - } - if(rr_rdlen < 22) return 0; /* bad SOA rdlen */ - serial = sldns_read_uint32(rr_rdata+rr_rdlen-20); - } - - /* add this RR */ - if(!az_insert_rr_decompress(z, rr_chunk->data, rr_chunk->len, - scratch_buffer, rr_dname, rr_type, rr_class, rr_ttl, - rr_rdata, rr_rdlen, NULL)) { - /* failed, malloc error or so */ - return 0; - } - - rr_counter++; - chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos); - } - if(!have_end_soa) { - log_err("no end SOA record for AXFR"); - return 0; - } - - xfr->serial = serial; - xfr->have_zone = 1; - return 1; -} - -/** apply HTTP to zone in memory. z is locked. false on failure(mallocfail) */ -static int -apply_http(struct auth_xfer* xfr, struct auth_zone* z, - struct sldns_buffer* scratch_buffer) -{ - /* parse data in chunks */ - /* parse RR's and read into memory. ignore $INCLUDE from the - * downloaded file*/ - struct sldns_file_parse_state pstate; - struct auth_chunk* chunk; - size_t chunk_pos; - int ret; - memset(&pstate, 0, sizeof(pstate)); - pstate.default_ttl = 3600; - if(xfr->namelen < sizeof(pstate.origin)) { - pstate.origin_len = xfr->namelen; - memmove(pstate.origin, xfr->name, xfr->namelen); - } - - if(verbosity >= VERB_ALGO) - verbose(VERB_ALGO, "http download %s of size %d", - xfr->task_transfer->master->file, - (int)chunklist_sum(xfr->task_transfer->chunks_first)); - if(xfr->task_transfer->chunks_first && verbosity >= VERB_ALGO) { - char preview[1024]; - if(xfr->task_transfer->chunks_first->len+1 > sizeof(preview)) { - memmove(preview, xfr->task_transfer->chunks_first->data, - sizeof(preview)-1); - preview[sizeof(preview)-1]=0; - } else { - memmove(preview, xfr->task_transfer->chunks_first->data, - xfr->task_transfer->chunks_first->len); - preview[xfr->task_transfer->chunks_first->len]=0; - } - log_info("auth zone http downloaded content preview: %s", - preview); - } - - /* perhaps a little syntax check before we try to apply the data? */ - if(!http_zonefile_syntax_check(xfr, scratch_buffer)) { - log_err("http download %s/%s does not contain a zonefile, " - "but got '%s'", xfr->task_transfer->master->host, - xfr->task_transfer->master->file, - sldns_buffer_begin(scratch_buffer)); - return 0; - } - - /* clear the data tree */ - traverse_postorder(&z->data, auth_data_del, NULL); - rbtree_init(&z->data, &auth_data_cmp); - /* clear the RPZ policies */ - if(z->rpz) - rpz_clear(z->rpz); - - xfr->have_zone = 0; - xfr->serial = 0; - - chunk = xfr->task_transfer->chunks_first; - chunk_pos = 0; - pstate.lineno = 0; - while(chunkline_get_line_collated(&chunk, &chunk_pos, scratch_buffer)) { - /* process this line */ - pstate.lineno++; - chunkline_newline_removal(scratch_buffer); - if(chunkline_is_comment_line_or_empty(scratch_buffer)) { - continue; - } - /* parse line and add RR */ - if((ret=http_parse_origin(scratch_buffer, &pstate))!=0) { - if(ret == 2) { - verbose(VERB_ALGO, "error parsing ORIGIN on line [%s:%d] %s", - xfr->task_transfer->master->file, - pstate.lineno, - sldns_buffer_begin(scratch_buffer)); - return 0; - } - continue; /* $ORIGIN has been handled */ - } - if((ret=http_parse_ttl(scratch_buffer, &pstate))!=0) { - if(ret == 2) { - verbose(VERB_ALGO, "error parsing TTL on line [%s:%d] %s", - xfr->task_transfer->master->file, - pstate.lineno, - sldns_buffer_begin(scratch_buffer)); - return 0; - } - continue; /* $TTL has been handled */ - } - if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) { - verbose(VERB_ALGO, "error parsing line [%s:%d] %s", - xfr->task_transfer->master->file, - pstate.lineno, - sldns_buffer_begin(scratch_buffer)); - return 0; - } - } - return 1; -} - -/** write http chunks to zonefile to create downloaded file */ -static int -auth_zone_write_chunks(struct auth_xfer* xfr, const char* fname) -{ - FILE* out; - struct auth_chunk* p; - out = fopen(fname, "w"); - if(!out) { - log_err("could not open %s: %s", fname, strerror(errno)); - return 0; - } - for(p = xfr->task_transfer->chunks_first; p ; p = p->next) { - if(!write_out(out, (char*)p->data, p->len)) { - log_err("could not write http download to %s", fname); - fclose(out); - return 0; - } - } - fclose(out); - return 1; -} - -/** write to zonefile after zone has been updated */ -static void -xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env) -{ - struct config_file* cfg = env->cfg; - struct auth_zone* z; - char tmpfile[1024]; - char* zfilename; - lock_basic_unlock(&xfr->lock); - - /* get lock again, so it is a readlock and concurrently queries - * can be answered */ - lock_rw_rdlock(&env->auth_zones->lock); - z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, - xfr->dclass); - if(!z) { - lock_rw_unlock(&env->auth_zones->lock); - /* the zone is gone, ignore xfr results */ - lock_basic_lock(&xfr->lock); - return; - } - lock_rw_rdlock(&z->lock); - lock_basic_lock(&xfr->lock); - lock_rw_unlock(&env->auth_zones->lock); - - if(z->zonefile == NULL || z->zonefile[0] == 0) { - lock_rw_unlock(&z->lock); - /* no write needed, no zonefile set */ - return; - } - zfilename = z->zonefile; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(zfilename, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - zfilename += strlen(cfg->chrootdir); - if(verbosity >= VERB_ALGO) { - char nm[255+1]; - dname_str(z->name, nm); - verbose(VERB_ALGO, "write zonefile %s for %s", zfilename, nm); - } - - /* write to tempfile first */ - if((size_t)strlen(zfilename) + 16 > sizeof(tmpfile)) { - verbose(VERB_ALGO, "tmpfilename too long, cannot update " - " zonefile %s", zfilename); - lock_rw_unlock(&z->lock); - return; - } - snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", zfilename, - (unsigned)getpid()); - if(xfr->task_transfer->master->http) { - /* use the stored chunk list to write them */ - if(!auth_zone_write_chunks(xfr, tmpfile)) { - unlink(tmpfile); - lock_rw_unlock(&z->lock); - return; - } - } else if(!auth_zone_write_file(z, tmpfile)) { - unlink(tmpfile); - lock_rw_unlock(&z->lock); - return; - } -#ifdef UB_ON_WINDOWS - (void)unlink(zfilename); /* windows does not replace file with rename() */ -#endif - if(rename(tmpfile, zfilename) < 0) { - log_err("could not rename(%s, %s): %s", tmpfile, zfilename, - strerror(errno)); - unlink(tmpfile); - lock_rw_unlock(&z->lock); - return; - } - lock_rw_unlock(&z->lock); -} - -/** reacquire locks and structures. Starts with no locks, ends - * with xfr and z locks, if fail, no z lock */ -static int xfr_process_reacquire_locks(struct auth_xfer* xfr, - struct module_env* env, struct auth_zone** z) -{ - /* release xfr lock, then, while holding az->lock grab both - * z->lock and xfr->lock */ - lock_rw_rdlock(&env->auth_zones->lock); - *z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen, - xfr->dclass); - if(!*z) { - lock_rw_unlock(&env->auth_zones->lock); - lock_basic_lock(&xfr->lock); - *z = NULL; - return 0; - } - lock_rw_wrlock(&(*z)->lock); - lock_basic_lock(&xfr->lock); - lock_rw_unlock(&env->auth_zones->lock); - return 1; -} - -/** process chunk list and update zone in memory, - * return false if it did not work */ -static int -xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env, - int* ixfr_fail) -{ - struct auth_zone* z; - - /* obtain locks and structures */ - lock_basic_unlock(&xfr->lock); - if(!xfr_process_reacquire_locks(xfr, env, &z)) { - /* the zone is gone, ignore xfr results */ - return 0; - } - /* holding xfr and z locks */ - - /* apply data */ - if(xfr->task_transfer->master->http) { - if(!apply_http(xfr, z, env->scratch_buffer)) { - lock_rw_unlock(&z->lock); - verbose(VERB_ALGO, "http from %s: could not store data", - xfr->task_transfer->master->host); - return 0; - } - } else if(xfr->task_transfer->on_ixfr && - !xfr->task_transfer->on_ixfr_is_axfr) { - if(!apply_ixfr(xfr, z, env->scratch_buffer)) { - lock_rw_unlock(&z->lock); - verbose(VERB_ALGO, "xfr from %s: could not store IXFR" - " data", xfr->task_transfer->master->host); - *ixfr_fail = 1; - return 0; - } - } else { - if(!apply_axfr(xfr, z, env->scratch_buffer)) { - lock_rw_unlock(&z->lock); - verbose(VERB_ALGO, "xfr from %s: could not store AXFR" - " data", xfr->task_transfer->master->host); - return 0; - } - } - xfr->zone_expired = 0; - z->zone_expired = 0; - if(!xfr_find_soa(z, xfr)) { - lock_rw_unlock(&z->lock); - verbose(VERB_ALGO, "xfr from %s: no SOA in zone after update" - " (or malformed RR)", xfr->task_transfer->master->host); - return 0; - } - - /* release xfr lock while verifying zonemd because it may have - * to spawn lookups in the state machines */ - lock_basic_unlock(&xfr->lock); - /* holding z lock */ - auth_zone_verify_zonemd(z, env, &env->mesh->mods, NULL, 0, 0); - if(z->zone_expired) { - char zname[256]; - /* ZONEMD must have failed */ - /* reacquire locks, so we hold xfr lock on exit of routine, - * and both xfr and z again after releasing xfr for potential - * state machine mesh callbacks */ - lock_rw_unlock(&z->lock); - if(!xfr_process_reacquire_locks(xfr, env, &z)) - return 0; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "xfr from %s: ZONEMD failed for %s, transfer is failed", xfr->task_transfer->master->host, zname); - xfr->zone_expired = 1; - lock_rw_unlock(&z->lock); - return 0; - } - /* reacquire locks, so we hold xfr lock on exit of routine, - * and both xfr and z again after releasing xfr for potential - * state machine mesh callbacks */ - lock_rw_unlock(&z->lock); - if(!xfr_process_reacquire_locks(xfr, env, &z)) - return 0; - /* holding xfr and z locks */ - - if(xfr->have_zone) - xfr->lease_time = *env->now; - - if(z->rpz) - rpz_finish_config(z->rpz); - - /* unlock */ - lock_rw_unlock(&z->lock); - - if(verbosity >= VERB_QUERY && xfr->have_zone) { - char zname[256]; - dname_str(xfr->name, zname); - verbose(VERB_QUERY, "auth zone %s updated to serial %u", zname, - (unsigned)xfr->serial); - } - /* see if we need to write to a zonefile */ - xfr_write_after_update(xfr, env); - return 1; -} - -/** disown task_transfer. caller must hold xfr.lock */ -static void -xfr_transfer_disown(struct auth_xfer* xfr) -{ - /* remove timer (from this worker's event base) */ - comm_timer_delete(xfr->task_transfer->timer); - xfr->task_transfer->timer = NULL; - /* remove the commpoint */ - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - /* we don't own this item anymore */ - xfr->task_transfer->worker = NULL; - xfr->task_transfer->env = NULL; -} - -/** lookup a host name for its addresses, if needed */ -static int -xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env) -{ - struct sockaddr_storage addr; - socklen_t addrlen = 0; - struct auth_master* master = xfr->task_transfer->lookup_target; - struct query_info qinfo; - uint16_t qflags = BIT_RD; - uint8_t dname[LDNS_MAX_DOMAINLEN+1]; - struct edns_data edns; - sldns_buffer* buf = env->scratch_buffer; - if(!master) return 0; - if(extstrtoaddr(master->host, &addr, &addrlen, UNBOUND_DNS_PORT)) { - /* not needed, host is in IP addr format */ - return 0; - } - if(master->allow_notify) - return 0; /* allow-notifies are not transferred from, no - lookup is needed */ - - /* use mesh_new_callback to probe for non-addr hosts, - * and then wait for them to be looked up (in cache, or query) */ - qinfo.qname_len = sizeof(dname); - if(sldns_str2wire_dname_buf(master->host, dname, &qinfo.qname_len) - != 0) { - log_err("cannot parse host name of master %s", master->host); - return 0; - } - qinfo.qname = dname; - qinfo.qclass = xfr->dclass; - qinfo.qtype = LDNS_RR_TYPE_A; - if(xfr->task_transfer->lookup_aaaa) - qinfo.qtype = LDNS_RR_TYPE_AAAA; - qinfo.local_alias = NULL; - if(verbosity >= VERB_ALGO) { - char buf1[512]; - char buf2[LDNS_MAX_DOMAINLEN+1]; - dname_str(xfr->name, buf2); - snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup" - " for task_transfer", buf2); - log_query_info(VERB_ALGO, buf1, &qinfo); - } - edns.edns_present = 1; - edns.ext_rcode = 0; - edns.edns_version = 0; - edns.bits = EDNS_DO; - edns.opt_list_in = NULL; - edns.opt_list_out = NULL; - edns.opt_list_inplace_cb_out = NULL; - edns.padding_block_size = 0; - edns.cookie_present = 0; - edns.cookie_valid = 0; - if(sldns_buffer_capacity(buf) < 65535) - edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); - else edns.udp_size = 65535; - - /* unlock xfr during mesh_new_callback() because the callback can be - * called straight away */ - lock_basic_unlock(&xfr->lock); - if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_xfer_transfer_lookup_callback, xfr, 0)) { - lock_basic_lock(&xfr->lock); - log_err("out of memory lookup up master %s", master->host); - return 0; - } - lock_basic_lock(&xfr->lock); - return 1; -} - -/** initiate TCP to the target and fetch zone. - * returns true if that was successfully started, and timeout setup. */ -static int -xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env) -{ - struct sockaddr_storage addr; - socklen_t addrlen = 0; - struct auth_master* master = xfr->task_transfer->master; - char *auth_name = NULL; - struct timeval t; - int timeout; - if(!master) return 0; - if(master->allow_notify) return 0; /* only for notify */ - - /* get master addr */ - if(xfr->task_transfer->scan_addr) { - addrlen = xfr->task_transfer->scan_addr->addrlen; - memmove(&addr, &xfr->task_transfer->scan_addr->addr, addrlen); - } else { - if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) { - /* the ones that are not in addr format are supposed - * to be looked up. The lookup has failed however, - * so skip them */ - char zname[255+1]; - dname_str(xfr->name, zname); - log_err("%s: failed lookup, cannot transfer from master %s", - zname, master->host); - return 0; - } - } - - /* remove previous TCP connection (if any) */ - if(xfr->task_transfer->cp) { - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - } - if(!xfr->task_transfer->timer) { - xfr->task_transfer->timer = comm_timer_create(env->worker_base, - auth_xfer_transfer_timer_callback, xfr); - if(!xfr->task_transfer->timer) { - log_err("malloc failure"); - return 0; - } - } - timeout = AUTH_TRANSFER_TIMEOUT; -#ifndef S_SPLINT_S - t.tv_sec = timeout/1000; - t.tv_usec = (timeout%1000)*1000; -#endif - - if(master->http) { - /* perform http fetch */ - /* store http port number into sockaddr, - * unless someone used unbound's host@port notation */ - xfr->task_transfer->on_ixfr = 0; - if(strchr(master->host, '@') == NULL) - sockaddr_store_port(&addr, addrlen, master->port); - xfr->task_transfer->cp = outnet_comm_point_for_http( - env->outnet, auth_xfer_transfer_http_callback, xfr, - &addr, addrlen, -1, master->ssl, master->host, - master->file, env->cfg); - if(!xfr->task_transfer->cp) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "cannot create http cp " - "connection for %s to %s", zname, as); - return 0; - } - comm_timer_set(xfr->task_transfer->timer, &t); - if(verbosity >= VERB_ALGO) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "auth zone %s transfer next HTTP fetch from %s started", zname, as); - } - /* Create or refresh the list of allow_notify addrs */ - probe_copy_masters_for_allow_notify(xfr); - return 1; - } - - /* perform AXFR/IXFR */ - /* set the packet to be written */ - /* create new ID */ - xfr->task_transfer->id = GET_RANDOM_ID(env->rnd); - xfr_create_ixfr_packet(xfr, env->scratch_buffer, - xfr->task_transfer->id, master); - - /* connect on fd */ - xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet, - auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen, - env->scratch_buffer, -1, - auth_name != NULL, auth_name); - if(!xfr->task_transfer->cp) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "cannot create tcp cp connection for " - "xfr %s to %s", zname, as); - return 0; - } - comm_timer_set(xfr->task_transfer->timer, &t); - if(verbosity >= VERB_ALGO) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "auth zone %s transfer next %s fetch from %s started", zname, - (xfr->task_transfer->on_ixfr?"IXFR":"AXFR"), as); - } - return 1; -} - -/** perform next lookup, next transfer TCP, or end and resume wait time task */ -static void -xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env) -{ - log_assert(xfr->task_transfer->worker == env->worker); - - /* are we performing lookups? */ - while(xfr->task_transfer->lookup_target) { - if(xfr_transfer_lookup_host(xfr, env)) { - /* wait for lookup to finish, - * note that the hostname may be in unbound's cache - * and we may then get an instant cache response, - * and that calls the callback just like a full - * lookup and lookup failures also call callback */ - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s transfer next target lookup", zname); - } - lock_basic_unlock(&xfr->lock); - return; - } - xfr_transfer_move_to_next_lookup(xfr, env); - } - - /* initiate TCP and fetch the zone from the master */ - /* and set timeout on it */ - while(!xfr_transfer_end_of_list(xfr)) { - xfr->task_transfer->master = xfr_transfer_current_master(xfr); - if(xfr_transfer_init_fetch(xfr, env)) { - /* successfully started, wait for callback */ - lock_basic_unlock(&xfr->lock); - return; - } - /* failed to fetch, next master */ - xfr_transfer_nextmaster(xfr); - } - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s transfer failed, wait", zname); - } - - /* we failed to fetch the zone, move to wait task - * use the shorter retry timeout */ - xfr_transfer_disown(xfr); - - /* pick up the nextprobe task and wait */ - if(xfr->task_nextprobe->worker == NULL) - xfr_set_timeout(xfr, env, 1, 0); - lock_basic_unlock(&xfr->lock); -} - -/** add addrs from A or AAAA rrset to the master */ -static void -xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset, - uint16_t rrtype) -{ - size_t i; - struct packed_rrset_data* data; - if(!m || !rrset) return; - if(rrtype != LDNS_RR_TYPE_A && rrtype != LDNS_RR_TYPE_AAAA) - return; - data = (struct packed_rrset_data*)rrset->entry.data; - for(i=0; icount; i++) { - struct auth_addr* a; - size_t len = data->rr_len[i] - 2; - uint8_t* rdata = data->rr_data[i]+2; - if(rrtype == LDNS_RR_TYPE_A && len != INET_SIZE) - continue; /* wrong length for A */ - if(rrtype == LDNS_RR_TYPE_AAAA && len != INET6_SIZE) - continue; /* wrong length for AAAA */ - - /* add and alloc it */ - a = (struct auth_addr*)calloc(1, sizeof(*a)); - if(!a) { - log_err("out of memory"); - return; - } - if(rrtype == LDNS_RR_TYPE_A) { - struct sockaddr_in* sa; - a->addrlen = (socklen_t)sizeof(*sa); - sa = (struct sockaddr_in*)&a->addr; - sa->sin_family = AF_INET; - sa->sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); - memmove(&sa->sin_addr, rdata, INET_SIZE); - } else { - struct sockaddr_in6* sa; - a->addrlen = (socklen_t)sizeof(*sa); - sa = (struct sockaddr_in6*)&a->addr; - sa->sin6_family = AF_INET6; - sa->sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); - memmove(&sa->sin6_addr, rdata, INET6_SIZE); - } - if(verbosity >= VERB_ALGO) { - char s[64]; - addr_to_str(&a->addr, a->addrlen, s, sizeof(s)); - verbose(VERB_ALGO, "auth host %s lookup %s", - m->host, s); - } - /* append to list */ - a->next = m->list; - m->list = a; - } -} - -/** callback for task_transfer lookup of host name, of A or AAAA */ -void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf, - enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus), - int ATTR_UNUSED(was_ratelimited)) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_transfer); - lock_basic_lock(&xfr->lock); - env = xfr->task_transfer->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return; /* stop on quit */ - } - - /* process result */ - if(rcode == LDNS_RCODE_NOERROR) { - uint16_t wanted_qtype = LDNS_RR_TYPE_A; - struct regional* temp = env->scratch; - struct query_info rq; - struct reply_info* rep; - if(xfr->task_transfer->lookup_aaaa) - wanted_qtype = LDNS_RR_TYPE_AAAA; - memset(&rq, 0, sizeof(rq)); - rep = parse_reply_in_temp_region(buf, temp, &rq); - if(rep && rq.qtype == wanted_qtype && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) { - /* parsed successfully */ - struct ub_packed_rrset_key* answer = - reply_find_answer_rrset(&rq, rep); - if(answer) { - xfr_master_add_addrs(xfr->task_transfer-> - lookup_target, answer, wanted_qtype); - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has nodata", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A")); - } - } - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has no answer", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A")); - } - } - regional_free_all(temp); - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup failed", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A")); - } - } - if(xfr->task_transfer->lookup_target->list && - xfr->task_transfer->lookup_target == xfr_transfer_current_master(xfr)) - xfr->task_transfer->scan_addr = xfr->task_transfer->lookup_target->list; - - /* move to lookup AAAA after A lookup, move to next hostname lookup, - * or move to fetch the zone, or, if nothing to do, end task_transfer */ - xfr_transfer_move_to_next_lookup(xfr, env); - xfr_transfer_nexttarget_or_end(xfr, env); -} - -/** check if xfer (AXFR or IXFR) packet is OK. - * return false if we lost connection (SERVFAIL, or unreadable). - * return false if we need to move from IXFR to AXFR, with gonextonfail - * set to false, so the same master is tried again, but with AXFR. - * return true if fine to link into data. - * return true with transferdone=true when the transfer has ended. - */ -static int -check_xfer_packet(sldns_buffer* pkt, struct auth_xfer* xfr, - int* gonextonfail, int* transferdone) -{ - uint8_t* wire = sldns_buffer_begin(pkt); - int i; - if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) { - verbose(VERB_ALGO, "xfr to %s failed, packet too small", - xfr->task_transfer->master->host); - return 0; - } - if(!LDNS_QR_WIRE(wire)) { - verbose(VERB_ALGO, "xfr to %s failed, packet has no QR flag", - xfr->task_transfer->master->host); - return 0; - } - if(LDNS_TC_WIRE(wire)) { - verbose(VERB_ALGO, "xfr to %s failed, packet has TC flag", - xfr->task_transfer->master->host); - return 0; - } - /* check ID */ - if(LDNS_ID_WIRE(wire) != xfr->task_transfer->id) { - verbose(VERB_ALGO, "xfr to %s failed, packet wrong ID", - xfr->task_transfer->master->host); - return 0; - } - if(LDNS_RCODE_WIRE(wire) != LDNS_RCODE_NOERROR) { - char rcode[32]; - sldns_wire2str_rcode_buf((int)LDNS_RCODE_WIRE(wire), rcode, - sizeof(rcode)); - /* if we are doing IXFR, check for fallback */ - if(xfr->task_transfer->on_ixfr) { - if(LDNS_RCODE_WIRE(wire) == LDNS_RCODE_NOTIMPL || - LDNS_RCODE_WIRE(wire) == LDNS_RCODE_SERVFAIL || - LDNS_RCODE_WIRE(wire) == LDNS_RCODE_REFUSED || - LDNS_RCODE_WIRE(wire) == LDNS_RCODE_FORMERR) { - verbose(VERB_ALGO, "xfr to %s, fallback " - "from IXFR to AXFR (with rcode %s)", - xfr->task_transfer->master->host, - rcode); - xfr->task_transfer->ixfr_fail = 1; - *gonextonfail = 0; - return 0; - } - } - verbose(VERB_ALGO, "xfr to %s failed, packet with rcode %s", - xfr->task_transfer->master->host, rcode); - return 0; - } - if(LDNS_OPCODE_WIRE(wire) != LDNS_PACKET_QUERY) { - verbose(VERB_ALGO, "xfr to %s failed, packet with bad opcode", - xfr->task_transfer->master->host); - return 0; - } - if(LDNS_QDCOUNT(wire) > 1) { - verbose(VERB_ALGO, "xfr to %s failed, packet has qdcount %d", - xfr->task_transfer->master->host, - (int)LDNS_QDCOUNT(wire)); - return 0; - } - - /* check qname */ - sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE); - for(i=0; i<(int)LDNS_QDCOUNT(wire); i++) { - size_t pos = sldns_buffer_position(pkt); - uint16_t qtype, qclass; - if(pkt_dname_len(pkt) == 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "malformed dname", - xfr->task_transfer->master->host); - return 0; - } - if(dname_pkt_compare(pkt, sldns_buffer_at(pkt, pos), - xfr->name) != 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "wrong qname", - xfr->task_transfer->master->host); - return 0; - } - if(sldns_buffer_remaining(pkt) < 4) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated query RR", - xfr->task_transfer->master->host); - return 0; - } - qtype = sldns_buffer_read_u16(pkt); - qclass = sldns_buffer_read_u16(pkt); - if(qclass != xfr->dclass) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "wrong qclass", - xfr->task_transfer->master->host); - return 0; - } - if(xfr->task_transfer->on_ixfr) { - if(qtype != LDNS_RR_TYPE_IXFR) { - verbose(VERB_ALGO, "xfr to %s failed, packet " - "with wrong qtype, expected IXFR", - xfr->task_transfer->master->host); - return 0; - } - } else { - if(qtype != LDNS_RR_TYPE_AXFR) { - verbose(VERB_ALGO, "xfr to %s failed, packet " - "with wrong qtype, expected AXFR", - xfr->task_transfer->master->host); - return 0; - } - } - } - - /* check parse of RRs in packet, store first SOA serial - * to be able to detect last SOA (with that serial) to see if done */ - /* also check for IXFR 'zone up to date' reply */ - for(i=0; i<(int)LDNS_ANCOUNT(wire); i++) { - size_t pos = sldns_buffer_position(pkt); - uint16_t tp, rdlen; - if(pkt_dname_len(pkt) == 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "malformed dname in answer section", - xfr->task_transfer->master->host); - return 0; - } - if(sldns_buffer_remaining(pkt) < 10) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR", - xfr->task_transfer->master->host); - return 0; - } - tp = sldns_buffer_read_u16(pkt); - (void)sldns_buffer_read_u16(pkt); /* class */ - (void)sldns_buffer_read_u32(pkt); /* ttl */ - rdlen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdlen) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR rdata", - xfr->task_transfer->master->host); - return 0; - } - - /* RR parses (haven't checked rdata itself), now look at - * SOA records to see serial number */ - if(xfr->task_transfer->rr_scan_num == 0 && - tp != LDNS_RR_TYPE_SOA) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "malformed zone transfer, no start SOA", - xfr->task_transfer->master->host); - return 0; - } - if(xfr->task_transfer->rr_scan_num == 1 && - tp != LDNS_RR_TYPE_SOA) { - /* second RR is not a SOA record, this is not an IXFR - * the master is replying with an AXFR */ - xfr->task_transfer->on_ixfr_is_axfr = 1; - } - if(tp == LDNS_RR_TYPE_SOA) { - uint32_t serial; - if(rdlen < 22) { - verbose(VERB_ALGO, "xfr to %s failed, packet " - "with SOA with malformed rdata", - xfr->task_transfer->master->host); - return 0; - } - if(dname_pkt_compare(pkt, sldns_buffer_at(pkt, pos), - xfr->name) != 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet " - "with SOA with wrong dname", - xfr->task_transfer->master->host); - return 0; - } - - /* read serial number of SOA */ - serial = sldns_buffer_read_u32_at(pkt, - sldns_buffer_position(pkt)+rdlen-20); - - /* check for IXFR 'zone has SOA x' reply */ - if(xfr->task_transfer->on_ixfr && - xfr->task_transfer->rr_scan_num == 0 && - LDNS_ANCOUNT(wire)==1) { - verbose(VERB_ALGO, "xfr to %s ended, " - "IXFR reply that zone has serial %u," - " fallback from IXFR to AXFR", - xfr->task_transfer->master->host, - (unsigned)serial); - xfr->task_transfer->ixfr_fail = 1; - *gonextonfail = 0; - return 0; - } - - /* if first SOA, store serial number */ - if(xfr->task_transfer->got_xfr_serial == 0) { - xfr->task_transfer->got_xfr_serial = 1; - xfr->task_transfer->incoming_xfr_serial = - serial; - verbose(VERB_ALGO, "xfr %s: contains " - "SOA serial %u", - xfr->task_transfer->master->host, - (unsigned)serial); - /* see if end of AXFR */ - } else if(!xfr->task_transfer->on_ixfr || - xfr->task_transfer->on_ixfr_is_axfr) { - /* second SOA with serial is the end - * for AXFR */ - *transferdone = 1; - verbose(VERB_ALGO, "xfr %s: last AXFR packet", - xfr->task_transfer->master->host); - /* for IXFR, count SOA records with that serial */ - } else if(xfr->task_transfer->incoming_xfr_serial == - serial && xfr->task_transfer->got_xfr_serial - == 1) { - xfr->task_transfer->got_xfr_serial++; - /* if not first soa, if serial==firstserial, the - * third time we are at the end, for IXFR */ - } else if(xfr->task_transfer->incoming_xfr_serial == - serial && xfr->task_transfer->got_xfr_serial - == 2) { - verbose(VERB_ALGO, "xfr %s: last IXFR packet", - xfr->task_transfer->master->host); - *transferdone = 1; - /* continue parse check, if that succeeds, - * transfer is done */ - } - } - xfr->task_transfer->rr_scan_num++; - - /* skip over RR rdata to go to the next RR */ - sldns_buffer_skip(pkt, (ssize_t)rdlen); - } - - /* check authority section */ - /* we skip over the RRs checking packet format */ - for(i=0; i<(int)LDNS_NSCOUNT(wire); i++) { - uint16_t rdlen; - if(pkt_dname_len(pkt) == 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "malformed dname in authority section", - xfr->task_transfer->master->host); - return 0; - } - if(sldns_buffer_remaining(pkt) < 10) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR", - xfr->task_transfer->master->host); - return 0; - } - (void)sldns_buffer_read_u16(pkt); /* type */ - (void)sldns_buffer_read_u16(pkt); /* class */ - (void)sldns_buffer_read_u32(pkt); /* ttl */ - rdlen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdlen) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR rdata", - xfr->task_transfer->master->host); - return 0; - } - /* skip over RR rdata to go to the next RR */ - sldns_buffer_skip(pkt, (ssize_t)rdlen); - } - - /* check additional section */ - for(i=0; i<(int)LDNS_ARCOUNT(wire); i++) { - uint16_t rdlen; - if(pkt_dname_len(pkt) == 0) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "malformed dname in additional section", - xfr->task_transfer->master->host); - return 0; - } - if(sldns_buffer_remaining(pkt) < 10) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR", - xfr->task_transfer->master->host); - return 0; - } - (void)sldns_buffer_read_u16(pkt); /* type */ - (void)sldns_buffer_read_u16(pkt); /* class */ - (void)sldns_buffer_read_u32(pkt); /* ttl */ - rdlen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdlen) { - verbose(VERB_ALGO, "xfr to %s failed, packet with " - "truncated RR rdata", - xfr->task_transfer->master->host); - return 0; - } - /* skip over RR rdata to go to the next RR */ - sldns_buffer_skip(pkt, (ssize_t)rdlen); - } - - return 1; -} - -/** Link the data from this packet into the worklist of transferred data */ -static int -xfer_link_data(sldns_buffer* pkt, struct auth_xfer* xfr) -{ - /* alloc it */ - struct auth_chunk* e; - e = (struct auth_chunk*)calloc(1, sizeof(*e)); - if(!e) return 0; - e->next = NULL; - e->len = sldns_buffer_limit(pkt); - e->data = memdup(sldns_buffer_begin(pkt), e->len); - if(!e->data) { - free(e); - return 0; - } - - /* alloc succeeded, link into list */ - if(!xfr->task_transfer->chunks_first) - xfr->task_transfer->chunks_first = e; - if(xfr->task_transfer->chunks_last) - xfr->task_transfer->chunks_last->next = e; - xfr->task_transfer->chunks_last = e; - return 1; -} - -/** task transfer. the list of data is complete. process it and if failed - * move to next master, if succeeded, end the task transfer */ -static void -process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env) -{ - int ixfr_fail = 0; - if(xfr_process_chunk_list(xfr, env, &ixfr_fail)) { - /* it worked! */ - auth_chunks_delete(xfr->task_transfer); - - /* we fetched the zone, move to wait task */ - xfr_transfer_disown(xfr); - - if(xfr->notify_received && (!xfr->notify_has_serial || - (xfr->notify_has_serial && - xfr_serial_means_update(xfr, xfr->notify_serial)))) { - uint32_t sr = xfr->notify_serial; - int has_sr = xfr->notify_has_serial; - /* we received a notify while probe/transfer was - * in progress. start a new probe and transfer */ - xfr->notify_received = 0; - xfr->notify_has_serial = 0; - xfr->notify_serial = 0; - if(!xfr_start_probe(xfr, env, NULL)) { - /* if we couldn't start it, already in - * progress; restore notify serial, - * while xfr still locked */ - xfr->notify_received = 1; - xfr->notify_has_serial = has_sr; - xfr->notify_serial = sr; - lock_basic_unlock(&xfr->lock); - } - return; - } else { - /* pick up the nextprobe task and wait (normail wait time) */ - if(xfr->task_nextprobe->worker == NULL) - xfr_set_timeout(xfr, env, 0, 0); - } - lock_basic_unlock(&xfr->lock); - return; - } - /* processing failed */ - /* when done, delete data from list */ - auth_chunks_delete(xfr->task_transfer); - if(ixfr_fail) { - xfr->task_transfer->ixfr_fail = 1; - } else { - xfr_transfer_nextmaster(xfr); - } - xfr_transfer_nexttarget_or_end(xfr, env); -} - -/** callback for the task_transfer timer */ -void -auth_xfer_transfer_timer_callback(void* arg) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - int gonextonfail = 1; - log_assert(xfr->task_transfer); - lock_basic_lock(&xfr->lock); - env = xfr->task_transfer->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return; /* stop on quit */ - } - - verbose(VERB_ALGO, "xfr stopped, connection timeout to %s", - xfr->task_transfer->master->host); - - /* see if IXFR caused the failure, if so, try AXFR */ - if(xfr->task_transfer->on_ixfr) { - xfr->task_transfer->ixfr_possible_timeout_count++; - if(xfr->task_transfer->ixfr_possible_timeout_count >= - NUM_TIMEOUTS_FALLBACK_IXFR) { - verbose(VERB_ALGO, "xfr to %s, fallback " - "from IXFR to AXFR (because of timeouts)", - xfr->task_transfer->master->host); - xfr->task_transfer->ixfr_fail = 1; - gonextonfail = 0; - } - } - - /* delete transferred data from list */ - auth_chunks_delete(xfr->task_transfer); - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - if(gonextonfail) - xfr_transfer_nextmaster(xfr); - xfr_transfer_nexttarget_or_end(xfr, env); -} - -/** callback for task_transfer tcp connections */ -int -auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* ATTR_UNUSED(repinfo)) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - int gonextonfail = 1; - int transferdone = 0; - log_assert(xfr->task_transfer); - lock_basic_lock(&xfr->lock); - env = xfr->task_transfer->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return 0; /* stop on quit */ - } - /* stop the timer */ - comm_timer_disable(xfr->task_transfer->timer); - - if(err != NETEVENT_NOERROR) { - /* connection failed, closed, or timeout */ - /* stop this transfer, cleanup - * and continue task_transfer*/ - verbose(VERB_ALGO, "xfr stopped, connection lost to %s", - xfr->task_transfer->master->host); - - /* see if IXFR caused the failure, if so, try AXFR */ - if(xfr->task_transfer->on_ixfr) { - xfr->task_transfer->ixfr_possible_timeout_count++; - if(xfr->task_transfer->ixfr_possible_timeout_count >= - NUM_TIMEOUTS_FALLBACK_IXFR) { - verbose(VERB_ALGO, "xfr to %s, fallback " - "from IXFR to AXFR (because of timeouts)", - xfr->task_transfer->master->host); - xfr->task_transfer->ixfr_fail = 1; - gonextonfail = 0; - } - } - - failed: - /* delete transferred data from list */ - auth_chunks_delete(xfr->task_transfer); - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - if(gonextonfail) - xfr_transfer_nextmaster(xfr); - xfr_transfer_nexttarget_or_end(xfr, env); - return 0; - } - /* note that IXFR worked without timeout */ - if(xfr->task_transfer->on_ixfr) - xfr->task_transfer->ixfr_possible_timeout_count = 0; - - /* handle returned packet */ - /* if it fails, cleanup and end this transfer */ - /* if it needs to fallback from IXFR to AXFR, do that */ - if(!check_xfer_packet(c->buffer, xfr, &gonextonfail, &transferdone)) { - goto failed; - } - /* if it is good, link it into the list of data */ - /* if the link into list of data fails (malloc fail) cleanup and end */ - if(!xfer_link_data(c->buffer, xfr)) { - verbose(VERB_ALGO, "xfr stopped to %s, malloc failed", - xfr->task_transfer->master->host); - goto failed; - } - /* if the transfer is done now, disconnect and process the list */ - if(transferdone) { - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - process_list_end_transfer(xfr, env); - return 0; - } - - /* if we want to read more messages, setup the commpoint to read - * a DNS packet, and the timeout */ - lock_basic_unlock(&xfr->lock); - c->tcp_is_reading = 1; - sldns_buffer_clear(c->buffer); - comm_point_start_listening(c, -1, AUTH_TRANSFER_TIMEOUT); - return 0; -} - -/** callback for task_transfer http connections */ -int -auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* repinfo) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_transfer); - lock_basic_lock(&xfr->lock); - env = xfr->task_transfer->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return 0; /* stop on quit */ - } - verbose(VERB_ALGO, "auth zone transfer http callback"); - /* stop the timer */ - comm_timer_disable(xfr->task_transfer->timer); - - if(err != NETEVENT_NOERROR && err != NETEVENT_DONE) { - /* connection failed, closed, or timeout */ - /* stop this transfer, cleanup - * and continue task_transfer*/ - verbose(VERB_ALGO, "http stopped, connection lost to %s", - xfr->task_transfer->master->host); - failed: - /* delete transferred data from list */ - auth_chunks_delete(xfr->task_transfer); - if(repinfo) repinfo->c = NULL; /* signal cp deleted to - the routine calling this callback */ - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - xfr_transfer_nextmaster(xfr); - xfr_transfer_nexttarget_or_end(xfr, env); - return 0; - } - - /* if it is good, link it into the list of data */ - /* if the link into list of data fails (malloc fail) cleanup and end */ - if(sldns_buffer_limit(c->buffer) > 0) { - verbose(VERB_ALGO, "auth zone http queued up %d bytes", - (int)sldns_buffer_limit(c->buffer)); - if(!xfer_link_data(c->buffer, xfr)) { - verbose(VERB_ALGO, "http stopped to %s, malloc failed", - xfr->task_transfer->master->host); - goto failed; - } - } - /* if the transfer is done now, disconnect and process the list */ - if(err == NETEVENT_DONE) { - if(repinfo) repinfo->c = NULL; /* signal cp deleted to - the routine calling this callback */ - comm_point_delete(xfr->task_transfer->cp); - xfr->task_transfer->cp = NULL; - process_list_end_transfer(xfr, env); - return 0; - } - - /* if we want to read more messages, setup the commpoint to read - * a DNS packet, and the timeout */ - lock_basic_unlock(&xfr->lock); - c->tcp_is_reading = 1; - sldns_buffer_clear(c->buffer); - comm_point_start_listening(c, -1, AUTH_TRANSFER_TIMEOUT); - return 0; -} - - -/** start transfer task by this worker , xfr is locked. */ -static void -xfr_start_transfer(struct auth_xfer* xfr, struct module_env* env, - struct auth_master* master) -{ - log_assert(xfr->task_transfer != NULL); - log_assert(xfr->task_transfer->worker == NULL); - log_assert(xfr->task_transfer->chunks_first == NULL); - log_assert(xfr->task_transfer->chunks_last == NULL); - xfr->task_transfer->worker = env->worker; - xfr->task_transfer->env = env; - - /* init transfer process */ - /* find that master in the transfer's list of masters? */ - xfr_transfer_start_list(xfr, master); - /* start lookup for hostnames in transfer master list */ - xfr_transfer_start_lookups(xfr); - - /* initiate TCP, and set timeout on it */ - xfr_transfer_nexttarget_or_end(xfr, env); -} - -/** disown task_probe. caller must hold xfr.lock */ -static void -xfr_probe_disown(struct auth_xfer* xfr) -{ - /* remove timer (from this worker's event base) */ - comm_timer_delete(xfr->task_probe->timer); - xfr->task_probe->timer = NULL; - /* remove the commpoint */ - comm_point_delete(xfr->task_probe->cp); - xfr->task_probe->cp = NULL; - /* we don't own this item anymore */ - xfr->task_probe->worker = NULL; - xfr->task_probe->env = NULL; -} - -/** send the UDP probe to the master, this is part of task_probe */ -static int -xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env, - int timeout) -{ - struct sockaddr_storage addr; - socklen_t addrlen = 0; - struct timeval t; - /* pick master */ - struct auth_master* master = xfr_probe_current_master(xfr); - char *auth_name = NULL; - if(!master) return 0; - if(master->allow_notify) return 0; /* only for notify */ - if(master->http) return 0; /* only masters get SOA UDP probe, - not urls, if those are in this list */ - - /* get master addr */ - if(xfr->task_probe->scan_addr) { - addrlen = xfr->task_probe->scan_addr->addrlen; - memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen); - } else { - if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) { - /* the ones that are not in addr format are supposed - * to be looked up. The lookup has failed however, - * so skip them */ - char zname[255+1]; - dname_str(xfr->name, zname); - log_err("%s: failed lookup, cannot probe to master %s", - zname, master->host); - return 0; - } - if (auth_name != NULL) { - if (addr.ss_family == AF_INET - && (int)ntohs(((struct sockaddr_in *)&addr)->sin_port) - == env->cfg->ssl_port) - ((struct sockaddr_in *)&addr)->sin_port - = htons((uint16_t)env->cfg->port); - else if (addr.ss_family == AF_INET6 - && (int)ntohs(((struct sockaddr_in6 *)&addr)->sin6_port) - == env->cfg->ssl_port) - ((struct sockaddr_in6 *)&addr)->sin6_port - = htons((uint16_t)env->cfg->port); - } - } - - /* create packet */ - /* create new ID for new probes, but not on timeout retries, - * this means we'll accept replies to previous retries to same ip */ - if(timeout == AUTH_PROBE_TIMEOUT) - xfr->task_probe->id = GET_RANDOM_ID(env->rnd); - xfr_create_soa_probe_packet(xfr, env->scratch_buffer, - xfr->task_probe->id); - /* we need to remove the cp if we have a different ip4/ip6 type now */ - if(xfr->task_probe->cp && - ((xfr->task_probe->cp_is_ip6 && !addr_is_ip6(&addr, addrlen)) || - (!xfr->task_probe->cp_is_ip6 && addr_is_ip6(&addr, addrlen))) - ) { - comm_point_delete(xfr->task_probe->cp); - xfr->task_probe->cp = NULL; - } - if(!xfr->task_probe->cp) { - if(addr_is_ip6(&addr, addrlen)) - xfr->task_probe->cp_is_ip6 = 1; - else xfr->task_probe->cp_is_ip6 = 0; - xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet, - auth_xfer_probe_udp_callback, xfr, &addr, addrlen); - if(!xfr->task_probe->cp) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "cannot create udp cp for " - "probe %s to %s", zname, as); - return 0; - } - } - if(!xfr->task_probe->timer) { - xfr->task_probe->timer = comm_timer_create(env->worker_base, - auth_xfer_probe_timer_callback, xfr); - if(!xfr->task_probe->timer) { - log_err("malloc failure"); - return 0; - } - } - - /* send udp packet */ - if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer, - (struct sockaddr*)&addr, addrlen, 0)) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "failed to send soa probe for %s to %s", - zname, as); - return 0; - } - if(verbosity >= VERB_ALGO) { - char zname[255+1], as[256]; - dname_str(xfr->name, zname); - addr_to_str(&addr, addrlen, as, sizeof(as)); - verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname, - as); - } - xfr->task_probe->timeout = timeout; -#ifndef S_SPLINT_S - t.tv_sec = timeout/1000; - t.tv_usec = (timeout%1000)*1000; -#endif - comm_timer_set(xfr->task_probe->timer, &t); - - return 1; -} - -/** callback for task_probe timer */ -void -auth_xfer_probe_timer_callback(void* arg) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_probe); - lock_basic_lock(&xfr->lock); - env = xfr->task_probe->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return; /* stop on quit */ - } - - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s soa probe timeout", zname); - } - if(xfr->task_probe->timeout <= AUTH_PROBE_TIMEOUT_STOP) { - /* try again with bigger timeout */ - if(xfr_probe_send_probe(xfr, env, xfr->task_probe->timeout*2)) { - lock_basic_unlock(&xfr->lock); - return; - } - } - /* delete commpoint so a new one is created, with a fresh port nr */ - comm_point_delete(xfr->task_probe->cp); - xfr->task_probe->cp = NULL; - - /* too many timeouts (or fail to send), move to next or end */ - xfr_probe_nextmaster(xfr); - xfr_probe_send_or_end(xfr, env); -} - -/** callback for task_probe udp packets */ -int -auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* repinfo) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_probe); - lock_basic_lock(&xfr->lock); - env = xfr->task_probe->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return 0; /* stop on quit */ - } - - /* the comm_point_udp_callback is in a for loop for NUM_UDP_PER_SELECT - * and we set rep.c=NULL to stop if from looking inside the commpoint*/ - repinfo->c = NULL; - /* stop the timer */ - comm_timer_disable(xfr->task_probe->timer); - - /* see if we got a packet and what that means */ - if(err == NETEVENT_NOERROR) { - uint32_t serial = 0; - if(check_packet_ok(c->buffer, LDNS_RR_TYPE_SOA, xfr, - &serial)) { - /* successful lookup */ - if(verbosity >= VERB_ALGO) { - char buf[256]; - dname_str(xfr->name, buf); - verbose(VERB_ALGO, "auth zone %s: soa probe " - "serial is %u", buf, (unsigned)serial); - } - /* see if this serial indicates that the zone has - * to be updated */ - if(xfr_serial_means_update(xfr, serial)) { - /* if updated, start the transfer task, if needed */ - verbose(VERB_ALGO, "auth_zone updated, start transfer"); - if(xfr->task_transfer->worker == NULL) { - struct auth_master* master = - xfr_probe_current_master(xfr); - /* if we have download URLs use them - * in preference to this master we - * just probed the SOA from */ - if(xfr->task_transfer->masters && - xfr->task_transfer->masters->http) - master = NULL; - xfr_probe_disown(xfr); - xfr_start_transfer(xfr, env, master); - return 0; - - } - /* other tasks are running, we don't do this anymore */ - xfr_probe_disown(xfr); - lock_basic_unlock(&xfr->lock); - /* return, we don't sent a reply to this udp packet, - * and we setup the tasks to do next */ - return 0; - } else { - verbose(VERB_ALGO, "auth_zone master reports unchanged soa serial"); - /* we if cannot find updates amongst the - * masters, this means we then have a new lease - * on the zone */ - xfr->task_probe->have_new_lease = 1; - } - } else { - if(verbosity >= VERB_ALGO) { - char buf[256]; - dname_str(xfr->name, buf); - verbose(VERB_ALGO, "auth zone %s: bad reply to soa probe", buf); - } - } - } else { - if(verbosity >= VERB_ALGO) { - char buf[256]; - dname_str(xfr->name, buf); - verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf); - } - } - - /* failed lookup or not an update */ - /* delete commpoint so a new one is created, with a fresh port nr */ - comm_point_delete(xfr->task_probe->cp); - xfr->task_probe->cp = NULL; - - /* if the result was not a successful probe, we need - * to send the next one */ - xfr_probe_nextmaster(xfr); - xfr_probe_send_or_end(xfr, env); - return 0; -} - -/** lookup a host name for its addresses, if needed */ -static int -xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env) -{ - struct sockaddr_storage addr; - socklen_t addrlen = 0; - struct auth_master* master = xfr->task_probe->lookup_target; - struct query_info qinfo; - uint16_t qflags = BIT_RD; - uint8_t dname[LDNS_MAX_DOMAINLEN+1]; - struct edns_data edns; - sldns_buffer* buf = env->scratch_buffer; - if(!master) return 0; - if(extstrtoaddr(master->host, &addr, &addrlen, UNBOUND_DNS_PORT)) { - /* not needed, host is in IP addr format */ - return 0; - } - if(master->allow_notify && !master->http && - strchr(master->host, '/') != NULL && - strchr(master->host, '/') == strrchr(master->host, '/')) { - return 0; /* is IP/prefix format, not something to look up */ - } - - /* use mesh_new_callback to probe for non-addr hosts, - * and then wait for them to be looked up (in cache, or query) */ - qinfo.qname_len = sizeof(dname); - if(sldns_str2wire_dname_buf(master->host, dname, &qinfo.qname_len) - != 0) { - log_err("cannot parse host name of master %s", master->host); - return 0; - } - qinfo.qname = dname; - qinfo.qclass = xfr->dclass; - qinfo.qtype = LDNS_RR_TYPE_A; - if(xfr->task_probe->lookup_aaaa) - qinfo.qtype = LDNS_RR_TYPE_AAAA; - qinfo.local_alias = NULL; - if(verbosity >= VERB_ALGO) { - char buf1[512]; - char buf2[LDNS_MAX_DOMAINLEN+1]; - dname_str(xfr->name, buf2); - snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup" - " for task_probe", buf2); - log_query_info(VERB_ALGO, buf1, &qinfo); - } - edns.edns_present = 1; - edns.ext_rcode = 0; - edns.edns_version = 0; - edns.bits = EDNS_DO; - edns.opt_list_in = NULL; - edns.opt_list_out = NULL; - edns.opt_list_inplace_cb_out = NULL; - edns.padding_block_size = 0; - edns.cookie_present = 0; - edns.cookie_valid = 0; - if(sldns_buffer_capacity(buf) < 65535) - edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); - else edns.udp_size = 65535; - - /* unlock xfr during mesh_new_callback() because the callback can be - * called straight away */ - lock_basic_unlock(&xfr->lock); - if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_xfer_probe_lookup_callback, xfr, 0)) { - lock_basic_lock(&xfr->lock); - log_err("out of memory lookup up master %s", master->host); - return 0; - } - lock_basic_lock(&xfr->lock); - return 1; -} - -/** move to sending the probe packets, next if fails. task_probe */ -static void -xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env) -{ - /* are we doing hostname lookups? */ - while(xfr->task_probe->lookup_target) { - if(xfr_probe_lookup_host(xfr, env)) { - /* wait for lookup to finish, - * note that the hostname may be in unbound's cache - * and we may then get an instant cache response, - * and that calls the callback just like a full - * lookup and lookup failures also call callback */ - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s probe next target lookup", zname); - } - lock_basic_unlock(&xfr->lock); - return; - } - xfr_probe_move_to_next_lookup(xfr, env); - } - /* probe of list has ended. Create or refresh the list of of - * allow_notify addrs */ - probe_copy_masters_for_allow_notify(xfr); - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s probe: notify addrs updated", zname); - } - if(xfr->task_probe->only_lookup) { - /* only wanted lookups for copy, stop probe and start wait */ - xfr->task_probe->only_lookup = 0; - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname); - } - xfr_probe_disown(xfr); - if(xfr->task_nextprobe->worker == NULL) - xfr_set_timeout(xfr, env, 0, 0); - lock_basic_unlock(&xfr->lock); - return; - } - - /* send probe packets */ - while(!xfr_probe_end_of_list(xfr)) { - if(xfr_probe_send_probe(xfr, env, AUTH_PROBE_TIMEOUT)) { - /* successfully sent probe, wait for callback */ - lock_basic_unlock(&xfr->lock); - return; - } - /* failed to send probe, next master */ - xfr_probe_nextmaster(xfr); - } - - /* done with probe sequence, wait */ - if(xfr->task_probe->have_new_lease) { - /* if zone not updated, start the wait timer again */ - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth_zone %s unchanged, new lease, wait", zname); - } - xfr_probe_disown(xfr); - if(xfr->have_zone) - xfr->lease_time = *env->now; - if(xfr->task_nextprobe->worker == NULL) - xfr_set_timeout(xfr, env, 0, 0); - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s soa probe failed, wait to retry", zname); - } - /* we failed to send this as well, move to the wait task, - * use the shorter retry timeout */ - xfr_probe_disown(xfr); - /* pick up the nextprobe task and wait */ - if(xfr->task_nextprobe->worker == NULL) - xfr_set_timeout(xfr, env, 1, 0); - } - - lock_basic_unlock(&xfr->lock); -} - -/** callback for task_probe lookup of host name, of A or AAAA */ -void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf, - enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus), - int ATTR_UNUSED(was_ratelimited)) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_probe); - lock_basic_lock(&xfr->lock); - env = xfr->task_probe->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return; /* stop on quit */ - } - - /* process result */ - if(rcode == LDNS_RCODE_NOERROR) { - uint16_t wanted_qtype = LDNS_RR_TYPE_A; - struct regional* temp = env->scratch; - struct query_info rq; - struct reply_info* rep; - if(xfr->task_probe->lookup_aaaa) - wanted_qtype = LDNS_RR_TYPE_AAAA; - memset(&rq, 0, sizeof(rq)); - rep = parse_reply_in_temp_region(buf, temp, &rq); - if(rep && rq.qtype == wanted_qtype && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) { - /* parsed successfully */ - struct ub_packed_rrset_key* answer = - reply_find_answer_rrset(&rq, rep); - if(answer) { - xfr_master_add_addrs(xfr->task_probe-> - lookup_target, answer, wanted_qtype); - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has nodata", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A")); - } - } - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has no address", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A")); - } - } - regional_free_all(temp); - } else { - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup failed", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A")); - } - } - if(xfr->task_probe->lookup_target->list && - xfr->task_probe->lookup_target == xfr_probe_current_master(xfr)) - xfr->task_probe->scan_addr = xfr->task_probe->lookup_target->list; - - /* move to lookup AAAA after A lookup, move to next hostname lookup, - * or move to send the probes, or, if nothing to do, end task_probe */ - xfr_probe_move_to_next_lookup(xfr, env); - xfr_probe_send_or_end(xfr, env); -} - -/** disown task_nextprobe. caller must hold xfr.lock */ -static void -xfr_nextprobe_disown(struct auth_xfer* xfr) -{ - /* delete the timer, because the next worker to pick this up may - * not have the same event base */ - comm_timer_delete(xfr->task_nextprobe->timer); - xfr->task_nextprobe->timer = NULL; - xfr->task_nextprobe->next_probe = 0; - /* we don't own this item anymore */ - xfr->task_nextprobe->worker = NULL; - xfr->task_nextprobe->env = NULL; -} - -/** xfer nextprobe timeout callback, this is part of task_nextprobe */ -void -auth_xfer_timer(void* arg) -{ - struct auth_xfer* xfr = (struct auth_xfer*)arg; - struct module_env* env; - log_assert(xfr->task_nextprobe); - lock_basic_lock(&xfr->lock); - env = xfr->task_nextprobe->env; - if(!env || env->outnet->want_to_quit) { - lock_basic_unlock(&xfr->lock); - return; /* stop on quit */ - } - - /* see if zone has expired, and if so, also set auth_zone expired */ - if(xfr->have_zone && !xfr->zone_expired && - *env->now >= xfr->lease_time + xfr->expiry) { - lock_basic_unlock(&xfr->lock); - auth_xfer_set_expired(xfr, env, 1); - lock_basic_lock(&xfr->lock); - } - - xfr_nextprobe_disown(xfr); - - if(!xfr_start_probe(xfr, env, NULL)) { - /* not started because already in progress */ - lock_basic_unlock(&xfr->lock); - } -} - -/** return true if there are probe (SOA UDP query) targets in the master list*/ -static int -have_probe_targets(struct auth_master* list) -{ - struct auth_master* p; - for(p=list; p; p = p->next) { - if(!p->allow_notify && p->host) - return 1; - } - return 0; -} - -/** start task_probe if possible, if no masters for probe start task_transfer - * returns true if task has been started, and false if the task is already - * in progress. */ -static int -xfr_start_probe(struct auth_xfer* xfr, struct module_env* env, - struct auth_master* spec) -{ - /* see if we need to start a probe (or maybe it is already in - * progress (due to notify)) */ - if(xfr->task_probe->worker == NULL) { - if(!have_probe_targets(xfr->task_probe->masters) && - !(xfr->task_probe->only_lookup && - xfr->task_probe->masters != NULL)) { - /* useless to pick up task_probe, no masters to - * probe. Instead attempt to pick up task transfer */ - if(xfr->task_transfer->worker == NULL) { - xfr_start_transfer(xfr, env, spec); - return 1; - } - /* task transfer already in progress */ - return 0; - } - - /* pick up the probe task ourselves */ - xfr->task_probe->worker = env->worker; - xfr->task_probe->env = env; - xfr->task_probe->cp = NULL; - - /* start the task */ - /* have not seen a new lease yet, this scan */ - xfr->task_probe->have_new_lease = 0; - /* if this was a timeout, no specific first master to scan */ - /* otherwise, spec is nonNULL the notified master, scan - * first and also transfer first from it */ - xfr_probe_start_list(xfr, spec); - /* setup to start the lookup of hostnames of masters afresh */ - xfr_probe_start_lookups(xfr); - /* send the probe packet or next send, or end task */ - xfr_probe_send_or_end(xfr, env); - return 1; - } - return 0; -} - -/** for task_nextprobe. - * determine next timeout for auth_xfer. Also (re)sets timer. - * @param xfr: task structure - * @param env: module environment, with worker and time. - * @param failure: set true if timer should be set for failure retry. - * @param lookup_only: only perform lookups when timer done, 0 sec timeout - */ -static void -xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env, - int failure, int lookup_only) -{ - struct timeval tv; - log_assert(xfr->task_nextprobe != NULL); - log_assert(xfr->task_nextprobe->worker == NULL || - xfr->task_nextprobe->worker == env->worker); - /* normally, nextprobe = startoflease + refresh, - * but if expiry is sooner, use that one. - * after a failure, use the retry timer instead. */ - xfr->task_nextprobe->next_probe = *env->now; - if(xfr->lease_time && !failure) - xfr->task_nextprobe->next_probe = xfr->lease_time; - - if(!failure) { - xfr->task_nextprobe->backoff = 0; - } else { - if(xfr->task_nextprobe->backoff == 0) - xfr->task_nextprobe->backoff = 3; - else xfr->task_nextprobe->backoff *= 2; - if(xfr->task_nextprobe->backoff > AUTH_TRANSFER_MAX_BACKOFF) - xfr->task_nextprobe->backoff = - AUTH_TRANSFER_MAX_BACKOFF; - } - - if(xfr->have_zone) { - time_t wait = xfr->refresh; - if(failure) wait = xfr->retry; - if(xfr->expiry < wait) - xfr->task_nextprobe->next_probe += xfr->expiry; - else xfr->task_nextprobe->next_probe += wait; - if(failure) - xfr->task_nextprobe->next_probe += - xfr->task_nextprobe->backoff; - /* put the timer exactly on expiry, if possible */ - if(xfr->lease_time && xfr->lease_time+xfr->expiry < - xfr->task_nextprobe->next_probe && - xfr->lease_time+xfr->expiry > *env->now) - xfr->task_nextprobe->next_probe = - xfr->lease_time+xfr->expiry; - } else { - xfr->task_nextprobe->next_probe += - xfr->task_nextprobe->backoff; - } - - if(!xfr->task_nextprobe->timer) { - xfr->task_nextprobe->timer = comm_timer_create( - env->worker_base, auth_xfer_timer, xfr); - if(!xfr->task_nextprobe->timer) { - /* failed to malloc memory. likely zone transfer - * also fails for that. skip the timeout */ - char zname[255+1]; - dname_str(xfr->name, zname); - log_err("cannot allocate timer, no refresh for %s", - zname); - return; - } - } - xfr->task_nextprobe->worker = env->worker; - xfr->task_nextprobe->env = env; - if(*(xfr->task_nextprobe->env->now) <= xfr->task_nextprobe->next_probe) - tv.tv_sec = xfr->task_nextprobe->next_probe - - *(xfr->task_nextprobe->env->now); - else tv.tv_sec = 0; - if(tv.tv_sec != 0 && lookup_only && xfr->task_probe->masters) { - /* don't lookup_only, if lookup timeout is 0 anyway, - * or if we don't have masters to lookup */ - tv.tv_sec = 0; - if(xfr->task_probe->worker == NULL) - xfr->task_probe->only_lookup = 1; - } - if(verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(xfr->name, zname); - verbose(VERB_ALGO, "auth zone %s timeout in %d seconds", - zname, (int)tv.tv_sec); - } - tv.tv_usec = 0; - comm_timer_set(xfr->task_nextprobe->timer, &tv); -} - -/** initial pick up of worker timeouts, ties events to worker event loop */ -void -auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env) -{ - struct auth_xfer* x; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(x, struct auth_xfer*, &az->xtree) { - lock_basic_lock(&x->lock); - /* set lease_time, because we now have timestamp in env, - * (not earlier during startup and apply_cfg), and this - * notes the start time when the data was acquired */ - if(x->have_zone) - x->lease_time = *env->now; - if(x->task_nextprobe && x->task_nextprobe->worker == NULL) { - xfr_set_timeout(x, env, 0, 1); - } - lock_basic_unlock(&x->lock); - } - lock_rw_unlock(&az->lock); -} - -void auth_zones_cleanup(struct auth_zones* az) -{ - struct auth_xfer* x; - lock_rw_wrlock(&az->lock); - RBTREE_FOR(x, struct auth_xfer*, &az->xtree) { - lock_basic_lock(&x->lock); - if(x->task_nextprobe && x->task_nextprobe->worker != NULL) { - xfr_nextprobe_disown(x); - } - if(x->task_probe && x->task_probe->worker != NULL) { - xfr_probe_disown(x); - } - if(x->task_transfer && x->task_transfer->worker != NULL) { - auth_chunks_delete(x->task_transfer); - xfr_transfer_disown(x); - } - lock_basic_unlock(&x->lock); - } - lock_rw_unlock(&az->lock); -} - -/** - * malloc the xfer and tasks - * @param z: auth_zone with name of zone. - */ -static struct auth_xfer* -auth_xfer_new(struct auth_zone* z) -{ - struct auth_xfer* xfr; - xfr = (struct auth_xfer*)calloc(1, sizeof(*xfr)); - if(!xfr) return NULL; - xfr->name = memdup(z->name, z->namelen); - if(!xfr->name) { - free(xfr); - return NULL; - } - xfr->node.key = xfr; - xfr->namelen = z->namelen; - xfr->namelabs = z->namelabs; - xfr->dclass = z->dclass; - - xfr->task_nextprobe = (struct auth_nextprobe*)calloc(1, - sizeof(struct auth_nextprobe)); - if(!xfr->task_nextprobe) { - free(xfr->name); - free(xfr); - return NULL; - } - xfr->task_probe = (struct auth_probe*)calloc(1, - sizeof(struct auth_probe)); - if(!xfr->task_probe) { - free(xfr->task_nextprobe); - free(xfr->name); - free(xfr); - return NULL; - } - xfr->task_transfer = (struct auth_transfer*)calloc(1, - sizeof(struct auth_transfer)); - if(!xfr->task_transfer) { - free(xfr->task_probe); - free(xfr->task_nextprobe); - free(xfr->name); - free(xfr); - return NULL; - } - - lock_basic_init(&xfr->lock); - lock_protect(&xfr->lock, &xfr->name, sizeof(xfr->name)); - lock_protect(&xfr->lock, &xfr->namelen, sizeof(xfr->namelen)); - lock_protect(&xfr->lock, xfr->name, xfr->namelen); - lock_protect(&xfr->lock, &xfr->namelabs, sizeof(xfr->namelabs)); - lock_protect(&xfr->lock, &xfr->dclass, sizeof(xfr->dclass)); - lock_protect(&xfr->lock, &xfr->notify_received, sizeof(xfr->notify_received)); - lock_protect(&xfr->lock, &xfr->notify_serial, sizeof(xfr->notify_serial)); - lock_protect(&xfr->lock, &xfr->zone_expired, sizeof(xfr->zone_expired)); - lock_protect(&xfr->lock, &xfr->have_zone, sizeof(xfr->have_zone)); - lock_protect(&xfr->lock, &xfr->serial, sizeof(xfr->serial)); - lock_protect(&xfr->lock, &xfr->retry, sizeof(xfr->retry)); - lock_protect(&xfr->lock, &xfr->refresh, sizeof(xfr->refresh)); - lock_protect(&xfr->lock, &xfr->expiry, sizeof(xfr->expiry)); - lock_protect(&xfr->lock, &xfr->lease_time, sizeof(xfr->lease_time)); - lock_protect(&xfr->lock, &xfr->task_nextprobe->worker, - sizeof(xfr->task_nextprobe->worker)); - lock_protect(&xfr->lock, &xfr->task_probe->worker, - sizeof(xfr->task_probe->worker)); - lock_protect(&xfr->lock, &xfr->task_transfer->worker, - sizeof(xfr->task_transfer->worker)); - lock_basic_lock(&xfr->lock); - return xfr; -} - -/** Create auth_xfer structure. - * This populates the have_zone, soa values, and so on times. - * and sets the timeout, if a zone transfer is needed a short timeout is set. - * For that the auth_zone itself must exist (and read in zonefile) - * returns false on alloc failure. */ -struct auth_xfer* -auth_xfer_create(struct auth_zones* az, struct auth_zone* z) -{ - struct auth_xfer* xfr; - - /* malloc it */ - xfr = auth_xfer_new(z); - if(!xfr) { - log_err("malloc failure"); - return NULL; - } - /* insert in tree */ - (void)rbtree_insert(&az->xtree, &xfr->node); - return xfr; -} - -/** create new auth_master structure */ -static struct auth_master* -auth_master_new(struct auth_master*** list) -{ - struct auth_master *m; - m = (struct auth_master*)calloc(1, sizeof(*m)); - if(!m) { - log_err("malloc failure"); - return NULL; - } - /* set first pointer to m, or next pointer of previous element to m */ - (**list) = m; - /* store m's next pointer as future point to store at */ - (*list) = &(m->next); - return m; -} - -/** dup_prefix : create string from initial part of other string, malloced */ -static char* -dup_prefix(char* str, size_t num) -{ - char* result; - size_t len = strlen(str); - if(len < num) num = len; /* not more than strlen */ - result = (char*)malloc(num+1); - if(!result) { - log_err("malloc failure"); - return result; - } - memmove(result, str, num); - result[num] = 0; - return result; -} - -/** dup string and print error on error */ -static char* -dup_all(char* str) -{ - char* result = strdup(str); - if(!result) { - log_err("malloc failure"); - return NULL; - } - return result; -} - -/** find first of two characters */ -static char* -str_find_first_of_chars(char* s, char a, char b) -{ - char* ra = strchr(s, a); - char* rb = strchr(s, b); - if(!ra) return rb; - if(!rb) return ra; - if(ra < rb) return ra; - return rb; -} - -/** parse URL into host and file parts, false on malloc or parse error */ -static int -parse_url(char* url, char** host, char** file, int* port, int* ssl) -{ - char* p = url; - /* parse http://www.example.com/file.htm - * or http://127.0.0.1 (index.html) - * or https://[::1@1234]/a/b/c/d */ - *ssl = 1; - *port = AUTH_HTTPS_PORT; - - /* parse http:// or https:// */ - if(strncmp(p, "http://", 7) == 0) { - p += 7; - *ssl = 0; - *port = AUTH_HTTP_PORT; - } else if(strncmp(p, "https://", 8) == 0) { - p += 8; - } else if(strstr(p, "://") && strchr(p, '/') > strstr(p, "://") && - strchr(p, ':') >= strstr(p, "://")) { - char* uri = dup_prefix(p, (size_t)(strstr(p, "://")-p)); - log_err("protocol %s:// not supported (for url %s)", - uri?uri:"", p); - free(uri); - return 0; - } - - /* parse hostname part */ - if(p[0] == '[') { - char* end = strchr(p, ']'); - p++; /* skip over [ */ - if(end) { - *host = dup_prefix(p, (size_t)(end-p)); - if(!*host) return 0; - p = end+1; /* skip over ] */ - } else { - *host = dup_all(p); - if(!*host) return 0; - p = end; - } - } else { - char* end = str_find_first_of_chars(p, ':', '/'); - if(end) { - *host = dup_prefix(p, (size_t)(end-p)); - if(!*host) return 0; - } else { - *host = dup_all(p); - if(!*host) return 0; - } - p = end; /* at next : or / or NULL */ - } - - /* parse port number */ - if(p && p[0] == ':') { - char* end = NULL; - *port = strtol(p+1, &end, 10); - p = end; - } - - /* parse filename part */ - while(p && *p == '/') - p++; - if(!p || p[0] == 0) - *file = strdup("/"); - else *file = strdup(p); - if(!*file) { - log_err("malloc failure"); - return 0; - } - return 1; -} - -int -xfer_set_masters(struct auth_master** list, struct config_auth* c, - int with_http) -{ - struct auth_master* m; - struct config_strlist* p; - /* list points to the first, or next pointer for the new element */ - while(*list) { - list = &( (*list)->next ); - } - if(with_http) - for(p = c->urls; p; p = p->next) { - m = auth_master_new(&list); - if(!m) return 0; - m->http = 1; - if(!parse_url(p->str, &m->host, &m->file, &m->port, &m->ssl)) - return 0; - } - for(p = c->masters; p; p = p->next) { - m = auth_master_new(&list); - if(!m) return 0; - m->ixfr = 1; /* this flag is not configurable */ - m->host = strdup(p->str); - if(!m->host) { - log_err("malloc failure"); - return 0; - } - } - for(p = c->allow_notify; p; p = p->next) { - m = auth_master_new(&list); - if(!m) return 0; - m->allow_notify = 1; - m->host = strdup(p->str); - if(!m->host) { - log_err("malloc failure"); - return 0; - } - } - return 1; -} - -#define SERIAL_BITS 32 -int -compare_serial(uint32_t a, uint32_t b) -{ - const uint32_t cutoff = ((uint32_t) 1 << (SERIAL_BITS - 1)); - - if (a == b) { - return 0; - } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) { - return -1; - } else { - return 1; - } -} - -int zonemd_hashalgo_supported(int hashalgo) -{ - if(hashalgo == ZONEMD_ALGO_SHA384) return 1; - if(hashalgo == ZONEMD_ALGO_SHA512) return 1; - return 0; -} - -int zonemd_scheme_supported(int scheme) -{ - if(scheme == ZONEMD_SCHEME_SIMPLE) return 1; - return 0; -} - -/** initialize hash for hashing with zonemd hash algo */ -static struct secalgo_hash* zonemd_digest_init(int hashalgo, char** reason) -{ - struct secalgo_hash *h; - if(hashalgo == ZONEMD_ALGO_SHA384) { - /* sha384 */ - h = secalgo_hash_create_sha384(); - if(!h) - *reason = "digest sha384 could not be created"; - return h; - } else if(hashalgo == ZONEMD_ALGO_SHA512) { - /* sha512 */ - h = secalgo_hash_create_sha512(); - if(!h) - *reason = "digest sha512 could not be created"; - return h; - } - /* unknown hash algo */ - *reason = "unsupported algorithm"; - return NULL; -} - -/** update the hash for zonemd */ -static int zonemd_digest_update(int hashalgo, struct secalgo_hash* h, - uint8_t* data, size_t len, char** reason) -{ - if(hashalgo == ZONEMD_ALGO_SHA384) { - if(!secalgo_hash_update(h, data, len)) { - *reason = "digest sha384 failed"; - return 0; - } - return 1; - } else if(hashalgo == ZONEMD_ALGO_SHA512) { - if(!secalgo_hash_update(h, data, len)) { - *reason = "digest sha512 failed"; - return 0; - } - return 1; - } - /* unknown hash algo */ - *reason = "unsupported algorithm"; - return 0; -} - -/** finish the hash for zonemd */ -static int zonemd_digest_finish(int hashalgo, struct secalgo_hash* h, - uint8_t* result, size_t hashlen, size_t* resultlen, char** reason) -{ - if(hashalgo == ZONEMD_ALGO_SHA384) { - if(hashlen < 384/8) { - *reason = "digest buffer too small for sha384"; - return 0; - } - if(!secalgo_hash_final(h, result, hashlen, resultlen)) { - *reason = "digest sha384 finish failed"; - return 0; - } - return 1; - } else if(hashalgo == ZONEMD_ALGO_SHA512) { - if(hashlen < 512/8) { - *reason = "digest buffer too small for sha512"; - return 0; - } - if(!secalgo_hash_final(h, result, hashlen, resultlen)) { - *reason = "digest sha512 finish failed"; - return 0; - } - return 1; - } - /* unknown algo */ - *reason = "unsupported algorithm"; - return 0; -} - -/** add rrsets from node to the list */ -static size_t authdata_rrsets_to_list(struct auth_rrset** array, - size_t arraysize, struct auth_rrset* first) -{ - struct auth_rrset* rrset = first; - size_t num = 0; - while(rrset) { - if(num >= arraysize) - return num; - array[num] = rrset; - num++; - rrset = rrset->next; - } - return num; -} - -/** compare rr list entries */ -static int rrlist_compare(const void* arg1, const void* arg2) -{ - struct auth_rrset* r1 = *(struct auth_rrset**)arg1; - struct auth_rrset* r2 = *(struct auth_rrset**)arg2; - uint16_t t1, t2; - if(r1 == NULL) t1 = LDNS_RR_TYPE_RRSIG; - else t1 = r1->type; - if(r2 == NULL) t2 = LDNS_RR_TYPE_RRSIG; - else t2 = r2->type; - if(t1 < t2) - return -1; - if(t1 > t2) - return 1; - return 0; -} - -/** add type RRSIG to rr list if not one there already, - * this is to perform RRSIG collate processing at that point. */ -static void addrrsigtype_if_needed(struct auth_rrset** array, - size_t arraysize, size_t* rrnum, struct auth_data* node) -{ - if(az_domain_rrset(node, LDNS_RR_TYPE_RRSIG)) - return; /* already one there */ - if((*rrnum) >= arraysize) - return; /* array too small? */ - array[*rrnum] = NULL; /* nothing there, but need entry in list */ - (*rrnum)++; -} - -/** collate the RRs in an RRset using the simple scheme */ -static int zonemd_simple_rrset(struct auth_zone* z, int hashalgo, - struct secalgo_hash* h, struct auth_data* node, - struct auth_rrset* rrset, struct regional* region, - struct sldns_buffer* buf, char** reason) -{ - /* canonicalize */ - struct ub_packed_rrset_key key; - memset(&key, 0, sizeof(key)); - key.entry.key = &key; - key.entry.data = rrset->data; - key.rk.dname = node->name; - key.rk.dname_len = node->namelen; - key.rk.type = htons(rrset->type); - key.rk.rrset_class = htons(z->dclass); - if(!rrset_canonicalize_to_buffer(region, buf, &key)) { - *reason = "out of memory"; - return 0; - } - regional_free_all(region); - - /* hash */ - if(!zonemd_digest_update(hashalgo, h, sldns_buffer_begin(buf), - sldns_buffer_limit(buf), reason)) { - return 0; - } - return 1; -} - -/** count number of RRSIGs in a domain name rrset list */ -static size_t zonemd_simple_count_rrsig(struct auth_rrset* rrset, - struct auth_rrset** rrlist, size_t rrnum, - struct auth_zone* z, struct auth_data* node) -{ - size_t i, count = 0; - if(rrset) { - size_t j; - for(j = 0; jdata->count; j++) { - if(rrsig_rdata_get_type_covered(rrset->data-> - rr_data[j], rrset->data->rr_len[j]) == - LDNS_RR_TYPE_ZONEMD && - query_dname_compare(z->name, node->name)==0) { - /* omit RRSIGs over type ZONEMD at apex */ - continue; - } - count++; - } - } - for(i=0; itype == LDNS_RR_TYPE_ZONEMD && - query_dname_compare(z->name, node->name)==0) { - /* omit RRSIGs over type ZONEMD at apex */ - continue; - } - count += (rrlist[i]?rrlist[i]->data->rrsig_count:0); - } - return count; -} - -/** allocate sparse rrset data for the number of entries in tepm region */ -static int zonemd_simple_rrsig_allocs(struct regional* region, - struct packed_rrset_data* data, size_t count) -{ - data->rr_len = regional_alloc(region, sizeof(*data->rr_len) * count); - if(!data->rr_len) { - return 0; - } - data->rr_ttl = regional_alloc(region, sizeof(*data->rr_ttl) * count); - if(!data->rr_ttl) { - return 0; - } - data->rr_data = regional_alloc(region, sizeof(*data->rr_data) * count); - if(!data->rr_data) { - return 0; - } - return 1; -} - -/** add the RRSIGs from the rrs in the domain into the data */ -static void add_rrlist_rrsigs_into_data(struct packed_rrset_data* data, - size_t* done, struct auth_rrset** rrlist, size_t rrnum, - struct auth_zone* z, struct auth_data* node) -{ - size_t i; - for(i=0; itype == LDNS_RR_TYPE_ZONEMD && - query_dname_compare(z->name, node->name)==0) { - /* omit RRSIGs over type ZONEMD at apex */ - continue; - } - for(j = 0; jdata->rrsig_count; j++) { - data->rr_len[*done] = rrlist[i]->data->rr_len[rrlist[i]->data->count + j]; - data->rr_ttl[*done] = rrlist[i]->data->rr_ttl[rrlist[i]->data->count + j]; - /* reference the rdata in the rrset, no need to - * copy it, it is no longer needed at the end of - * the routine */ - data->rr_data[*done] = rrlist[i]->data->rr_data[rrlist[i]->data->count + j]; - (*done)++; - } - } -} - -static void add_rrset_into_data(struct packed_rrset_data* data, - size_t* done, struct auth_rrset* rrset, - struct auth_zone* z, struct auth_data* node) -{ - if(rrset) { - size_t j; - for(j = 0; jdata->count; j++) { - if(rrsig_rdata_get_type_covered(rrset->data-> - rr_data[j], rrset->data->rr_len[j]) == - LDNS_RR_TYPE_ZONEMD && - query_dname_compare(z->name, node->name)==0) { - /* omit RRSIGs over type ZONEMD at apex */ - continue; - } - data->rr_len[*done] = rrset->data->rr_len[j]; - data->rr_ttl[*done] = rrset->data->rr_ttl[j]; - /* reference the rdata in the rrset, no need to - * copy it, it is no longer need at the end of - * the routine */ - data->rr_data[*done] = rrset->data->rr_data[j]; - (*done)++; - } - } -} - -/** collate the RRSIGs using the simple scheme */ -static int zonemd_simple_rrsig(struct auth_zone* z, int hashalgo, - struct secalgo_hash* h, struct auth_data* node, - struct auth_rrset* rrset, struct auth_rrset** rrlist, size_t rrnum, - struct regional* region, struct sldns_buffer* buf, char** reason) -{ - /* the rrset pointer can be NULL, this means it is type RRSIG and - * there is no ordinary type RRSIG there. The RRSIGs are stored - * with the RRsets in their data. - * - * The RRset pointer can be nonNULL. This happens if there is - * no RR that is covered by the RRSIG for the domain. Then this - * RRSIG RR is stored in an rrset of type RRSIG. The other RRSIGs - * are stored in the rrset entries for the RRs in the rr list for - * the domain node. We need to collate the rrset's data, if any, and - * the rrlist's rrsigs */ - /* if this is the apex, omit RRSIGs that cover type ZONEMD */ - /* build rrsig rrset */ - size_t done = 0; - struct ub_packed_rrset_key key; - struct packed_rrset_data data; - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - key.entry.key = &key; - key.entry.data = &data; - key.rk.dname = node->name; - key.rk.dname_len = node->namelen; - key.rk.type = htons(LDNS_RR_TYPE_RRSIG); - key.rk.rrset_class = htons(z->dclass); - data.count = zonemd_simple_count_rrsig(rrset, rrlist, rrnum, z, node); - if(!zonemd_simple_rrsig_allocs(region, &data, data.count)) { - *reason = "out of memory"; - regional_free_all(region); - return 0; - } - /* all the RRSIGs stored in the other rrsets for this domain node */ - add_rrlist_rrsigs_into_data(&data, &done, rrlist, rrnum, z, node); - /* plus the RRSIGs stored in an rrset of type RRSIG for this node */ - add_rrset_into_data(&data, &done, rrset, z, node); - - /* canonicalize */ - if(!rrset_canonicalize_to_buffer(region, buf, &key)) { - *reason = "out of memory"; - regional_free_all(region); - return 0; - } - regional_free_all(region); - - /* hash */ - if(!zonemd_digest_update(hashalgo, h, sldns_buffer_begin(buf), - sldns_buffer_limit(buf), reason)) { - return 0; - } - return 1; -} - -/** collate a domain's rrsets using the simple scheme */ -static int zonemd_simple_domain(struct auth_zone* z, int hashalgo, - struct secalgo_hash* h, struct auth_data* node, - struct regional* region, struct sldns_buffer* buf, char** reason) -{ - const size_t rrlistsize = 65536; - struct auth_rrset* rrlist[rrlistsize]; - size_t i, rrnum = 0; - /* see if the domain is out of scope, the zone origin, - * that would be omitted */ - if(!dname_subdomain_c(node->name, z->name)) - return 1; /* continue */ - /* loop over the rrsets in ascending order. */ - rrnum = authdata_rrsets_to_list(rrlist, rrlistsize, node->rrsets); - addrrsigtype_if_needed(rrlist, rrlistsize, &rrnum, node); - qsort(rrlist, rrnum, sizeof(*rrlist), rrlist_compare); - for(i=0; itype == LDNS_RR_TYPE_ZONEMD && - query_dname_compare(z->name, node->name) == 0) { - /* omit type ZONEMD at apex */ - continue; - } - if(rrlist[i] == NULL || rrlist[i]->type == - LDNS_RR_TYPE_RRSIG) { - if(!zonemd_simple_rrsig(z, hashalgo, h, node, - rrlist[i], rrlist, rrnum, region, buf, reason)) - return 0; - } else if(!zonemd_simple_rrset(z, hashalgo, h, node, - rrlist[i], region, buf, reason)) { - return 0; - } - } - return 1; -} - -/** collate the zone using the simple scheme */ -static int zonemd_simple_collate(struct auth_zone* z, int hashalgo, - struct secalgo_hash* h, struct regional* region, - struct sldns_buffer* buf, char** reason) -{ - /* our tree is sorted in canonical order, so we can just loop over - * the tree */ - struct auth_data* n; - RBTREE_FOR(n, struct auth_data*, &z->data) { - if(!zonemd_simple_domain(z, hashalgo, h, n, region, buf, - reason)) - return 0; - } - return 1; -} - -int auth_zone_generate_zonemd_hash(struct auth_zone* z, int scheme, - int hashalgo, uint8_t* hash, size_t hashlen, size_t* resultlen, - struct regional* region, struct sldns_buffer* buf, char** reason) -{ - struct secalgo_hash* h = zonemd_digest_init(hashalgo, reason); - if(!h) { - if(!*reason) - *reason = "digest init fail"; - return 0; - } - if(scheme == ZONEMD_SCHEME_SIMPLE) { - if(!zonemd_simple_collate(z, hashalgo, h, region, buf, reason)) { - if(!*reason) *reason = "scheme simple collate fail"; - secalgo_hash_delete(h); - return 0; - } - } - if(!zonemd_digest_finish(hashalgo, h, hash, hashlen, resultlen, - reason)) { - secalgo_hash_delete(h); - *reason = "digest finish fail"; - return 0; - } - secalgo_hash_delete(h); - return 1; -} - -int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme, - int hashalgo, uint8_t* hash, size_t hashlen, struct regional* region, - struct sldns_buffer* buf, char** reason) -{ - uint8_t gen[512]; - size_t genlen = 0; - *reason = NULL; - if(!zonemd_hashalgo_supported(hashalgo)) { - /* allow it */ - *reason = "unsupported algorithm"; - return 1; - } - if(!zonemd_scheme_supported(scheme)) { - /* allow it */ - *reason = "unsupported scheme"; - return 1; - } - if(hashlen < 12) { - /* the ZONEMD draft requires digests to fail if too small */ - *reason = "digest length too small, less than 12"; - return 0; - } - /* generate digest */ - if(!auth_zone_generate_zonemd_hash(z, scheme, hashalgo, gen, - sizeof(gen), &genlen, region, buf, reason)) { - /* reason filled in by zonemd hash routine */ - return 0; - } - /* check digest length */ - if(hashlen != genlen) { - *reason = "incorrect digest length"; - if(verbosity >= VERB_ALGO) { - verbose(VERB_ALGO, "zonemd scheme=%d hashalgo=%d", - scheme, hashalgo); - log_hex("ZONEMD should be ", gen, genlen); - log_hex("ZONEMD to check is", hash, hashlen); - } - return 0; - } - /* check digest */ - if(memcmp(hash, gen, genlen) != 0) { - *reason = "incorrect digest"; - if(verbosity >= VERB_ALGO) { - verbose(VERB_ALGO, "zonemd scheme=%d hashalgo=%d", - scheme, hashalgo); - log_hex("ZONEMD should be ", gen, genlen); - log_hex("ZONEMD to check is", hash, hashlen); - } - return 0; - } - return 1; -} - -/** log auth zone message with zone name in front. */ -static void auth_zone_log(uint8_t* name, enum verbosity_value level, - const char* format, ...) ATTR_FORMAT(printf, 3, 4); -static void auth_zone_log(uint8_t* name, enum verbosity_value level, - const char* format, ...) -{ - va_list args; - va_start(args, format); - if(verbosity >= level) { - char str[255+1]; - char msg[MAXSYSLOGMSGLEN]; - dname_str(name, str); - vsnprintf(msg, sizeof(msg), format, args); - verbose(level, "auth zone %s %s", str, msg); - } - va_end(args); -} - -/** ZONEMD, dnssec verify the rrset with the dnskey */ -static int zonemd_dnssec_verify_rrset(struct auth_zone* z, - struct module_env* env, struct module_stack* mods, - struct ub_packed_rrset_key* dnskey, struct auth_data* node, - struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg) -{ - struct ub_packed_rrset_key pk; - enum sec_status sec; - struct val_env* ve; - int m; - m = modstack_find(mods, "validator"); - if(m == -1) { - auth_zone_log(z->name, VERB_ALGO, "zonemd dnssec verify: have " - "DNSKEY chain of trust, but no validator module"); - return 0; - } - ve = (struct val_env*)env->modinfo[m]; - - memset(&pk, 0, sizeof(pk)); - pk.entry.key = &pk; - pk.entry.data = rrset->data; - pk.rk.dname = node->name; - pk.rk.dname_len = node->namelen; - pk.rk.type = htons(rrset->type); - pk.rk.rrset_class = htons(z->dclass); - if(verbosity >= VERB_ALGO) { - char typestr[32]; - typestr[0]=0; - sldns_wire2str_type_buf(rrset->type, typestr, sizeof(typestr)); - auth_zone_log(z->name, VERB_ALGO, - "zonemd: verify %s RRset with DNSKEY", typestr); - } - sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL, - LDNS_SECTION_ANSWER, NULL); - if(sec == sec_status_secure) { - return 1; - } - if(why_bogus) - auth_zone_log(z->name, VERB_ALGO, "DNSSEC verify was bogus: %s", *why_bogus); - return 0; -} - -/** check for nsec3, the RR with params equal, if bitmap has the type */ -static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo, - size_t iter, uint8_t* salt, size_t saltlen, uint16_t rrtype) -{ - int i, count = (int)nsec3->data->count; - struct ub_packed_rrset_key pk; - memset(&pk, 0, sizeof(pk)); - pk.entry.data = nsec3->data; - for(i=0; idata; - if(nsec_has_type(&pk, LDNS_RR_TYPE_ZONEMD)) { - *reason = "DNSSEC NSEC bitmap says type ZONEMD exists"; - return 0; - } - auth_zone_log(z->name, VERB_ALGO, "zonemd DNSSEC NSEC verification of absence of ZONEMD secure"); - } else { - /* NSEC3 perhaps ? */ - int algo; - size_t iter, saltlen; - uint8_t* salt; - struct auth_rrset* nsec3param = az_domain_rrset(apex, - LDNS_RR_TYPE_NSEC3PARAM); - struct auth_data* match; - struct auth_rrset* nsec3; - if(!nsec3param) { - *reason = "zone has no NSEC information but ZONEMD missing"; - return 0; - } - if(!az_nsec3_param(z, &algo, &iter, &salt, &saltlen)) { - *reason = "zone has no NSEC information but ZONEMD missing"; - return 0; - } - /* find the NSEC3 record */ - match = az_nsec3_find_exact(z, z->name, z->namelen, algo, - iter, salt, saltlen); - if(!match) { - *reason = "zone has no NSEC3 domain for the apex but ZONEMD missing"; - return 0; - } - nsec3 = az_domain_rrset(match, LDNS_RR_TYPE_NSEC3); - if(!nsec3) { - *reason = "zone has no NSEC3 RRset for the apex but ZONEMD missing"; - return 0; - } - /* dnssec verify the NSEC3 */ - if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, match, - nsec3, why_bogus, sigalg)) { - *reason = "DNSSEC verify failed for NSEC3 RRset"; - return 0; - } - /* check type bitmap */ - if(nsec3_of_param_has_type(nsec3, algo, iter, salt, saltlen, - LDNS_RR_TYPE_ZONEMD)) { - *reason = "DNSSEC NSEC3 bitmap says type ZONEMD exists"; - return 0; - } - auth_zone_log(z->name, VERB_ALGO, "zonemd DNSSEC NSEC3 verification of absence of ZONEMD secure"); - } - - return 1; -} - -/** Verify the SOA and ZONEMD DNSSEC signatures. - * return false on failure, reason contains description of failure. */ -static int zonemd_check_dnssec_soazonemd(struct auth_zone* z, - struct module_env* env, struct module_stack* mods, - struct ub_packed_rrset_key* dnskey, struct auth_data* apex, - struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus, - uint8_t* sigalg) -{ - struct auth_rrset* soa; - if(!apex) { - *reason = "zone has no apex domain"; - return 0; - } - soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); - if(!soa) { - *reason = "zone has no SOA RRset"; - return 0; - } - if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, soa, - why_bogus, sigalg)) { - *reason = "DNSSEC verify failed for SOA RRset"; - return 0; - } - if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, - zonemd_rrset, why_bogus, sigalg)) { - *reason = "DNSSEC verify failed for ZONEMD RRset"; - return 0; - } - auth_zone_log(z->name, VERB_ALGO, "zonemd DNSSEC verification of SOA and ZONEMD RRsets secure"); - return 1; -} - -/** - * Fail the ZONEMD verification. - * @param z: auth zone that fails. - * @param env: environment with config, to ignore failure or not. - * @param reason: failure string description. - * @param why_bogus: failure string for DNSSEC verification failure. - * @param result: strdup result in here if not NULL. - */ -static void auth_zone_zonemd_fail(struct auth_zone* z, struct module_env* env, - char* reason, char* why_bogus, char** result) -{ - char zstr[255+1]; - /* if fail: log reason, and depending on config also take action - * and drop the zone, eg. it is gone from memory, set zone_expired */ - dname_str(z->name, zstr); - if(!reason) reason = "verification failed"; - if(result) { - if(why_bogus) { - char res[1024]; - snprintf(res, sizeof(res), "%s: %s", reason, - why_bogus); - *result = strdup(res); - } else { - *result = strdup(reason); - } - if(!*result) log_err("out of memory"); - } else { - log_warn("auth zone %s: ZONEMD verification failed: %s", zstr, reason); - } - - if(env->cfg->zonemd_permissive_mode) { - verbose(VERB_ALGO, "zonemd-permissive-mode enabled, " - "not blocking zone %s", zstr); - return; - } - - /* expired means the zone gives servfail and is not used by - * lookup if fallback_enabled*/ - z->zone_expired = 1; -} - -/** - * Verify the zonemd with DNSSEC and hash check, with given key. - * @param z: auth zone. - * @param env: environment with config and temp buffers. - * @param mods: module stack with validator env for verification. - * @param dnskey: dnskey that we can use, or NULL. If nonnull, the key - * has been verified and is the start of the chain of trust. - * @param is_insecure: if true, the dnskey is not used, the zone is insecure. - * And dnssec is not used. It is DNSSEC secure insecure or not under - * a trust anchor. - * @param sigalg: if nonNULL provide algorithm downgrade protection. - * Otherwise one algorithm is enough. Must have space of ALGO_NEEDS_MAX+1. - * @param result: if not NULL result reason copied here. - */ -static void -auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env, - struct module_stack* mods, struct ub_packed_rrset_key* dnskey, - int is_insecure, char** result, uint8_t* sigalg) -{ - char* reason = NULL, *why_bogus = NULL; - struct auth_data* apex = NULL; - struct auth_rrset* zonemd_rrset = NULL; - int zonemd_absent = 0, zonemd_absence_dnssecok = 0; - - /* see if ZONEMD is present or absent. */ - apex = az_find_name(z, z->name, z->namelen); - if(!apex) { - zonemd_absent = 1; - } else { - zonemd_rrset = az_domain_rrset(apex, LDNS_RR_TYPE_ZONEMD); - if(!zonemd_rrset || zonemd_rrset->data->count==0) { - zonemd_absent = 1; - zonemd_rrset = NULL; - } - } - - /* if no DNSSEC, done. */ - /* if no ZONEMD, and DNSSEC, use DNSKEY to verify NSEC or NSEC3 for - * zone apex. Check ZONEMD bit is turned off or else fail */ - /* if ZONEMD, and DNSSEC, check DNSSEC signature on SOA and ZONEMD, - * or else fail */ - if(!dnskey && !is_insecure) { - auth_zone_zonemd_fail(z, env, "DNSKEY missing", NULL, result); - return; - } else if(!zonemd_rrset && dnskey && !is_insecure) { - /* fetch, DNSSEC verify, and check NSEC/NSEC3 */ - if(!zonemd_check_dnssec_absence(z, env, mods, dnskey, apex, - &reason, &why_bogus, sigalg)) { - auth_zone_zonemd_fail(z, env, reason, why_bogus, result); - return; - } - zonemd_absence_dnssecok = 1; - } else if(zonemd_rrset && dnskey && !is_insecure) { - /* check DNSSEC verify of SOA and ZONEMD */ - if(!zonemd_check_dnssec_soazonemd(z, env, mods, dnskey, apex, - zonemd_rrset, &reason, &why_bogus, sigalg)) { - auth_zone_zonemd_fail(z, env, reason, why_bogus, result); - return; - } - } - - if(zonemd_absent && z->zonemd_reject_absence) { - auth_zone_zonemd_fail(z, env, "ZONEMD absent and that is not allowed by config", NULL, result); - return; - } - if(zonemd_absent && zonemd_absence_dnssecok) { - auth_zone_log(z->name, VERB_ALGO, "DNSSEC verified nonexistence of ZONEMD"); - if(result) { - *result = strdup("DNSSEC verified nonexistence of ZONEMD"); - if(!*result) log_err("out of memory"); - } - return; - } - if(zonemd_absent) { - auth_zone_log(z->name, VERB_ALGO, "no ZONEMD present"); - if(result) { - *result = strdup("no ZONEMD present"); - if(!*result) log_err("out of memory"); - } - return; - } - - /* check ZONEMD checksum and report or else fail. */ - if(!auth_zone_zonemd_check_hash(z, env, &reason)) { - auth_zone_zonemd_fail(z, env, reason, NULL, result); - return; - } - - /* success! log the success */ - if(reason) - auth_zone_log(z->name, VERB_ALGO, "ZONEMD %s", reason); - else auth_zone_log(z->name, VERB_ALGO, "ZONEMD verification successful"); - if(result) { - if(reason) - *result = strdup(reason); - else *result = strdup("ZONEMD verification successful"); - if(!*result) log_err("out of memory"); - } -} - -/** - * verify the zone DNSKEY rrset from the trust anchor - * This is possible because the anchor is for the zone itself, and can - * thus apply straight to the zone DNSKEY set. - * @param z: the auth zone. - * @param env: environment with time and temp buffers. - * @param mods: module stack for validator environment for dnssec validation. - * @param anchor: trust anchor to use - * @param is_insecure: returned, true if the zone is securely insecure. - * @param why_bogus: if the routine fails, returns the failure reason. - * @param keystorage: where to store the ub_packed_rrset_key that is created - * on success. A pointer to it is returned on success. - * @return the dnskey RRset, reference to zone data and keystorage, or - * NULL on failure. - */ -static struct ub_packed_rrset_key* -zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env, - struct module_stack* mods, struct trust_anchor* anchor, - int* is_insecure, char** why_bogus, - struct ub_packed_rrset_key* keystorage) -{ - struct auth_data* apex; - struct auth_rrset* dnskey_rrset; - enum sec_status sec; - struct val_env* ve; - int m; - - apex = az_find_name(z, z->name, z->namelen); - if(!apex) { - *why_bogus = "have trust anchor, but zone has no apex domain for DNSKEY"; - return 0; - } - dnskey_rrset = az_domain_rrset(apex, LDNS_RR_TYPE_DNSKEY); - if(!dnskey_rrset || dnskey_rrset->data->count==0) { - *why_bogus = "have trust anchor, but zone has no DNSKEY"; - return 0; - } - - m = modstack_find(mods, "validator"); - if(m == -1) { - *why_bogus = "have trust anchor, but no validator module"; - return 0; - } - ve = (struct val_env*)env->modinfo[m]; - - memset(keystorage, 0, sizeof(*keystorage)); - keystorage->entry.key = keystorage; - keystorage->entry.data = dnskey_rrset->data; - keystorage->rk.dname = apex->name; - keystorage->rk.dname_len = apex->namelen; - keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY); - keystorage->rk.rrset_class = htons(z->dclass); - auth_zone_log(z->name, VERB_QUERY, - "zonemd: verify DNSKEY RRset with trust anchor"); - sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset, - anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL); - regional_free_all(env->scratch); - if(sec == sec_status_secure) { - /* success */ - *is_insecure = 0; - return keystorage; - } else if(sec == sec_status_insecure) { - /* insecure */ - *is_insecure = 1; - } else { - /* bogus */ - *is_insecure = 0; - auth_zone_log(z->name, VERB_ALGO, - "zonemd: verify DNSKEY RRset with trust anchor failed: %s", *why_bogus); - } - return NULL; -} - -/** verify the DNSKEY from the zone with looked up DS record */ -static struct ub_packed_rrset_key* -auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z, - struct module_env* env, struct module_stack* mods, - struct ub_packed_rrset_key* ds, int* is_insecure, char** why_bogus, - struct ub_packed_rrset_key* keystorage, uint8_t* sigalg) -{ - struct auth_data* apex; - struct auth_rrset* dnskey_rrset; - enum sec_status sec; - struct val_env* ve; - int m; - - /* fetch DNSKEY from zone data */ - apex = az_find_name(z, z->name, z->namelen); - if(!apex) { - *why_bogus = "in verifywithDS, zone has no apex"; - return NULL; - } - dnskey_rrset = az_domain_rrset(apex, LDNS_RR_TYPE_DNSKEY); - if(!dnskey_rrset || dnskey_rrset->data->count==0) { - *why_bogus = "in verifywithDS, zone has no DNSKEY"; - return NULL; - } - - m = modstack_find(mods, "validator"); - if(m == -1) { - *why_bogus = "in verifywithDS, have no validator module"; - return NULL; - } - ve = (struct val_env*)env->modinfo[m]; - - memset(keystorage, 0, sizeof(*keystorage)); - keystorage->entry.key = keystorage; - keystorage->entry.data = dnskey_rrset->data; - keystorage->rk.dname = apex->name; - keystorage->rk.dname_len = apex->namelen; - keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY); - keystorage->rk.rrset_class = htons(z->dclass); - auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS"); - sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg, - why_bogus, NULL, NULL); - regional_free_all(env->scratch); - if(sec == sec_status_secure) { - /* success */ - return keystorage; - } else if(sec == sec_status_insecure) { - /* insecure */ - *is_insecure = 1; - } else { - /* bogus */ - *is_insecure = 0; - if(*why_bogus == NULL) - *why_bogus = "verify failed"; - auth_zone_log(z->name, VERB_ALGO, - "zonemd: verify DNSKEY RRset with DS failed: %s", - *why_bogus); - } - return NULL; -} - -/** callback for ZONEMD lookup of DNSKEY */ -void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, - enum sec_status sec, char* why_bogus, int ATTR_UNUSED(was_ratelimited)) -{ - struct auth_zone* z = (struct auth_zone*)arg; - struct module_env* env; - char* reason = NULL, *ds_bogus = NULL, *typestr="DNSKEY"; - struct ub_packed_rrset_key* dnskey = NULL, *ds = NULL; - int is_insecure = 0, downprot; - struct ub_packed_rrset_key keystorage; - uint8_t sigalg[ALGO_NEEDS_MAX+1]; - - lock_rw_wrlock(&z->lock); - env = z->zonemd_callback_env; - /* release the env variable so another worker can pick up the - * ZONEMD verification task if it wants to */ - z->zonemd_callback_env = NULL; - if(!env || env->outnet->want_to_quit || z->zone_deleted) { - lock_rw_unlock(&z->lock); - return; /* stop on quit */ - } - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DS) - typestr = "DS"; - downprot = env->cfg->harden_algo_downgrade; - - /* process result */ - if(sec == sec_status_bogus) { - reason = why_bogus; - if(!reason) { - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) - reason = "lookup of DNSKEY was bogus"; - else reason = "lookup of DS was bogus"; - } - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was bogus: %s", typestr, reason); - } else if(rcode == LDNS_RCODE_NOERROR) { - uint16_t wanted_qtype = z->zonemd_callback_qtype; - struct regional* temp = env->scratch; - struct query_info rq; - struct reply_info* rep; - memset(&rq, 0, sizeof(rq)); - rep = parse_reply_in_temp_region(buf, temp, &rq); - if(rep && rq.qtype == wanted_qtype && - query_dname_compare(z->name, rq.qname) == 0 && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) { - /* parsed successfully */ - struct ub_packed_rrset_key* answer = - reply_find_answer_rrset(&rq, rep); - if(answer && sec == sec_status_secure) { - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) - dnskey = answer; - else ds = answer; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was secure", typestr); - } else if(sec == sec_status_secure && !answer) { - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s has no content, but is secure, treat as insecure", typestr); - } else if(sec == sec_status_insecure) { - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was insecure", typestr); - } else if(sec == sec_status_indeterminate) { - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was indeterminate, treat as insecure", typestr); - } else { - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s has nodata", typestr); - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) - reason = "lookup of DNSKEY has nodata"; - else reason = "lookup of DS has nodata"; - } - } else if(rep && rq.qtype == wanted_qtype && - query_dname_compare(z->name, rq.qname) == 0 && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN && - sec == sec_status_secure) { - /* secure nxdomain, so the zone is like some RPZ zone - * that does not exist in the wider internet, with - * a secure nxdomain answer outside of it. So we - * treat the zonemd zone without a dnssec chain of - * trust, as insecure. */ - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was secure NXDOMAIN, treat as insecure", typestr); - } else if(rep && rq.qtype == wanted_qtype && - query_dname_compare(z->name, rq.qname) == 0 && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN && - sec == sec_status_insecure) { - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was insecure NXDOMAIN, treat as insecure", typestr); - } else if(rep && rq.qtype == wanted_qtype && - query_dname_compare(z->name, rq.qname) == 0 && - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN && - sec == sec_status_indeterminate) { - is_insecure = 1; - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s was indeterminate NXDOMAIN, treat as insecure", typestr); - } else { - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s has no answer", typestr); - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) - reason = "lookup of DNSKEY has no answer"; - else reason = "lookup of DS has no answer"; - } - } else { - auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of %s failed", typestr); - if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) - reason = "lookup of DNSKEY failed"; - else reason = "lookup of DS failed"; - } - - if(!reason && !is_insecure && !dnskey && ds) { - dnskey = auth_zone_verify_zonemd_key_with_ds(z, env, - &env->mesh->mods, ds, &is_insecure, &ds_bogus, - &keystorage, downprot?sigalg:NULL); - if(!dnskey && !is_insecure && !reason) - reason = "DNSKEY verify with DS failed"; - } - - if(reason) { - auth_zone_zonemd_fail(z, env, reason, ds_bogus, NULL); - lock_rw_unlock(&z->lock); - return; - } - - auth_zone_verify_zonemd_with_key(z, env, &env->mesh->mods, dnskey, - is_insecure, NULL, downprot?sigalg:NULL); - regional_free_all(env->scratch); - lock_rw_unlock(&z->lock); -} - -/** lookup DNSKEY for ZONEMD verification */ -static int -zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) -{ - struct query_info qinfo; - uint16_t qflags = BIT_RD; - struct edns_data edns; - sldns_buffer* buf = env->scratch_buffer; - int fetch_ds = 0; - - if(!z->fallback_enabled) { - /* we cannot actually get the DNSKEY, because it is in the - * zone we have ourselves, and it is not served yet - * (possibly), so fetch type DS */ - fetch_ds = 1; - } - if(z->zonemd_callback_env) { - /* another worker is already working on the callback - * for the DNSKEY lookup for ZONEMD verification. - * We do not also have to do ZONEMD verification, let that - * worker do it */ - auth_zone_log(z->name, VERB_ALGO, - "zonemd needs lookup of %s and that already is worked on by another worker", (fetch_ds?"DS":"DNSKEY")); - return 1; - } - - /* use mesh_new_callback to lookup the DNSKEY, - * and then wait for them to be looked up (in cache, or query) */ - qinfo.qname_len = z->namelen; - qinfo.qname = z->name; - qinfo.qclass = z->dclass; - if(fetch_ds) - qinfo.qtype = LDNS_RR_TYPE_DS; - else qinfo.qtype = LDNS_RR_TYPE_DNSKEY; - qinfo.local_alias = NULL; - if(verbosity >= VERB_ALGO) { - char buf1[512]; - char buf2[LDNS_MAX_DOMAINLEN+1]; - dname_str(z->name, buf2); - snprintf(buf1, sizeof(buf1), "auth zone %s: lookup %s " - "for zonemd verification", buf2, - (fetch_ds?"DS":"DNSKEY")); - log_query_info(VERB_ALGO, buf1, &qinfo); - } - edns.edns_present = 1; - edns.ext_rcode = 0; - edns.edns_version = 0; - edns.bits = EDNS_DO; - edns.opt_list_in = NULL; - edns.opt_list_out = NULL; - edns.opt_list_inplace_cb_out = NULL; - if(sldns_buffer_capacity(buf) < 65535) - edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); - else edns.udp_size = 65535; - - /* store the worker-specific module env for the callback. - * We can then reference this when the callback executes */ - z->zonemd_callback_env = env; - z->zonemd_callback_qtype = qinfo.qtype; - /* the callback can be called straight away */ - lock_rw_unlock(&z->lock); - if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &auth_zonemd_dnskey_lookup_callback, z, 0)) { - lock_rw_wrlock(&z->lock); - log_err("out of memory lookup of %s for zonemd", - (fetch_ds?"DS":"DNSKEY")); - return 0; - } - lock_rw_wrlock(&z->lock); - return 1; -} - -void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env, - struct module_stack* mods, char** result, int offline, int only_online) -{ - char* reason = NULL, *why_bogus = NULL; - struct trust_anchor* anchor = NULL; - struct ub_packed_rrset_key* dnskey = NULL; - struct ub_packed_rrset_key keystorage; - int is_insecure = 0; - /* verify the ZONEMD if present. - * If not present check if absence is allowed by DNSSEC */ - if(!z->zonemd_check) - return; - if(z->data.count == 0) - return; /* no data */ - - /* if zone is under a trustanchor */ - /* is it equal to trustanchor - get dnskey's verified */ - /* else, find chain of trust by fetching DNSKEYs lookup for zone */ - /* result if that, if insecure, means no DNSSEC for the ZONEMD, - * otherwise we have the zone DNSKEY for the DNSSEC verification. */ - if(env->anchors) - anchor = anchors_lookup(env->anchors, z->name, z->namelen, - z->dclass); - if(anchor && anchor->numDS == 0 && anchor->numDNSKEY == 0) { - /* domain-insecure trust anchor for unsigned zones */ - lock_basic_unlock(&anchor->lock); - if(only_online) - return; - dnskey = NULL; - is_insecure = 1; - } else if(anchor && query_dname_compare(z->name, anchor->name) == 0) { - if(only_online) { - lock_basic_unlock(&anchor->lock); - return; - } - /* equal to trustanchor, no need for online lookups */ - dnskey = zonemd_get_dnskey_from_anchor(z, env, mods, anchor, - &is_insecure, &why_bogus, &keystorage); - lock_basic_unlock(&anchor->lock); - if(!dnskey && !reason && !is_insecure) { - reason = "verify DNSKEY RRset with trust anchor failed"; - } - } else if(anchor) { - lock_basic_unlock(&anchor->lock); - /* perform online lookups */ - if(offline) - return; - /* setup online lookups, and wait for them */ - if(zonemd_lookup_dnskey(z, env)) { - /* wait for the lookup */ - return; - } - reason = "could not lookup DNSKEY for chain of trust"; - } else { - /* the zone is not under a trust anchor */ - if(only_online) - return; - dnskey = NULL; - is_insecure = 1; - } - - if(reason) { - auth_zone_zonemd_fail(z, env, reason, why_bogus, result); - return; - } - - auth_zone_verify_zonemd_with_key(z, env, mods, dnskey, is_insecure, - result, NULL); - regional_free_all(env->scratch); -} - -void auth_zones_pickup_zonemd_verify(struct auth_zones* az, - struct module_env* env) -{ - struct auth_zone key; - uint8_t savezname[255+1]; - size_t savezname_len; - struct auth_zone* z; - key.node.key = &key; - lock_rw_rdlock(&az->lock); - RBTREE_FOR(z, struct auth_zone*, &az->ztree) { - lock_rw_wrlock(&z->lock); - if(!z->zonemd_check) { - lock_rw_unlock(&z->lock); - continue; - } - key.dclass = z->dclass; - key.namelabs = z->namelabs; - if(z->namelen > sizeof(savezname)) { - lock_rw_unlock(&z->lock); - log_err("auth_zones_pickup_zonemd_verify: zone name too long"); - continue; - } - savezname_len = z->namelen; - memmove(savezname, z->name, z->namelen); - lock_rw_unlock(&az->lock); - auth_zone_verify_zonemd(z, env, &env->mesh->mods, NULL, 0, 1); - lock_rw_unlock(&z->lock); - lock_rw_rdlock(&az->lock); - /* find the zone we had before, it is not deleted, - * because we have a flag for that that is processed at - * apply_cfg time */ - key.namelen = savezname_len; - key.name = savezname; - z = (struct auth_zone*)rbtree_search(&az->ztree, &key); - if(!z) - break; - } - lock_rw_unlock(&az->lock); -} diff --git a/crates/libunbound-sys/unbound/services/authzone.h b/crates/libunbound-sys/unbound/services/authzone.h deleted file mode 100644 index 07614ed8..00000000 --- a/crates/libunbound-sys/unbound/services/authzone.h +++ /dev/null @@ -1,790 +0,0 @@ -/* - * services/authzone.h - authoritative zone that is locally hosted. - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the functions for an authority zone. This zone - * is queried by the iterator, just like a stub or forward zone, but then - * the data is locally held. - */ - -#ifndef SERVICES_AUTHZONE_H -#define SERVICES_AUTHZONE_H -#include "util/rbtree.h" -#include "util/locks.h" -#include "services/mesh.h" -#include "services/rpz.h" -struct ub_packed_rrset_key; -struct regional; -struct config_file; -struct config_auth; -struct query_info; -struct dns_msg; -struct edns_data; -struct module_env; -struct worker; -struct comm_point; -struct comm_timer; -struct comm_reply; -struct auth_rrset; -struct auth_nextprobe; -struct auth_probe; -struct auth_transfer; -struct auth_master; -struct auth_chunk; - -/** - * Authoritative zones, shared. - */ -struct auth_zones { - /** lock on the authzone trees */ - lock_rw_type lock; - /** rbtree of struct auth_zone */ - rbtree_type ztree; - /** rbtree of struct auth_xfer */ - rbtree_type xtree; - /** do we have downstream enabled */ - int have_downstream; - /** number of queries upstream */ - size_t num_query_up; - /** number of queries downstream */ - size_t num_query_down; - /** first auth zone containing rpz item in linked list */ - struct auth_zone* rpz_first; - /** rw lock for rpz linked list, needed when iterating or editing linked - * list. */ - lock_rw_type rpz_lock; -}; - -/** - * Auth zone. Authoritative data, that is fetched from instead of sending - * packets to the internet. - */ -struct auth_zone { - /** rbtree node, key is name and class */ - rbnode_type node; - - /** zone name, in uncompressed wireformat */ - uint8_t* name; - /** length of zone name */ - size_t namelen; - /** number of labels in zone name */ - int namelabs; - /** the class of this zone, in host byteorder. - * uses 'dclass' to not conflict with c++ keyword class. */ - uint16_t dclass; - - /** lock on the data in the structure - * For the node, parent, name, namelen, namelabs, dclass, you - * need to also hold the zones_tree lock to change them (or to - * delete this zone) */ - lock_rw_type lock; - - /** auth data for this zone - * rbtree of struct auth_data */ - rbtree_type data; - - /** zonefile name (or NULL for no zonefile) */ - char* zonefile; - /** fallback to the internet on failure or ttl-expiry of auth zone */ - int fallback_enabled; - /** the zone has expired (enabled by the xfer worker), fallback - * happens if that option is enabled. */ - int zone_expired; - /** zone is a slave zone (it has masters) */ - int zone_is_slave; - /** for downstream: this zone answers queries towards the downstream - * clients */ - int for_downstream; - /** for upstream: this zone answers queries that unbound intends to - * send upstream. */ - int for_upstream; - /** check ZONEMD records */ - int zonemd_check; - /** reject absence of ZONEMD records */ - int zonemd_reject_absence; - /** RPZ zones */ - struct rpz* rpz; - /** store the env (worker thread specific) for the zonemd callbacks - * from the mesh with the results of the lookup, if nonNULL, some - * worker has already picked up the zonemd verification task and - * this worker does not have to do it as well. */ - struct module_env* zonemd_callback_env; - /** for the zonemd callback, the type of data looked up */ - uint16_t zonemd_callback_qtype; - /** zone has been deleted */ - int zone_deleted; - /** deletelist pointer, unused normally except during delete */ - struct auth_zone* delete_next; - /* not protected by auth_zone lock, must be last items in struct */ - /** next auth zone containing RPZ data, or NULL */ - struct auth_zone* rpz_az_next; - /** previous auth zone containing RPZ data, or NULL */ - struct auth_zone* rpz_az_prev; -}; - -/** - * Auth data. One domain name, and the RRs to go with it. - */ -struct auth_data { - /** rbtree node, key is name only */ - rbnode_type node; - /** domain name */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** number of labels in name */ - int namelabs; - /** the data rrsets, with different types, linked list. - * if the list if NULL the node would be an empty non-terminal, - * but in this data structure such nodes that represent an empty - * non-terminal are not needed; they just don't exist. - */ - struct auth_rrset* rrsets; -}; - -/** - * A auth data RRset - */ -struct auth_rrset { - /** next in list */ - struct auth_rrset* next; - /** RR type in host byteorder */ - uint16_t type; - /** RRset data item */ - struct packed_rrset_data* data; -}; - -/** - * Authoritative zone transfer structure. - * Create and destroy needs the auth_zones* biglock. - * The structure consists of different tasks. Each can be unowned (-1) or - * owner by a worker (worker-num). A worker can pick up a task and then do - * it. This means the events (timeouts, sockets) are for that worker. - * - * (move this to tasks). - * They don't have locks themselves, the worker (that owns it) uses it, - * also as part of callbacks, hence it has separate zonename pointers for - * lookup in the main zonetree. If the zone has no transfers, this - * structure is not created. - */ -struct auth_xfer { - /** rbtree node, key is name and class */ - rbnode_type node; - - /** lock on this structure, and on the workernum elements of the - * tasks. First hold the tree-lock in auth_zones, find the auth_xfer, - * lock this lock. Then a worker can reassign itself to fill up - * one of the tasks. - * Once it has the task assigned to it, the worker can access the - * other elements of the task structure without a lock, because that - * is necessary for the eventloop and callbacks from that. */ - lock_basic_type lock; - - /** zone name, in uncompressed wireformat */ - uint8_t* name; - /** length of zone name */ - size_t namelen; - /** number of labels in zone name */ - int namelabs; - /** the class of this zone, in host byteorder. - * uses 'dclass' to not conflict with c++ keyword class. */ - uint16_t dclass; - - /** task to wait for next-probe-timeout, - * once timeouted, see if a SOA probe is needed, or already - * in progress */ - struct auth_nextprobe* task_nextprobe; - - /** task for SOA probe. Check if the zone can be updated */ - struct auth_probe* task_probe; - - /** Task for transfer. Transferring and updating the zone. This - * includes trying (potentially) several upstream masters. Downloading - * and storing the zone */ - struct auth_transfer* task_transfer; - - /** a notify was received, but a zone transfer or probe was already - * acted on. - * However, the zone transfer could signal a newer serial number. - * The serial number of that notify is saved below. The transfer and - * probe tasks should check this once done to see if they need to - * restart the transfer task for the newer notify serial. - * Hold the lock to access this member (and the serial). - */ - int notify_received; - /** true if the notify_received has a serial number */ - int notify_has_serial; - /** serial number of the notify */ - uint32_t notify_serial; - /** the list of masters for checking notifies. This list is - * empty on start, and a copy of the list from the probe_task when - * it is done looking them up. */ - struct auth_master* allow_notify_list; - - /* protected by the lock on the structure, information about - * the loaded authority zone. */ - /** is the zone currently considered expired? after expiry also older - * serial numbers are allowed (not just newer) */ - int zone_expired; - /** do we have a zone (if 0, no zone data at all) */ - int have_zone; - - /** current serial (from SOA), if we have no zone, 0 */ - uint32_t serial; - /** retry time (from SOA), time to wait with next_probe - * if no master responds */ - time_t retry; - /** refresh time (from SOA), time to wait with next_probe - * if everything is fine */ - time_t refresh; - /** expiry time (from SOA), time until zone data is not considered - * valid any more, if no master responds within this time, either - * with the current zone or a new zone. */ - time_t expiry; - - /** zone lease start time (start+expiry is expiration time). - * this is renewed every SOA probe and transfer. On zone load - * from zonefile it is also set (with probe set soon to check) */ - time_t lease_time; -}; - -/** - * The next probe task. - * This task consists of waiting for the probetimeout. It is a task because - * it needs an event in the eventtable. Once the timeout has passed, that - * worker can (potentially) become the auth_probe worker, or if another worker - * is already doing that, do nothing. Tasks becomes unowned. - * The probe worker, if it detects nothing has to be done picks up this task, - * if unowned. - */ -struct auth_nextprobe { - /* Worker pointer. NULL means unowned. */ - struct worker* worker; - /* module env for this task */ - struct module_env* env; - - /** increasing backoff for failures */ - time_t backoff; - /** Timeout for next probe (for SOA) */ - time_t next_probe; - /** timeout callback for next_probe or expiry(if that is sooner). - * it is on the worker's event_base */ - struct comm_timer* timer; -}; - -/** - * The probe task. - * Send a SOA UDP query to see if the zone needs to be updated (or similar, - * potential, HTTP probe query) and check serial number. - * If yes, start the auth_transfer task. If no, make sure auth_nextprobe - * timeout wait task is running. - * Needs to be a task, because the UDP query needs an event entry. - * This task could also be started by eg. a NOTIFY being received, even though - * another worker is performing the nextprobe task (and that worker keeps - * waiting uninterrupted). - */ -struct auth_probe { - /* Worker pointer. NULL means unowned. */ - struct worker* worker; - /* module env for this task */ - struct module_env* env; - - /** list of upstream masters for this zone, from config */ - struct auth_master* masters; - - /** for the hostname lookups, which master is current */ - struct auth_master* lookup_target; - /** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */ - int lookup_aaaa; - /** we only want to do lookups for making config work (for notify), - * don't proceed with UDP SOA probe queries */ - int only_lookup; - /** we have seen a new lease this scan, because one of the masters - * replied with the current SOA serial version */ - int have_new_lease; - - /** once notified, or the timeout has been reached. a scan starts. */ - /** the scan specific target (notify source), or NULL if none */ - struct auth_master* scan_specific; - /** scan tries all the upstream masters. the scan current target. - * or NULL if not working on sequential scan */ - struct auth_master* scan_target; - /** if not NULL, the specific addr for the current master */ - struct auth_addr* scan_addr; - - /** dns id of packet in flight */ - uint16_t id; - /** the SOA probe udp event. - * on the workers event base. */ - struct comm_point* cp; - /** is the cp for ip6 or ip4 */ - int cp_is_ip6; - /** timeout for packets. - * on the workers event base. */ - struct comm_timer* timer; - /** timeout in msec */ - int timeout; -}; - -/** - * The transfer task. - * Once done, make sure the nextprobe waiting task is running, whether done - * with failure or success. If failure, use shorter timeout for wait time. - */ -struct auth_transfer { - /* Worker pointer. NULL means unowned. */ - struct worker* worker; - /* module env for this task */ - struct module_env* env; - - /** xfer data that has been transferred, the data is applied - * once the transfer has completed correctly */ - struct auth_chunk* chunks_first; - /** last element in chunks list (to append new data at the end) */ - struct auth_chunk* chunks_last; - - /** list of upstream masters for this zone, from config */ - struct auth_master* masters; - - /** for the hostname lookups, which master is current */ - struct auth_master* lookup_target; - /** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */ - int lookup_aaaa; - - /** once notified, or the timeout has been reached. a scan starts. */ - /** the scan specific target (notify source), or NULL if none */ - struct auth_master* scan_specific; - /** scan tries all the upstream masters. the scan current target. - * or NULL if not working on sequential scan */ - struct auth_master* scan_target; - /** what address we are scanning for the master, or NULL if the - * master is in IP format itself */ - struct auth_addr* scan_addr; - /** the zone transfer in progress (or NULL if in scan). It is - * from this master */ - struct auth_master* master; - - /** failed ixfr transfer, retry with axfr (to the current master), - * the IXFR was 'REFUSED', 'SERVFAIL', 'NOTIMPL' or the contents of - * the IXFR did not apply cleanly (out of sync, delete of nonexistent - * data or add of duplicate data). Flag is cleared once the retry - * with axfr is done. */ - int ixfr_fail; - /** we saw an ixfr-indicating timeout, count of them */ - int ixfr_possible_timeout_count; - /** we are doing IXFR right now */ - int on_ixfr; - /** did we detect the current AXFR/IXFR serial number yet, 0 not yet, - * 1 we saw the first, 2 we saw the second, 3 must be last SOA in xfr*/ - int got_xfr_serial; - /** number of RRs scanned for AXFR/IXFR detection */ - size_t rr_scan_num; - /** we are doing an IXFR but we detected an AXFR contents */ - int on_ixfr_is_axfr; - /** the serial number for the current AXFR/IXFR incoming reply, - * for IXFR, the outermost SOA records serial */ - uint32_t incoming_xfr_serial; - - /** dns id of AXFR query */ - uint16_t id; - /** the transfer (TCP) to the master. - * on the workers event base. */ - struct comm_point* cp; - /** timeout for the transfer. - * on the workers event base. */ - struct comm_timer* timer; -}; - -/** list of addresses */ -struct auth_addr { - /** next in list */ - struct auth_addr* next; - /** IP address */ - struct sockaddr_storage addr; - /** addr length */ - socklen_t addrlen; -}; - -/** auth zone master upstream, and the config settings for it */ -struct auth_master { - /** next master in list */ - struct auth_master* next; - /** master IP address (and port), or hostname, string */ - char* host; - /** for http, filename */ - char* file; - /** use HTTP for this master */ - int http; - /** use IXFR for this master */ - int ixfr; - /** this is an allow notify member, the master can send notifies - * to us, but we don't send SOA probes, or zone transfer from it */ - int allow_notify; - /** use ssl for channel */ - int ssl; - /** the port number (for urls) */ - int port; - /** if the host is a hostname, the list of resolved addrs, if any*/ - struct auth_addr* list; -}; - -/** auth zone master zone transfer data chunk */ -struct auth_chunk { - /** next chunk in list */ - struct auth_chunk* next; - /** the data from this chunk, this is what was received. - * for an IXFR that means results from comm_net tcp actions, - * packets. also for an AXFR. For HTTP a zonefile chunk. */ - uint8_t* data; - /** length of allocated data */ - size_t len; -}; - -/** - * Create auth zones structure - */ -struct auth_zones* auth_zones_create(void); - -/** - * Apply configuration to auth zones. Reads zonefiles. - * @param az: auth zones structure - * @param cfg: config to apply. - * @param setup: if true, also sets up values in the auth zones structure - * @param is_rpz: set to 1 if at least one RPZ zone is configured. - * @param env: environment for offline verification. - * @param mods: modules in environment. - * @return false on failure. - */ -int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg, - int setup, int* is_rpz, struct module_env* env, - struct module_stack* mods); - -/** initial pick up of worker timeouts, ties events to worker event loop - * @param az: auth zones structure - * @param env: worker env, of first worker that receives the events (if any) - * in its eventloop. - */ -void auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env); - -/** - * Cleanup auth zones. This removes all events from event bases. - * Stops the xfr tasks. But leaves zone data. - * @param az: auth zones structure. - */ -void auth_zones_cleanup(struct auth_zones* az); - -/** - * Delete auth zones structure - */ -void auth_zones_delete(struct auth_zones* az); - -/** - * Write auth zone data to file, in zonefile format. - */ -int auth_zone_write_file(struct auth_zone* z, const char* fname); - -/** - * Use auth zones to lookup the answer to a query. - * The query is from the iterator. And the auth zones attempts to provide - * the answer instead of going to the internet. - * - * @param az: auth zones structure. - * @param qinfo: query info to lookup. - * @param region: region to use to allocate the reply in. - * @param msg: reply is stored here (if one). - * @param fallback: if true, fallback to making a query to the internet. - * @param dp_nm: name of delegation point to look for. This zone is used - * to answer the query. - * If the dp_nm is not found, fallback is set to true and false returned. - * @param dp_nmlen: length of dp_nm. - * @return 0: failure (an error of some sort, like servfail). - * if 0 and fallback is true, fallback to the internet. - * if 0 and fallback is false, like getting servfail. - * If true, an answer is available. - */ -int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo, - struct regional* region, struct dns_msg** msg, int* fallback, - uint8_t* dp_nm, size_t dp_nmlen); - -/** - * Answer query from auth zone. Create authoritative answer. - * @param az: auth zones structure. - * @param env: the module environment. - * @param qinfo: query info (parsed). - * @param edns: edns info (parsed). - * @param buf: buffer with query ID and flags, also for reply. - * @param repinfo: reply information for a communication point. - * @param temp: temporary storage region. - * @return false if not answered - */ -int auth_zones_answer(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, struct sldns_buffer* buf, struct regional* temp); - -/** - * Find the auth zone that is above the given qname. - * Return NULL when there is no auth_zone above the give name, otherwise - * returns the closest auth_zone above the qname that pertains to it. - * @param az: auth zones structure. - * @param name: query to look up for. - * @param name_len: length of name. - * @param dclass: class of zone to find. - * @return NULL or auth_zone that pertains to the query. - */ -struct auth_zone* auth_zones_find_zone(struct auth_zones* az, - uint8_t* name, size_t name_len, uint16_t dclass); - -/** find an auth zone by name (exact match by name or NULL returned) */ -struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm, - size_t nmlen, uint16_t dclass); - -/** find an xfer zone by name (exact match by name or NULL returned) */ -struct auth_xfer* auth_xfer_find(struct auth_zones* az, uint8_t* nm, - size_t nmlen, uint16_t dclass); - -/** create an auth zone. returns wrlocked zone. caller must have wrlock - * on az. returns NULL on malloc failure */ -struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm, - size_t nmlen, uint16_t dclass); - -/** set auth zone zonefile string. caller must have lock on zone */ -int auth_zone_set_zonefile(struct auth_zone* z, char* zonefile); - -/** set auth zone fallback. caller must have lock on zone. - * fallbackstr is "yes" or "no". false on parse failure. */ -int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr); - -/** see if the auth zone for the name can fallback - * @param az: auth zones - * @param nm: name of delegation point. - * @param nmlen: length of nm. - * @param dclass: class of zone to look for. - * @return true if fallback_enabled is true. false if not. - * if the zone does not exist, fallback is true (more lenient) - * also true if zone does not do upstream requests. - */ -int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen, - uint16_t dclass); - -/** process notify for auth zones. - * first checks the access list. Then processes the notify. This starts - * the probe sequence or it notes the serial number (if any) - * @param az: auth zones structure. - * @param env: module env of the worker that is handling the notify. it will - * pick up the task probe (or transfer), unless already in progress by - * another worker. - * @param nm: name of the zone. Uncompressed. from query. - * @param nmlen: length of name. - * @param dclass: class of zone. - * @param addr: source address of notify - * @param addrlen: length of addr. - * @param has_serial: if true, the notify has a serial attached. - * @param serial: the serial number, if has_serial is true. - * @param refused: is set to true on failure to note refused access. - * @return fail on failures (refused is false) and when access is - * denied (refused is true). True when processed. - */ -int auth_zones_notify(struct auth_zones* az, struct module_env* env, - uint8_t* nm, size_t nmlen, uint16_t dclass, - struct sockaddr_storage* addr, socklen_t addrlen, int has_serial, - uint32_t serial, int* refused); - -/** process notify packet and read serial number from SOA. - * returns 0 if no soa record in the notify */ -int auth_zone_parse_notify_serial(struct sldns_buffer* pkt, uint32_t *serial); - -/** for the zone and if not already going, starts the probe sequence. - * false if zone cannot be found. This is like a notify arrived and was - * accepted for that zone. */ -int auth_zones_startprobesequence(struct auth_zones* az, - struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t dclass); - -/** read auth zone from zonefile. caller must lock zone. false on failure */ -int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg); - -/** find the apex SOA RRset, if it exists. NULL if no SOA RRset. */ -struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z); - -/** find serial number of zone or false if none (no SOA record) */ -int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial); - -/** Find auth_zone SOA and populate the values in xfr(soa values). */ -int xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr); - -/** compare auth_zones for sorted rbtree */ -int auth_zone_cmp(const void* z1, const void* z2); - -/** compare auth_data for sorted rbtree */ -int auth_data_cmp(const void* z1, const void* z2); - -/** compare auth_xfer for sorted rbtree */ -int auth_xfer_cmp(const void* z1, const void* z2); - -/** Create auth_xfer structure. - * Caller must have wrlock on az. Returns locked xfer zone. - * @param az: zones structure. - * @param z: zone with name and class - * @return xfer zone or NULL - */ -struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z); - -/** - * Set masters in auth xfer structure from config. - * @param list: pointer to start of list. The malloced list is returned here. - * @param c: the config items to copy over. - * @param with_http: if true, http urls are also included, before the masters. - * @return false on failure. - */ -int xfer_set_masters(struct auth_master** list, struct config_auth* c, - int with_http); - -/** xfer nextprobe timeout callback, this is part of task_nextprobe */ -void auth_xfer_timer(void* arg); - -/** callback for commpoint udp replies to task_probe */ -int auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* repinfo); -/** callback for task_transfer tcp connections */ -int auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* repinfo); -/** callback for task_transfer http connections */ -int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err, - struct comm_reply* repinfo); -/** xfer probe timeout callback, part of task_probe */ -void auth_xfer_probe_timer_callback(void* arg); -/** xfer transfer timeout callback, part of task_transfer */ -void auth_xfer_transfer_timer_callback(void* arg); -/** mesh callback for task_probe on lookup of host names */ -void auth_xfer_probe_lookup_callback(void* arg, int rcode, - struct sldns_buffer* buf, enum sec_status sec, char* why_bogus, - int was_ratelimited); -/** mesh callback for task_transfer on lookup of host names */ -void auth_xfer_transfer_lookup_callback(void* arg, int rcode, - struct sldns_buffer* buf, enum sec_status sec, char* why_bogus, - int was_ratelimited); - -/* - * Compares two 32-bit serial numbers as defined in RFC1982. Returns - * <0 if a < b, 0 if a == b, and >0 if a > b. The result is undefined - * if a != b but neither is greater or smaller (see RFC1982 section - * 3.2.). - */ -int compare_serial(uint32_t a, uint32_t b); - -/** - * Generate ZONEMD digest for the auth zone. - * @param z: the auth zone to digest. - * omits zonemd at apex and its RRSIG from the digest. - * @param scheme: the collation scheme to use. Numbers as defined for ZONEMD. - * @param hashalgo: the hash algo, from the registry defined for ZONEMD type. - * @param hash: the result buffer. - * @param buflen: size of the result buffer, must be large enough. or the - * routine fails. - * @param resultlen: size of the hash in the result buffer of the result. - * @param region: temp region for allocs during canonicalisation. - * @param buf: temp buffer during canonicalisation. - * @param reason: failure reason, returns a string, NULL on success. - * @return false on failure. - */ -int auth_zone_generate_zonemd_hash(struct auth_zone* z, int scheme, - int hashalgo, uint8_t* hash, size_t buflen, size_t* resultlen, - struct regional* region, struct sldns_buffer* buf, char** reason); - -/** ZONEMD scheme definitions */ -#define ZONEMD_SCHEME_SIMPLE 1 - -/** ZONEMD hash algorithm definition for SHA384 */ -#define ZONEMD_ALGO_SHA384 1 -/** ZONEMD hash algorithm definition for SHA512 */ -#define ZONEMD_ALGO_SHA512 2 - -/** returns true if a zonemd hash algo is supported */ -int zonemd_hashalgo_supported(int hashalgo); -/** returns true if a zonemd scheme is supported */ -int zonemd_scheme_supported(int scheme); - -/** - * Check ZONEMD digest for the auth zone. - * @param z: auth zone to digest. - * @param scheme: zonemd scheme. - * @param hashalgo: zonemd hash algorithm. - * @param hash: the hash to check. - * @param hashlen: length of hash buffer. - * @param region: temp region for allocs during canonicalisation. - * @param buf: temp buffer during canonicalisation. - * @param reason: string returned with failure reason. - * If the hash cannot be checked, but it is allowed, for unknown - * algorithms, the routine returns success, and the reason is nonNULL, - * with the allowance reason. - * @return false on failure. - */ -int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme, - int hashalgo, uint8_t* hash, size_t hashlen, struct regional* region, - struct sldns_buffer* buf, char** reason); - -/** - * Perform ZONEMD checks and verification for the auth zone. - * This includes DNSSEC verification if applicable. - * @param z: auth zone to check. Caller holds lock. wrlock. - * @param env: with temp region, buffer and config. - * @param mods: module stack for validator env. - * @param result: if not NULL, result string strdupped in here. - * @param offline: if true, there is no spawned lookup when online is needed. - * Those zones are skipped for ZONEMD checking. - * @param only_online: if true, only for ZONEMD that need online lookup - * of DNSKEY chain of trust are processed. - */ -void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env, - struct module_stack* mods, char** result, int offline, - int only_online); - -/** mesh callback for zonemd on lookup of dnskey */ -void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, - struct sldns_buffer* buf, enum sec_status sec, char* why_bogus, - int was_ratelimited); - -/** - * Check the ZONEMD records that need online DNSSEC chain lookups, - * for them spawn the lookup process to get it checked out. - * Attaches the lookup process to the worker event base and mesh state. - * @param az: auth zones, every zones is checked. - * @param env: env of the worker where the task is attached. - */ -void auth_zones_pickup_zonemd_verify(struct auth_zones* az, - struct module_env* env); - -#endif /* SERVICES_AUTHZONE_H */ diff --git a/crates/libunbound-sys/unbound/services/cache/dns.c b/crates/libunbound-sys/unbound/services/cache/dns.c deleted file mode 100644 index 9b4ad588..00000000 --- a/crates/libunbound-sys/unbound/services/cache/dns.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * services/cache/dns.c - Cache services for DNS using msg and rrset caches. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the DNS cache. - */ -#include "config.h" -#include "iterator/iter_delegpt.h" -#include "iterator/iter_utils.h" -#include "validator/val_nsec.h" -#include "validator/val_utils.h" -#include "services/cache/dns.h" -#include "services/cache/rrset.h" -#include "util/data/msgparse.h" -#include "util/data/msgreply.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "sldns/sbuffer.h" - -/** store rrsets in the rrset cache. - * @param env: module environment with caches. - * @param rep: contains list of rrsets to store. - * @param now: current time. - * @param leeway: during prefetch how much leeway to update TTLs. - * This makes rrsets (other than type NS) timeout sooner so they get - * updated with a new full TTL. - * Type NS does not get this, because it must not be refreshed from the - * child domain, but keep counting down properly. - * @param pside: if from parentside discovered NS, so that its NS is okay - * in a prefetch situation to be updated (without becoming sticky). - * @param qrep: update rrsets here if cache is better - * @param region: for qrep allocs. - * @param qstarttime: time when delegations were looked up, this is perhaps - * earlier than the time in now. The time is used to determine if RRsets - * of type NS have expired, so that they can only be updated using - * lookups of delegation points that did not use them, since they had - * expired then. - */ -static void -store_rrsets(struct module_env* env, struct reply_info* rep, time_t now, - time_t leeway, int pside, struct reply_info* qrep, - struct regional* region, time_t qstarttime) -{ - size_t i; - /* see if rrset already exists in cache, if not insert it. */ - for(i=0; irrset_count; i++) { - rep->ref[i].key = rep->rrsets[i]; - rep->ref[i].id = rep->rrsets[i]->id; - /* update ref if it was in the cache */ - switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], - env->alloc, ((ntohs(rep->ref[i].key->rk.type)== - LDNS_RR_TYPE_NS && !pside)?qstarttime:now + leeway))) { - case 0: /* ref unchanged, item inserted */ - break; - case 2: /* ref updated, cache is superior */ - if(region) { - struct ub_packed_rrset_key* ck; - lock_rw_rdlock(&rep->ref[i].key->entry.lock); - /* if deleted rrset, do not copy it */ - if(rep->ref[i].key->id == 0) - ck = NULL; - else ck = packed_rrset_copy_region( - rep->ref[i].key, region, now); - lock_rw_unlock(&rep->ref[i].key->entry.lock); - if(ck) { - /* use cached copy if memory allows */ - qrep->rrsets[i] = ck; - } - } - /* no break: also copy key item */ - /* the line below is matched by gcc regex and silences - * the fallthrough warning */ - /* fallthrough */ - case 1: /* ref updated, item inserted */ - rep->rrsets[i] = rep->ref[i].key; - } - } -} - -/** delete message from message cache */ -void -msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags) -{ - struct query_info k; - hashvalue_type h; - - k.qname = qname; - k.qname_len = qnamelen; - k.qtype = qtype; - k.qclass = qclass; - k.local_alias = NULL; - h = query_info_hash(&k, flags); - slabhash_remove(env->msg_cache, h, &k); -} - -void -dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, - hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside, - struct reply_info* qrep, uint32_t flags, struct regional* region, - time_t qstarttime) -{ - struct msgreply_entry* e; - time_t ttl = rep->ttl; - size_t i; - - /* store RRsets */ - for(i=0; irrset_count; i++) { - rep->ref[i].key = rep->rrsets[i]; - rep->ref[i].id = rep->rrsets[i]->id; - } - - /* there was a reply_info_sortref(rep) here but it seems to be - * unnecessary, because the cache gets locked per rrset. */ - reply_info_set_ttls(rep, *env->now); - store_rrsets(env, rep, *env->now, leeway, pside, qrep, region, - qstarttime); - if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) { - /* we do not store the message, but we did store the RRs, - * which could be useful for delegation information */ - verbose(VERB_ALGO, "TTL 0: dropped msg from cache"); - reply_info_delete(rep, NULL); - /* if the message is in the cache, remove that msg, - * so that the TTL 0 response can be returned for future - * responses (i.e. don't get answered from - * cache, but instead go to recursion to get this TTL0 - * response). - * Possible messages that could be in the cache: - * - SERVFAIL - * - NXDOMAIN - * - NODATA - * - an older record that is expired - * - an older record that did not yet expire */ - msg_cache_remove(env, qinfo->qname, qinfo->qname_len, - qinfo->qtype, qinfo->qclass, flags); - return; - } - - /* store msg in the cache */ - reply_info_sortref(rep); - if(!(e = query_info_entrysetup(qinfo, rep, hash))) { - log_err("store_msg: malloc failed"); - return; - } - slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc); -} - -/** see if an rrset is expired above the qname, return upper qname. */ -static int -rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen, - uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop, - size_t expiretoplen) -{ - struct ub_packed_rrset_key *rrset; - uint8_t lablen; - - while(*qnamelen > 0) { - /* look one label higher */ - lablen = **qname; - *qname += lablen + 1; - *qnamelen -= lablen + 1; - if(*qnamelen <= 0) - break; - - /* looks up with a time of 0, to see expired entries */ - if((rrset = rrset_cache_lookup(env->rrset_cache, *qname, - *qnamelen, searchtype, qclass, 0, 0, 0))) { - struct packed_rrset_data* data = - (struct packed_rrset_data*)rrset->entry.data; - if(now > data->ttl) { - /* it is expired, this is not wanted */ - lock_rw_unlock(&rrset->entry.lock); - log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass); - return 1; - } - /* it is not expired, continue looking */ - lock_rw_unlock(&rrset->entry.lock); - } - - /* do not look above the expiretop. */ - if(expiretop && *qnamelen == expiretoplen && - query_dname_compare(*qname, expiretop)==0) - break; - } - return 0; -} - -/** find closest NS or DNAME and returns the rrset (locked) */ -static struct ub_packed_rrset_key* -find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen, - uint16_t qclass, time_t now, uint16_t searchtype, int stripfront, - int noexpiredabove, uint8_t* expiretop, size_t expiretoplen) -{ - struct ub_packed_rrset_key *rrset; - uint8_t lablen; - - if(stripfront) { - /* strip off so that DNAMEs have strict subdomain match */ - lablen = *qname; - qname += lablen + 1; - qnamelen -= lablen + 1; - } - - /* snip off front part of qname until the type is found */ - while(qnamelen > 0) { - if((rrset = rrset_cache_lookup(env->rrset_cache, qname, - qnamelen, searchtype, qclass, 0, now, 0))) { - uint8_t* origqname = qname; - size_t origqnamelen = qnamelen; - if(!noexpiredabove) - return rrset; - /* if expiretop set, do not look above it, but - * qname is equal, so the just found result is also - * the nonexpired above part. */ - if(expiretop && qnamelen == expiretoplen && - query_dname_compare(qname, expiretop)==0) - return rrset; - /* check for expiry, but we have to let go of the rrset - * for the lock ordering */ - lock_rw_unlock(&rrset->entry.lock); - /* the expired_above function always takes off one - * label (if qnamelen>0) and returns the final qname - * where it searched, so we can continue from there - * turning the O N*N search into O N. */ - if(!rrset_expired_above(env, &qname, &qnamelen, - searchtype, qclass, now, expiretop, - expiretoplen)) { - /* we want to return rrset, but it may be - * gone from cache, if so, just loop like - * it was not in the cache in the first place. - */ - if((rrset = rrset_cache_lookup(env-> - rrset_cache, origqname, origqnamelen, - searchtype, qclass, 0, now, 0))) { - return rrset; - } - } - log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass); - continue; - } - - /* snip off front label */ - lablen = *qname; - qname += lablen + 1; - qnamelen -= lablen + 1; - } - return NULL; -} - -/** add addr to additional section */ -static void -addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region, - struct dns_msg* msg, time_t now) -{ - if((msg->rep->rrsets[msg->rep->rrset_count] = - packed_rrset_copy_region(rrset, region, now))) { - msg->rep->ar_numrrsets++; - msg->rep->rrset_count++; - } -} - -/** lookup message in message cache */ -struct msgreply_entry* -msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr) -{ - struct lruhash_entry* e; - struct query_info k; - hashvalue_type h; - - k.qname = qname; - k.qname_len = qnamelen; - k.qtype = qtype; - k.qclass = qclass; - k.local_alias = NULL; - h = query_info_hash(&k, flags); - e = slabhash_lookup(env->msg_cache, h, &k, wr); - - if(!e) return NULL; - if( now > ((struct reply_info*)e->data)->ttl ) { - lock_rw_unlock(&e->lock); - return NULL; - } - return (struct msgreply_entry*)e->key; -} - -/** find and add A and AAAA records for nameservers in delegpt */ -static int -find_add_addrs(struct module_env* env, uint16_t qclass, - struct regional* region, struct delegpt* dp, time_t now, - struct dns_msg** msg) -{ - struct delegpt_ns* ns; - struct msgreply_entry* neg; - struct ub_packed_rrset_key* akey; - for(ns = dp->nslist; ns; ns = ns->next) { - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(akey) { - if(!delegpt_add_rrset_A(dp, region, akey, 0, NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } - if(msg) - addr_to_additional(akey, region, *msg, now); - lock_rw_unlock(&akey->entry.lock); - } else { - /* BIT_CD on false because delegpt lookup does - * not use dns64 translation */ - neg = msg_cache_lookup(env, ns->name, ns->namelen, - LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(neg) { - delegpt_add_neg_msg(dp, neg); - lock_rw_unlock(&neg->entry.lock); - } - } - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(akey) { - if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } - if(msg) - addr_to_additional(akey, region, *msg, now); - lock_rw_unlock(&akey->entry.lock); - } else { - /* BIT_CD on false because delegpt lookup does - * not use dns64 translation */ - neg = msg_cache_lookup(env, ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(neg) { - delegpt_add_neg_msg(dp, neg); - lock_rw_unlock(&neg->entry.lock); - } - } - } - return 1; -} - -/** find and add A and AAAA records for missing nameservers in delegpt */ -int -cache_fill_missing(struct module_env* env, uint16_t qclass, - struct regional* region, struct delegpt* dp) -{ - struct delegpt_ns* ns; - struct msgreply_entry* neg; - struct ub_packed_rrset_key* akey; - time_t now = *env->now; - for(ns = dp->nslist; ns; ns = ns->next) { - if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX) - continue; - ns->cache_lookup_count++; - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(akey) { - if(!delegpt_add_rrset_A(dp, region, akey, ns->lame, - NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } - log_nametypeclass(VERB_ALGO, "found in cache", - ns->name, LDNS_RR_TYPE_A, qclass); - lock_rw_unlock(&akey->entry.lock); - } else { - /* BIT_CD on false because delegpt lookup does - * not use dns64 translation */ - neg = msg_cache_lookup(env, ns->name, ns->namelen, - LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(neg) { - delegpt_add_neg_msg(dp, neg); - lock_rw_unlock(&neg->entry.lock); - } - } - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(akey) { - if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame, - NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } - log_nametypeclass(VERB_ALGO, "found in cache", - ns->name, LDNS_RR_TYPE_AAAA, qclass); - lock_rw_unlock(&akey->entry.lock); - } else { - /* BIT_CD on false because delegpt lookup does - * not use dns64 translation */ - neg = msg_cache_lookup(env, ns->name, ns->namelen, - LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(neg) { - delegpt_add_neg_msg(dp, neg); - lock_rw_unlock(&neg->entry.lock); - } - } - } - return 1; -} - -/** find and add DS or NSEC to delegation msg */ -static void -find_add_ds(struct module_env* env, struct regional* region, - struct dns_msg* msg, struct delegpt* dp, time_t now) -{ - /* Lookup the DS or NSEC at the delegation point. */ - struct ub_packed_rrset_key* rrset = rrset_cache_lookup( - env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS, - msg->qinfo.qclass, 0, now, 0); - if(!rrset) { - /* NOTE: this won't work for alternate NSEC schemes - * (opt-in, NSEC3) */ - rrset = rrset_cache_lookup(env->rrset_cache, dp->name, - dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass, - 0, now, 0); - /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used. - * since this is a referral, we need the NSEC at the parent - * side of the zone cut, not the NSEC at apex side. */ - if(rrset && nsec_has_type(rrset, LDNS_RR_TYPE_DS)) { - lock_rw_unlock(&rrset->entry.lock); - rrset = NULL; /* discard wrong NSEC */ - } - } - if(rrset) { - /* add it to auth section. This is the second rrset. */ - if((msg->rep->rrsets[msg->rep->rrset_count] = - packed_rrset_copy_region(rrset, region, now))) { - msg->rep->ns_numrrsets++; - msg->rep->rrset_count++; - } - lock_rw_unlock(&rrset->entry.lock); - } -} - -struct dns_msg* -dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, - uint16_t qclass, struct regional* region, size_t capacity) -{ - struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(!msg) - return NULL; - msg->qinfo.qname = regional_alloc_init(region, qname, qnamelen); - if(!msg->qinfo.qname) - return NULL; - msg->qinfo.qname_len = qnamelen; - msg->qinfo.qtype = qtype; - msg->qinfo.qclass = qclass; - msg->qinfo.local_alias = NULL; - /* non-packed reply_info, because it needs to grow the array */ - msg->rep = (struct reply_info*)regional_alloc_zero(region, - sizeof(struct reply_info)-sizeof(struct rrset_ref)); - if(!msg->rep) - return NULL; - if(capacity > RR_COUNT_MAX) - return NULL; /* integer overflow protection */ - msg->rep->flags = BIT_QR; /* with QR, no AA */ - msg->rep->qdcount = 1; - msg->rep->reason_bogus = LDNS_EDE_NONE; - msg->rep->rrsets = (struct ub_packed_rrset_key**) - regional_alloc(region, - capacity*sizeof(struct ub_packed_rrset_key*)); - if(!msg->rep->rrsets) - return NULL; - return msg; -} - -int -dns_msg_authadd(struct dns_msg* msg, struct regional* region, - struct ub_packed_rrset_key* rrset, time_t now) -{ - if(!(msg->rep->rrsets[msg->rep->rrset_count++] = - packed_rrset_copy_region(rrset, region, now))) - return 0; - msg->rep->ns_numrrsets++; - return 1; -} - -int -dns_msg_ansadd(struct dns_msg* msg, struct regional* region, - struct ub_packed_rrset_key* rrset, time_t now) -{ - if(!(msg->rep->rrsets[msg->rep->rrset_count++] = - packed_rrset_copy_region(rrset, region, now))) - return 0; - msg->rep->an_numrrsets++; - return 1; -} - -struct delegpt* -dns_cache_find_delegation(struct module_env* env, uint8_t* qname, - size_t qnamelen, uint16_t qtype, uint16_t qclass, - struct regional* region, struct dns_msg** msg, time_t now, - int noexpiredabove, uint8_t* expiretop, size_t expiretoplen) -{ - /* try to find closest NS rrset */ - struct ub_packed_rrset_key* nskey; - struct packed_rrset_data* nsdata; - struct delegpt* dp; - - nskey = find_closest_of_type(env, qname, qnamelen, qclass, now, - LDNS_RR_TYPE_NS, 0, noexpiredabove, expiretop, expiretoplen); - if(!nskey) /* hope the caller has hints to prime or something */ - return NULL; - nsdata = (struct packed_rrset_data*)nskey->entry.data; - /* got the NS key, create delegation point */ - dp = delegpt_create(region); - if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) { - lock_rw_unlock(&nskey->entry.lock); - log_err("find_delegation: out of memory"); - return NULL; - } - /* create referral message */ - if(msg) { - /* allocate the array to as much as we could need: - * NS rrset + DS/NSEC rrset + - * A rrset for every NS RR - * AAAA rrset for every NS RR - */ - *msg = dns_msg_create(qname, qnamelen, qtype, qclass, region, - 2 + nsdata->count*2); - if(!*msg || !dns_msg_authadd(*msg, region, nskey, now)) { - lock_rw_unlock(&nskey->entry.lock); - log_err("find_delegation: out of memory"); - return NULL; - } - } - if(!delegpt_rrset_add_ns(dp, region, nskey, 0)) - log_err("find_delegation: addns out of memory"); - lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/ - /* find and add DS/NSEC (if any) */ - if(msg) - find_add_ds(env, region, *msg, dp, now); - /* find and add A entries */ - if(!find_add_addrs(env, qclass, region, dp, now, msg)) - log_err("find_delegation: addrs out of memory"); - return dp; -} - -/** allocate dns_msg from query_info and reply_info */ -static struct dns_msg* -gen_dns_msg(struct regional* region, struct query_info* q, size_t num) -{ - struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(!msg) - return NULL; - memcpy(&msg->qinfo, q, sizeof(struct query_info)); - msg->qinfo.qname = regional_alloc_init(region, q->qname, q->qname_len); - if(!msg->qinfo.qname) - return NULL; - /* allocate replyinfo struct and rrset key array separately */ - msg->rep = (struct reply_info*)regional_alloc(region, - sizeof(struct reply_info) - sizeof(struct rrset_ref)); - if(!msg->rep) - return NULL; - msg->rep->reason_bogus = LDNS_EDE_NONE; - msg->rep->reason_bogus_str = NULL; - if(num > RR_COUNT_MAX) - return NULL; /* integer overflow protection */ - msg->rep->rrsets = (struct ub_packed_rrset_key**) - regional_alloc(region, - num * sizeof(struct ub_packed_rrset_key*)); - if(!msg->rep->rrsets) - return NULL; - return msg; -} - -struct dns_msg* -tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, - struct regional* region, time_t now, int allow_expired, - struct regional* scratch) -{ - struct dns_msg* msg; - size_t i; - int is_expired = 0; - time_t now_control = now; - if(now > r->ttl) { - /* Check if we are allowed to serve expired */ - if(allow_expired) { - if(env->cfg->serve_expired_ttl && - r->serve_expired_ttl < now) { - return NULL; - } - /* Ignore expired failure answers */ - if(FLAGS_GET_RCODE(r->flags) != - LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(r->flags) != - LDNS_RCODE_NXDOMAIN && - FLAGS_GET_RCODE(r->flags) != - LDNS_RCODE_YXDOMAIN) - return 0; - } else { - return NULL; - } - /* Change the current time so we can pass the below TTL checks when - * serving expired data. */ - now_control = r->ttl - env->cfg->serve_expired_reply_ttl; - is_expired = 1; - } - - msg = gen_dns_msg(region, q, r->rrset_count); - if(!msg) return NULL; - msg->rep->flags = r->flags; - msg->rep->qdcount = r->qdcount; - msg->rep->ttl = is_expired - ?SERVE_EXPIRED_REPLY_TTL - :r->ttl - now; - if(r->prefetch_ttl > now) - msg->rep->prefetch_ttl = r->prefetch_ttl - now; - else - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - msg->rep->security = r->security; - msg->rep->an_numrrsets = r->an_numrrsets; - msg->rep->ns_numrrsets = r->ns_numrrsets; - msg->rep->ar_numrrsets = r->ar_numrrsets; - msg->rep->rrset_count = r->rrset_count; - msg->rep->authoritative = r->authoritative; - msg->rep->reason_bogus = r->reason_bogus; - if(r->reason_bogus_str) { - msg->rep->reason_bogus_str = regional_strdup(region, r->reason_bogus_str); - } - - if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) { - return NULL; - } - if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons( - LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons( - LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) { - /* cname chain is now invalid, reconstruct msg */ - rrset_array_unlock(r->ref, r->rrset_count); - return NULL; - } - if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) { - /* message rrsets have changed status, revalidate */ - rrset_array_unlock(r->ref, r->rrset_count); - return NULL; - } - for(i=0; irep->rrset_count; i++) { - msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], - region, now); - if(!msg->rep->rrsets[i]) { - rrset_array_unlock(r->ref, r->rrset_count); - return NULL; - } - } - if(env) - rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref, - r->rrset_count); - else - rrset_array_unlock(r->ref, r->rrset_count); - return msg; -} - -/** synthesize RRset-only response from cached RRset item */ -static struct dns_msg* -rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region, - time_t now, struct query_info* q) -{ - struct dns_msg* msg; - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - if(now > d->ttl) - return NULL; - msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */ - if(!msg) - return NULL; - msg->rep->flags = BIT_QR; /* reply, no AA, no error */ - msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ - msg->rep->qdcount = 1; - msg->rep->ttl = d->ttl - now; - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - msg->rep->security = sec_status_unchecked; - msg->rep->an_numrrsets = 1; - msg->rep->ns_numrrsets = 0; - msg->rep->ar_numrrsets = 0; - msg->rep->rrset_count = 1; - msg->rep->reason_bogus = LDNS_EDE_NONE; - msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); - if(!msg->rep->rrsets[0]) /* copy CNAME */ - return NULL; - return msg; -} - -/** synthesize DNAME+CNAME response from cached DNAME item */ -static struct dns_msg* -synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, - time_t now, struct query_info* q, enum sec_status* sec_status) -{ - struct dns_msg* msg; - struct ub_packed_rrset_key* ck; - struct packed_rrset_data* newd, *d = (struct packed_rrset_data*) - rrset->entry.data; - uint8_t* newname, *dtarg = NULL; - size_t newlen, dtarglen; - if(now > d->ttl) - return NULL; - /* only allow validated (with DNSSEC) DNAMEs used from cache - * for insecure DNAMEs, query again. */ - *sec_status = d->security; - /* return sec status, so the status of the CNAME can be checked - * by the calling routine. */ - msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */ - if(!msg) - return NULL; - msg->rep->flags = BIT_QR; /* reply, no AA, no error */ - msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ - msg->rep->qdcount = 1; - msg->rep->ttl = d->ttl - now; - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - msg->rep->security = sec_status_unchecked; - msg->rep->an_numrrsets = 1; - msg->rep->ns_numrrsets = 0; - msg->rep->ar_numrrsets = 0; - msg->rep->rrset_count = 1; - msg->rep->reason_bogus = LDNS_EDE_NONE; - msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); - if(!msg->rep->rrsets[0]) /* copy DNAME */ - return NULL; - /* synth CNAME rrset */ - get_cname_target(rrset, &dtarg, &dtarglen); - if(!dtarg) - return NULL; - newlen = q->qname_len + dtarglen - rrset->rk.dname_len; - if(newlen > LDNS_MAX_DOMAINLEN) { - msg->rep->flags |= LDNS_RCODE_YXDOMAIN; - return msg; - } - newname = (uint8_t*)regional_alloc(region, newlen); - if(!newname) - return NULL; - /* new name is concatenation of qname front (without DNAME owner) - * and DNAME target name */ - memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len); - memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen); - /* create rest of CNAME rrset */ - ck = (struct ub_packed_rrset_key*)regional_alloc(region, - sizeof(struct ub_packed_rrset_key)); - if(!ck) - return NULL; - memset(&ck->entry, 0, sizeof(ck->entry)); - msg->rep->rrsets[1] = ck; - ck->entry.key = ck; - ck->rk.type = htons(LDNS_RR_TYPE_CNAME); - ck->rk.rrset_class = rrset->rk.rrset_class; - ck->rk.flags = 0; - ck->rk.dname = regional_alloc_init(region, q->qname, q->qname_len); - if(!ck->rk.dname) - return NULL; - ck->rk.dname_len = q->qname_len; - ck->entry.hash = rrset_key_hash(&ck->rk); - newd = (struct packed_rrset_data*)regional_alloc_zero(region, - sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t) - + newlen); - if(!newd) - return NULL; - ck->entry.data = newd; - newd->ttl = 0; /* 0 for synthesized CNAME TTL */ - newd->count = 1; - newd->rrsig_count = 0; - newd->trust = rrset_trust_ans_noAA; - newd->rr_len = (size_t*)((uint8_t*)newd + - sizeof(struct packed_rrset_data)); - newd->rr_len[0] = newlen + sizeof(uint16_t); - packed_rrset_ptr_fixup(newd); - newd->rr_ttl[0] = newd->ttl; - msg->rep->ttl = newd->ttl; - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl); - msg->rep->serve_expired_ttl = newd->ttl + SERVE_EXPIRED_TTL; - sldns_write_uint16(newd->rr_data[0], newlen); - memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen); - msg->rep->an_numrrsets ++; - msg->rep->rrset_count ++; - return msg; -} - -/** Fill TYPE_ANY response with some data from cache */ -static struct dns_msg* -fill_any(struct module_env* env, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - struct regional* region) -{ - time_t now = *env->now; - struct dns_msg* msg = NULL; - uint16_t lookup[] = {LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA, - LDNS_RR_TYPE_MX, LDNS_RR_TYPE_SOA, LDNS_RR_TYPE_NS, - LDNS_RR_TYPE_DNAME, 0}; - int i, num=6; /* number of RR types to look up */ - log_assert(lookup[num] == 0); - - if(env->cfg->deny_any) { - /* return empty message */ - msg = dns_msg_create(qname, qnamelen, qtype, qclass, - region, 0); - if(!msg) { - return NULL; - } - /* set NOTIMPL for RFC 8482 */ - msg->rep->flags |= LDNS_RCODE_NOTIMPL; - msg->rep->security = sec_status_indeterminate; - return msg; - } - - for(i=0; irrset_cache, qname, qnamelen, lookup[i], - qclass, 0, now, 0); - struct packed_rrset_data *d; - if(!rrset) - continue; - - /* only if rrset from answer section */ - d = (struct packed_rrset_data*)rrset->entry.data; - if(d->trust == rrset_trust_add_noAA || - d->trust == rrset_trust_auth_noAA || - d->trust == rrset_trust_add_AA || - d->trust == rrset_trust_auth_AA) { - lock_rw_unlock(&rrset->entry.lock); - continue; - } - - /* create msg if none */ - if(!msg) { - msg = dns_msg_create(qname, qnamelen, qtype, qclass, - region, (size_t)(num-i)); - if(!msg) { - lock_rw_unlock(&rrset->entry.lock); - return NULL; - } - } - - /* add RRset to response */ - if(!dns_msg_ansadd(msg, region, rrset, now)) { - lock_rw_unlock(&rrset->entry.lock); - return NULL; - } - lock_rw_unlock(&rrset->entry.lock); - } - return msg; -} - -struct dns_msg* -dns_cache_lookup(struct module_env* env, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint16_t flags, struct regional* region, struct regional* scratch, - int no_partial, uint8_t* dpname, size_t dpnamelen) -{ - struct lruhash_entry* e; - struct query_info k; - hashvalue_type h; - time_t now = *env->now; - struct ub_packed_rrset_key* rrset; - - /* lookup first, this has both NXdomains and ANSWER responses */ - k.qname = qname; - k.qname_len = qnamelen; - k.qtype = qtype; - k.qclass = qclass; - k.local_alias = NULL; - h = query_info_hash(&k, flags); - e = slabhash_lookup(env->msg_cache, h, &k, 0); - if(e) { - struct msgreply_entry* key = (struct msgreply_entry*)e->key; - struct reply_info* data = (struct reply_info*)e->data; - struct dns_msg* msg = tomsg(env, &key->key, data, region, now, 0, - scratch); - if(msg) { - lock_rw_unlock(&e->lock); - return msg; - } - /* could be msg==NULL; due to TTL or not all rrsets available */ - lock_rw_unlock(&e->lock); - } - - /* see if a DNAME exists. Checked for first, to enforce that DNAMEs - * are more important, the CNAME is resynthesized and thus - * consistent with the DNAME */ - if(!no_partial && - (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now, - LDNS_RR_TYPE_DNAME, 1, 0, NULL, 0))) { - /* synthesize a DNAME+CNAME message based on this */ - enum sec_status sec_status = sec_status_unchecked; - struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k, - &sec_status); - if(msg) { - struct ub_packed_rrset_key* cname_rrset; - lock_rw_unlock(&rrset->entry.lock); - /* now, after unlocking the DNAME rrset lock, - * check the sec_status, and see if we need to look - * up the CNAME record associated before it can - * be used */ - /* normally, only secure DNAMEs allowed from cache*/ - if(sec_status == sec_status_secure) - return msg; - /* but if we have a CNAME cached with this name, then we - * have previously already allowed this name to pass. - * the next cache lookup is going to fetch that CNAME itself, - * but it is better to have the (unsigned)DNAME + CNAME in - * that case */ - cname_rrset = rrset_cache_lookup( - env->rrset_cache, qname, qnamelen, - LDNS_RR_TYPE_CNAME, qclass, 0, now, 0); - if(cname_rrset) { - /* CNAME already synthesized by - * synth_dname_msg routine, so we can - * straight up return the msg */ - lock_rw_unlock(&cname_rrset->entry.lock); - return msg; - } - } else { - lock_rw_unlock(&rrset->entry.lock); - } - } - - /* see if we have CNAME for this domain, - * but not for DS records (which are part of the parent) */ - if(!no_partial && qtype != LDNS_RR_TYPE_DS && - (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, - LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) { - uint8_t* wc = NULL; - size_t wl; - /* if the rrset is not a wildcard expansion, with wcname */ - /* because, if we return that CNAME rrset on its own, it is - * missing the NSEC or NSEC3 proof */ - if(!(val_rrset_wildcard(rrset, &wc, &wl) && wc != NULL)) { - struct dns_msg* msg = rrset_msg(rrset, region, now, &k); - if(msg) { - lock_rw_unlock(&rrset->entry.lock); - return msg; - } - } - lock_rw_unlock(&rrset->entry.lock); - } - - /* construct DS, DNSKEY messages from rrset cache. */ - if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY) && - (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, - qtype, qclass, 0, now, 0))) { - /* if the rrset is from the additional section, and the - * signatures have fallen off, then do not synthesize a msg - * instead, allow a full query for signed results to happen. - * Forego all rrset data from additional section, because - * some signatures may not be present and cause validation - * failure. - */ - struct packed_rrset_data *d = (struct packed_rrset_data*) - rrset->entry.data; - if(d->trust != rrset_trust_add_noAA && - d->trust != rrset_trust_add_AA && - (qtype == LDNS_RR_TYPE_DS || - (d->trust != rrset_trust_auth_noAA - && d->trust != rrset_trust_auth_AA) )) { - struct dns_msg* msg = rrset_msg(rrset, region, now, &k); - if(msg) { - lock_rw_unlock(&rrset->entry.lock); - return msg; - } - } - lock_rw_unlock(&rrset->entry.lock); - } - - /* stop downwards cache search on NXDOMAIN. - * Empty nonterminals are NOERROR, so an NXDOMAIN for foo - * means bla.foo also does not exist. The DNSSEC proofs are - * the same. We search upwards for NXDOMAINs. */ - if(env->cfg->harden_below_nxdomain) { - while(!dname_is_root(k.qname)) { - if(dpname && dpnamelen - && !dname_subdomain_c(k.qname, dpname)) - break; /* no synth nxdomain above the stub */ - dname_remove_label(&k.qname, &k.qname_len); - h = query_info_hash(&k, flags); - e = slabhash_lookup(env->msg_cache, h, &k, 0); - if(!e && k.qtype != LDNS_RR_TYPE_A && - env->cfg->qname_minimisation) { - k.qtype = LDNS_RR_TYPE_A; - h = query_info_hash(&k, flags); - e = slabhash_lookup(env->msg_cache, h, &k, 0); - } - if(e) { - struct reply_info* data = (struct reply_info*)e->data; - struct dns_msg* msg; - if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN - && data->security == sec_status_secure - && (data->an_numrrsets == 0 || - ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME) - && (msg=tomsg(env, &k, data, region, now, 0, scratch))) { - lock_rw_unlock(&e->lock); - msg->qinfo.qname=qname; - msg->qinfo.qname_len=qnamelen; - /* check that DNSSEC really works out */ - msg->rep->security = sec_status_unchecked; - iter_scrub_nxdomain(msg); - return msg; - } - lock_rw_unlock(&e->lock); - } - k.qtype = qtype; - } - } - - /* fill common RR types for ANY response to avoid requery */ - if(qtype == LDNS_RR_TYPE_ANY) { - return fill_any(env, qname, qnamelen, qtype, qclass, region); - } - - return NULL; -} - -int -dns_cache_store(struct module_env* env, struct query_info* msgqinf, - struct reply_info* msgrep, int is_referral, time_t leeway, int pside, - struct regional* region, uint32_t flags, time_t qstarttime) -{ - struct reply_info* rep = NULL; - /* alloc, malloc properly (not in region, like msg is) */ - rep = reply_info_copy(msgrep, env->alloc, NULL); - if(!rep) - return 0; - /* ttl must be relative ;i.e. 0..86400 not time(0)+86400. - * the env->now is added to message and RRsets in this routine. */ - /* the leeway is used to invalidate other rrsets earlier */ - if(is_referral) { - /* store rrsets */ - struct rrset_ref ref; - size_t i; - for(i=0; irrset_count; i++) { - packed_rrset_ttl_add((struct packed_rrset_data*) - rep->rrsets[i]->entry.data, *env->now); - ref.key = rep->rrsets[i]; - ref.id = rep->rrsets[i]->id; - /*ignore ret: it was in the cache, ref updated */ - /* no leeway for typeNS */ - (void)rrset_cache_update(env->rrset_cache, &ref, - env->alloc, - ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS - && !pside) ? qstarttime:*env->now + leeway)); - } - reply_info_delete(rep, NULL); - return 1; - } else { - /* store msg, and rrsets */ - struct query_info qinf; - hashvalue_type h; - - qinf = *msgqinf; - qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len); - if(!qinf.qname) { - reply_info_parsedelete(rep, env->alloc); - return 0; - } - /* fixup flags to be sensible for a reply based on the cache */ - /* this module means that RA is available. It is an answer QR. - * Not AA from cache. Not CD in cache (depends on client bit). */ - rep->flags |= (BIT_RA | BIT_QR); - rep->flags &= ~(BIT_AA | BIT_CD); - h = query_info_hash(&qinf, (uint16_t)flags); - dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep, - flags, region, qstarttime); - /* qname is used inside query_info_entrysetup, and set to - * NULL. If it has not been used, free it. free(0) is safe. */ - free(qinf.qname); - } - return 1; -} - -int -dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo, - time_t adjust, uint16_t flags) -{ - struct msgreply_entry* msg; - msg = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len, - qinfo->qtype, qinfo->qclass, flags, *env->now, 1); - if(msg) { - struct reply_info* rep = (struct reply_info*)msg->entry.data; - if(rep) { - rep->prefetch_ttl += adjust; - lock_rw_unlock(&msg->entry.lock); - return 1; - } - lock_rw_unlock(&msg->entry.lock); - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/services/cache/dns.h b/crates/libunbound-sys/unbound/services/cache/dns.h deleted file mode 100644 index 147f992c..00000000 --- a/crates/libunbound-sys/unbound/services/cache/dns.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - * services/cache/dns.h - Cache services for DNS using msg and rrset caches. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the DNS cache. - */ - -#ifndef SERVICES_CACHE_DNS_H -#define SERVICES_CACHE_DNS_H -#include "util/storage/lruhash.h" -#include "util/data/msgreply.h" -struct module_env; -struct query_info; -struct reply_info; -struct regional; -struct delegpt; - -/** Flags to control behavior of dns_cache_store() and dns_cache_store_msg(). - * Must be an unsigned 32-bit value larger than 0xffff */ - -/** Allow caching a DNS message with a zero TTL. */ -#define DNSCACHE_STORE_ZEROTTL 0x100000 - -/** - * Region allocated message reply - */ -struct dns_msg { - /** query info */ - struct query_info qinfo; - /** reply info - ptr to packed repinfo structure */ - struct reply_info *rep; -}; - -/** - * Allocate a dns_msg with malloc/alloc structure and store in dns cache. - * - * @param env: environment, with alloc structure and dns cache. - * @param qinf: query info, the query for which answer is stored. - * this is allocated in a region, and will be copied to malloc area - * before insertion. - * @param rep: reply in dns_msg from dns_alloc_msg for example. - * this is allocated in a region, and will be copied to malloc area - * before insertion. - * @param is_referral: If true, then the given message to be stored is a - * referral. The cache implementation may use this as a hint. - * It will store only the RRsets, not the message. - * @param leeway: TTL value, if not 0, other rrsets are considered expired - * that many seconds before actual TTL expiry. - * @param pside: if true, information came from a server which was fetched - * from the parentside of the zonecut. This means that the type NS - * can be updated to full TTL even in prefetch situations. - * @param region: region to allocate better entries from cache into. - * (used when is_referral is false). - * @param flags: flags with BIT_CD for AAAA queries in dns64 translation. - * The higher 16 bits are used internally to customize the cache policy. - * (See DNSCACHE_STORE_xxx flags). - * @param qstarttime: time when the query was started, and thus when the - * delegations were looked up. - * @return 0 on alloc error (out of memory). - */ -int dns_cache_store(struct module_env* env, struct query_info* qinf, - struct reply_info* rep, int is_referral, time_t leeway, int pside, - struct regional* region, uint32_t flags, time_t qstarttime); - -/** - * Store message in the cache. Stores in message cache and rrset cache. - * Both qinfo and rep should be malloced and are put in the cache. - * They should not be used after this call, as they are then in shared cache. - * Does not return errors, they are logged and only lead to less cache. - * - * @param env: module environment with the DNS cache. - * @param qinfo: query info - * @param hash: hash over qinfo. - * @param rep: reply info, together with qinfo makes up the message. - * Adjusts the reply info TTLs to absolute time. - * @param leeway: TTL value, if not 0, other rrsets are considered expired - * that many seconds before actual TTL expiry. - * @param pside: if true, information came from a server which was fetched - * from the parentside of the zonecut. This means that the type NS - * can be updated to full TTL even in prefetch situations. - * @param qrep: message that can be altered with better rrs from cache. - * @param flags: customization flags for the cache policy. - * @param qstarttime: time when the query was started, and thus when the - * delegations were looked up. - * @param region: to allocate into for qmsg. - */ -void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, - hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside, - struct reply_info* qrep, uint32_t flags, struct regional* region, - time_t qstarttime); - -/** - * Find a delegation from the cache. - * @param env: module environment with the DNS cache. - * @param qname: query name. - * @param qnamelen: length of qname. - * @param qtype: query type. - * @param qclass: query class. - * @param region: where to allocate result delegation. - * @param msg: if not NULL, delegation message is returned here, synthesized - * from the cache. - * @param timenow: the time now, for checking if TTL on cache entries is OK. - * @param noexpiredabove: if set, no expired NS rrsets above the one found - * are tolerated. It only returns delegations where the delegations above - * it are valid. - * @param expiretop: if not NULL, name where check for expiry ends for - * noexpiredabove. - * @param expiretoplen: length of expiretop dname. - * @return new delegation or NULL on error or if not found in cache. - */ -struct delegpt* dns_cache_find_delegation(struct module_env* env, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - struct regional* region, struct dns_msg** msg, time_t timenow, - int noexpiredabove, uint8_t* expiretop, size_t expiretoplen); - -/** - * generate dns_msg from cached message - * @param env: module environment with the DNS cache. NULL if the LRU from cache - * does not need to be touched. - * @param q: query info, contains qname that will make up the dns message. - * @param r: reply info that, together with qname, will make up the dns message. - * @param region: where to allocate dns message. - * @param now: the time now, for check if TTL on cache entry is ok. - * @param allow_expired: if true and serve-expired is enabled, it will allow - * for expired dns_msg to be generated based on the configured serve-expired - * logic. - * @param scratch: where to allocate temporary data. - * */ -struct dns_msg* tomsg(struct module_env* env, struct query_info* q, - struct reply_info* r, struct regional* region, time_t now, - int allow_expired, struct regional* scratch); - -/** - * Find cached message - * @param env: module environment with the DNS cache. - * @param qname: query name. - * @param qnamelen: length of qname. - * @param qtype: query type. - * @param qclass: query class. - * @param flags: flags with BIT_CD for AAAA queries in dns64 translation. - * @param region: where to allocate result. - * @param scratch: where to allocate temporary data. - * @param no_partial: if true, only complete messages and not a partial - * one (with only the start of the CNAME chain and not the rest). - * @param dpname: if not NULL, do not return NXDOMAIN above this name. - * @param dpnamelen: length of dpname. - * @return new response message (alloced in region, rrsets do not have IDs). - * or NULL on error or if not found in cache. - * TTLs are made relative to the current time. - */ -struct dns_msg* dns_cache_lookup(struct module_env* env, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint16_t flags, struct regional* region, struct regional* scratch, - int no_partial, uint8_t* dpname, size_t dpnamelen); - -/** - * find and add A and AAAA records for missing nameservers in delegpt - * @param env: module environment with rrset cache - * @param qclass: which class to look in. - * @param region: where to store new dp info. - * @param dp: delegation point to fill missing entries. - * @return false on alloc failure. - */ -int cache_fill_missing(struct module_env* env, uint16_t qclass, - struct regional* region, struct delegpt* dp); - -/** - * Utility, create new, unpacked data structure for cache response. - * QR bit set, no AA. Query set as indicated. Space for number of rrsets. - * @param qname: query section name - * @param qnamelen: len of qname - * @param qtype: query section type - * @param qclass: query section class - * @param region: where to alloc. - * @param capacity: number of rrsets space to create in the array. - * @return new dns_msg struct or NULL on mem fail. - */ -struct dns_msg* dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, - uint16_t qclass, struct regional* region, size_t capacity); - -/** - * Add rrset to authority section in unpacked dns_msg message. Must have enough - * space left, does not grow the array. - * @param msg: msg to put it in. - * @param region: region to alloc in - * @param rrset: to add in authority section - * @param now: now. - * @return true if worked, false on fail - */ -int dns_msg_authadd(struct dns_msg* msg, struct regional* region, - struct ub_packed_rrset_key* rrset, time_t now); - -/** - * Add rrset to authority section in unpacked dns_msg message. Must have enough - * space left, does not grow the array. - * @param msg: msg to put it in. - * @param region: region to alloc in - * @param rrset: to add in authority section - * @param now: now. - * @return true if worked, false on fail - */ -int dns_msg_ansadd(struct dns_msg* msg, struct regional* region, - struct ub_packed_rrset_key* rrset, time_t now); - -/** - * Adjust the prefetch_ttl for a cached message. This adds a value to the - * prefetch ttl - postponing the time when it will be prefetched for future - * incoming queries. - * @param env: module environment with caches and time. - * @param qinfo: query info for the query that needs adjustment. - * @param adjust: time in seconds to add to the prefetch_leeway. - * @param flags: flags with BIT_CD for AAAA queries in dns64 translation. - * @return false if not in cache. true if added. - */ -int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo, - time_t adjust, uint16_t flags); - -/** lookup message in message cache - * the returned nonNULL entry is locked and has to be unlocked by the caller */ -struct msgreply_entry* msg_cache_lookup(struct module_env* env, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint16_t flags, time_t now, int wr); - -/** - * Remove entry from the message cache. For unwanted entries. - * @param env: with message cache. - * @param qname: query name, in wireformat - * @param qnamelen: length of qname, including terminating 0. - * @param qtype: query type, host order. - * @param qclass: query class, host order. - * @param flags: flags - */ -void msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags); - -#endif /* SERVICES_CACHE_DNS_H */ diff --git a/crates/libunbound-sys/unbound/services/cache/infra.c b/crates/libunbound-sys/unbound/services/cache/infra.c deleted file mode 100644 index 31462d13..00000000 --- a/crates/libunbound-sys/unbound/services/cache/infra.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * services/cache/infra.c - infrastructure cache, server rtt and capabilities - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the infrastructure cache. - */ -#include "config.h" -#include "sldns/rrdef.h" -#include "sldns/str2wire.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "services/cache/infra.h" -#include "util/storage/slabhash.h" -#include "util/storage/lookup3.h" -#include "util/data/dname.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "iterator/iterator.h" - -/** Timeout when only a single probe query per IP is allowed. */ -#define PROBE_MAXRTO 12000 /* in msec */ - -/** number of timeouts for a type when the domain can be blocked ; - * even if another type has completely rtt maxed it, the different type - * can do this number of packets (until those all timeout too) */ -#define TIMEOUT_COUNT_MAX 3 - -/** ratelimit value for delegation point */ -int infra_dp_ratelimit = 0; - -/** ratelimit value for client ip addresses, - * in queries per second. */ -int infra_ip_ratelimit = 0; - -/** ratelimit value for client ip addresses, - * in queries per second. - * For clients with a valid DNS Cookie. */ -int infra_ip_ratelimit_cookie = 0; - -size_t -infra_sizefunc(void* k, void* ATTR_UNUSED(d)) -{ - struct infra_key* key = (struct infra_key*)k; - return sizeof(*key) + sizeof(struct infra_data) + key->namelen - + lock_get_mem(&key->entry.lock); -} - -int -infra_compfunc(void* key1, void* key2) -{ - struct infra_key* k1 = (struct infra_key*)key1; - struct infra_key* k2 = (struct infra_key*)key2; - int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen); - if(r != 0) - return r; - if(k1->namelen != k2->namelen) { - if(k1->namelen < k2->namelen) - return -1; - return 1; - } - return query_dname_compare(k1->zonename, k2->zonename); -} - -void -infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg)) -{ - struct infra_key* key = (struct infra_key*)k; - if(!key) - return; - lock_rw_destroy(&key->entry.lock); - free(key->zonename); - free(key); -} - -void -infra_deldatafunc(void* d, void* ATTR_UNUSED(arg)) -{ - struct infra_data* data = (struct infra_data*)d; - free(data); -} - -size_t -rate_sizefunc(void* k, void* ATTR_UNUSED(d)) -{ - struct rate_key* key = (struct rate_key*)k; - return sizeof(*key) + sizeof(struct rate_data) + key->namelen - + lock_get_mem(&key->entry.lock); -} - -int -rate_compfunc(void* key1, void* key2) -{ - struct rate_key* k1 = (struct rate_key*)key1; - struct rate_key* k2 = (struct rate_key*)key2; - if(k1->namelen != k2->namelen) { - if(k1->namelen < k2->namelen) - return -1; - return 1; - } - return query_dname_compare(k1->name, k2->name); -} - -void -rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg)) -{ - struct rate_key* key = (struct rate_key*)k; - if(!key) - return; - lock_rw_destroy(&key->entry.lock); - free(key->name); - free(key); -} - -void -rate_deldatafunc(void* d, void* ATTR_UNUSED(arg)) -{ - struct rate_data* data = (struct rate_data*)d; - free(data); -} - -/** find or create element in domainlimit tree */ -static struct domain_limit_data* domain_limit_findcreate( - struct infra_cache* infra, char* name) -{ - uint8_t* nm; - int labs; - size_t nmlen; - struct domain_limit_data* d; - - /* parse name */ - nm = sldns_str2wire_dname(name, &nmlen); - if(!nm) { - log_err("could not parse %s", name); - return NULL; - } - labs = dname_count_labels(nm); - - /* can we find it? */ - d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits, - nm, nmlen, labs, LDNS_RR_CLASS_IN); - if(d) { - free(nm); - return d; - } - - /* create it */ - d = (struct domain_limit_data*)calloc(1, sizeof(*d)); - if(!d) { - free(nm); - return NULL; - } - d->node.node.key = &d->node; - d->node.name = nm; - d->node.len = nmlen; - d->node.labs = labs; - d->node.dclass = LDNS_RR_CLASS_IN; - d->lim = -1; - d->below = -1; - if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen, - labs, LDNS_RR_CLASS_IN)) { - log_err("duplicate element in domainlimit tree"); - free(nm); - free(d); - return NULL; - } - return d; -} - -/** insert rate limit configuration into lookup tree */ -static int infra_ratelimit_cfg_insert(struct infra_cache* infra, - struct config_file* cfg) -{ - struct config_str2list* p; - struct domain_limit_data* d; - for(p = cfg->ratelimit_for_domain; p; p = p->next) { - d = domain_limit_findcreate(infra, p->str); - if(!d) - return 0; - d->lim = atoi(p->str2); - } - for(p = cfg->ratelimit_below_domain; p; p = p->next) { - d = domain_limit_findcreate(infra, p->str); - if(!d) - return 0; - d->below = atoi(p->str2); - } - return 1; -} - -/** setup domain limits tree (0 on failure) */ -static int -setup_domain_limits(struct infra_cache* infra, struct config_file* cfg) -{ - name_tree_init(&infra->domain_limits); - if(!infra_ratelimit_cfg_insert(infra, cfg)) { - return 0; - } - name_tree_init_parents(&infra->domain_limits); - return 1; -} - -struct infra_cache* -infra_create(struct config_file* cfg) -{ - struct infra_cache* infra = (struct infra_cache*)calloc(1, - sizeof(struct infra_cache)); - size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+ - sizeof(struct infra_data)+INFRA_BYTES_NAME); - if(!infra) { - return NULL; - } - infra->hosts = slabhash_create(cfg->infra_cache_slabs, - INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc, - &infra_delkeyfunc, &infra_deldatafunc, NULL); - if(!infra->hosts) { - free(infra); - return NULL; - } - infra->host_ttl = cfg->host_ttl; - infra->infra_keep_probing = cfg->infra_keep_probing; - infra_dp_ratelimit = cfg->ratelimit; - infra->domain_rates = slabhash_create(cfg->ratelimit_slabs, - INFRA_HOST_STARTSIZE, cfg->ratelimit_size, - &rate_sizefunc, &rate_compfunc, &rate_delkeyfunc, - &rate_deldatafunc, NULL); - if(!infra->domain_rates) { - infra_delete(infra); - return NULL; - } - /* insert config data into ratelimits */ - if(!setup_domain_limits(infra, cfg)) { - infra_delete(infra); - return NULL; - } - infra_ip_ratelimit = cfg->ip_ratelimit; - infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs, - INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc, - &ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL); - if(!infra->client_ip_rates) { - infra_delete(infra); - return NULL; - } - return infra; -} - -/** delete domain_limit entries */ -static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - if(n) { - free(((struct domain_limit_data*)n)->node.name); - free(n); - } -} - -void -infra_delete(struct infra_cache* infra) -{ - if(!infra) - return; - slabhash_delete(infra->hosts); - slabhash_delete(infra->domain_rates); - traverse_postorder(&infra->domain_limits, domain_limit_free, NULL); - slabhash_delete(infra->client_ip_rates); - free(infra); -} - -struct infra_cache* -infra_adjust(struct infra_cache* infra, struct config_file* cfg) -{ - size_t maxmem; - if(!infra) - return infra_create(cfg); - infra->host_ttl = cfg->host_ttl; - infra->infra_keep_probing = cfg->infra_keep_probing; - infra_dp_ratelimit = cfg->ratelimit; - infra_ip_ratelimit = cfg->ip_ratelimit; - maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+ - sizeof(struct infra_data)+INFRA_BYTES_NAME); - /* divide cachesize by slabs and multiply by slabs, because if the - * cachesize is not an even multiple of slabs, that is the resulting - * size of the slabhash */ - if(!slabhash_is_size(infra->hosts, maxmem, cfg->infra_cache_slabs) || - !slabhash_is_size(infra->domain_rates, cfg->ratelimit_size, - cfg->ratelimit_slabs) || - !slabhash_is_size(infra->client_ip_rates, cfg->ip_ratelimit_size, - cfg->ip_ratelimit_slabs)) { - infra_delete(infra); - infra = infra_create(cfg); - } else { - /* reapply domain limits */ - traverse_postorder(&infra->domain_limits, domain_limit_free, - NULL); - if(!setup_domain_limits(infra, cfg)) { - infra_delete(infra); - return NULL; - } - } - return infra; -} - -/** calculate the hash value for a host key - * set use_port to a non-0 number to use the port in - * the hash calculation; 0 to ignore the port.*/ -static hashvalue_type -hash_addr(struct sockaddr_storage* addr, socklen_t addrlen, - int use_port) -{ - hashvalue_type h = 0xab; - /* select the pieces to hash, some OS have changing data inside */ - if(addr_is_ip6(addr, addrlen)) { - struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; - h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h); - if(use_port){ - h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h); - } - h = hashlittle(&in6->sin6_addr, INET6_SIZE, h); - } else { - struct sockaddr_in* in = (struct sockaddr_in*)addr; - h = hashlittle(&in->sin_family, sizeof(in->sin_family), h); - if(use_port){ - h = hashlittle(&in->sin_port, sizeof(in->sin_port), h); - } - h = hashlittle(&in->sin_addr, INET_SIZE, h); - } - return h; -} - -/** calculate infra hash for a key */ -static hashvalue_type -hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name) -{ - return dname_query_hash(name, hash_addr(addr, addrlen, 1)); -} - -/** lookup version that does not check host ttl (you check it) */ -struct lruhash_entry* -infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* name, size_t namelen, int wr) -{ - struct infra_key k; - k.addrlen = addrlen; - memcpy(&k.addr, addr, addrlen); - k.namelen = namelen; - k.zonename = name; - k.entry.hash = hash_infra(addr, addrlen, name); - k.entry.key = (void*)&k; - k.entry.data = NULL; - return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr); -} - -/** init the data elements */ -static void -data_entry_init(struct infra_cache* infra, struct lruhash_entry* e, - time_t timenow) -{ - struct infra_data* data = (struct infra_data*)e->data; - data->ttl = timenow + infra->host_ttl; - rtt_init(&data->rtt); - data->edns_version = 0; - data->edns_lame_known = 0; - data->probedelay = 0; - data->isdnsseclame = 0; - data->rec_lame = 0; - data->lame_type_A = 0; - data->lame_other = 0; - data->timeout_A = 0; - data->timeout_AAAA = 0; - data->timeout_other = 0; -} - -/** - * Create and init a new entry for a host - * @param infra: infra structure with config parameters. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: name of zone - * @param namelen: length of name. - * @param tm: time now. - * @return: the new entry or NULL on malloc failure. - */ -static struct lruhash_entry* -new_entry(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* name, size_t namelen, time_t tm) -{ - struct infra_data* data; - struct infra_key* key = (struct infra_key*)malloc(sizeof(*key)); - if(!key) - return NULL; - data = (struct infra_data*)malloc(sizeof(struct infra_data)); - if(!data) { - free(key); - return NULL; - } - key->zonename = memdup(name, namelen); - if(!key->zonename) { - free(key); - free(data); - return NULL; - } - key->namelen = namelen; - lock_rw_init(&key->entry.lock); - key->entry.hash = hash_infra(addr, addrlen, name); - key->entry.key = (void*)key; - key->entry.data = (void*)data; - key->addrlen = addrlen; - memcpy(&key->addr, addr, addrlen); - data_entry_init(infra, &key->entry, tm); - return &key->entry; -} - -int -infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow, - int* edns_vs, uint8_t* edns_lame_known, int* to) -{ - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - nm, nmlen, 0); - struct infra_data* data; - int wr = 0; - if(e && ((struct infra_data*)e->data)->ttl < timenow) { - /* it expired, try to reuse existing entry */ - int old = ((struct infra_data*)e->data)->rtt.rto; - time_t tprobe = ((struct infra_data*)e->data)->probedelay; - uint8_t tA = ((struct infra_data*)e->data)->timeout_A; - uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA; - uint8_t tother = ((struct infra_data*)e->data)->timeout_other; - lock_rw_unlock(&e->lock); - e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1); - if(e) { - /* if its still there we have a writelock, init */ - /* re-initialise */ - /* do not touch lameness, it may be valid still */ - data_entry_init(infra, e, timenow); - wr = 1; - /* TOP_TIMEOUT remains on reuse */ - if(old >= USEFUL_SERVER_TOP_TIMEOUT) { - ((struct infra_data*)e->data)->rtt.rto - = USEFUL_SERVER_TOP_TIMEOUT; - ((struct infra_data*)e->data)->probedelay = tprobe; - ((struct infra_data*)e->data)->timeout_A = tA; - ((struct infra_data*)e->data)->timeout_AAAA = tAAAA; - ((struct infra_data*)e->data)->timeout_other = tother; - } - } - } - if(!e) { - /* insert new entry */ - if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) - return 0; - data = (struct infra_data*)e->data; - *edns_vs = data->edns_version; - *edns_lame_known = data->edns_lame_known; - *to = rtt_timeout(&data->rtt); - slabhash_insert(infra->hosts, e->hash, e, data, NULL); - return 1; - } - /* use existing entry */ - data = (struct infra_data*)e->data; - *edns_vs = data->edns_version; - *edns_lame_known = data->edns_lame_known; - *to = rtt_timeout(&data->rtt); - if(*to >= PROBE_MAXRTO && (infra->infra_keep_probing || - rtt_notimeout(&data->rtt)*4 <= *to)) { - /* delay other queries, this is the probe query */ - if(!wr) { - lock_rw_unlock(&e->lock); - e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1); - if(!e) { /* flushed from cache real fast, no use to - allocate just for the probedelay */ - return 1; - } - data = (struct infra_data*)e->data; - } - /* add 999 to round up the timeout value from msec to sec, - * then add a whole second so it is certain that this probe - * has timed out before the next is allowed */ - data->probedelay = timenow + ((*to)+1999)/1000; - } - lock_rw_unlock(&e->lock); - return 1; -} - -int -infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow, - int dnsseclame, int reclame, uint16_t qtype) -{ - struct infra_data* data; - struct lruhash_entry* e; - int needtoinsert = 0; - e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1); - if(!e) { - /* insert it */ - if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) { - log_err("set_lame: malloc failure"); - return 0; - } - needtoinsert = 1; - } else if( ((struct infra_data*)e->data)->ttl < timenow) { - /* expired, reuse existing entry */ - data_entry_init(infra, e, timenow); - } - /* got an entry, now set the zone lame */ - data = (struct infra_data*)e->data; - /* merge data (if any) */ - if(dnsseclame) - data->isdnsseclame = 1; - if(reclame) - data->rec_lame = 1; - if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A) - data->lame_type_A = 1; - if(!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A) - data->lame_other = 1; - /* done */ - if(needtoinsert) - slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); - else { lock_rw_unlock(&e->lock); } - return 1; -} - -void -infra_update_tcp_works(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm, - size_t nmlen) -{ - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - nm, nmlen, 1); - struct infra_data* data; - if(!e) - return; /* doesn't exist */ - data = (struct infra_data*)e->data; - if(data->rtt.rto >= RTT_MAX_TIMEOUT) - /* do not disqualify this server altogether, it is better - * than nothing */ - data->rtt.rto = RTT_MAX_TIMEOUT-1000; - lock_rw_unlock(&e->lock); -} - -int -infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype, - int roundtrip, int orig_rtt, time_t timenow) -{ - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - nm, nmlen, 1); - struct infra_data* data; - int needtoinsert = 0, expired = 0; - int rto = 1; - time_t oldprobedelay = 0; - if(!e) { - if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) - return 0; - needtoinsert = 1; - } else if(((struct infra_data*)e->data)->ttl < timenow) { - oldprobedelay = ((struct infra_data*)e->data)->probedelay; - data_entry_init(infra, e, timenow); - expired = 1; - } - /* have an entry, update the rtt */ - data = (struct infra_data*)e->data; - if(roundtrip == -1) { - if(needtoinsert || expired) { - /* timeout on entry that has expired before the timer - * keep old timeout from the function caller */ - data->rtt.rto = orig_rtt; - data->probedelay = oldprobedelay; - } - rtt_lost(&data->rtt, orig_rtt); - if(qtype == LDNS_RR_TYPE_A) { - if(data->timeout_A < TIMEOUT_COUNT_MAX) - data->timeout_A++; - } else if(qtype == LDNS_RR_TYPE_AAAA) { - if(data->timeout_AAAA < TIMEOUT_COUNT_MAX) - data->timeout_AAAA++; - } else { - if(data->timeout_other < TIMEOUT_COUNT_MAX) - data->timeout_other++; - } - } else { - /* if we got a reply, but the old timeout was above server - * selection height, delete the timeout so the server is - * fully available again */ - if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT) - rtt_init(&data->rtt); - rtt_update(&data->rtt, roundtrip); - data->probedelay = 0; - if(qtype == LDNS_RR_TYPE_A) - data->timeout_A = 0; - else if(qtype == LDNS_RR_TYPE_AAAA) - data->timeout_AAAA = 0; - else data->timeout_other = 0; - } - if(data->rtt.rto > 0) - rto = data->rtt.rto; - - if(needtoinsert) - slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); - else { lock_rw_unlock(&e->lock); } - return rto; -} - -long long infra_get_host_rto(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm, - size_t nmlen, struct rtt_info* rtt, int* delay, time_t timenow, - int* tA, int* tAAAA, int* tother) -{ - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - nm, nmlen, 0); - struct infra_data* data; - long long ttl = -2; - if(!e) return -1; - data = (struct infra_data*)e->data; - if(data->ttl >= timenow) { - ttl = (long long)(data->ttl - timenow); - memmove(rtt, &data->rtt, sizeof(*rtt)); - if(timenow < data->probedelay) - *delay = (int)(data->probedelay - timenow); - else *delay = 0; - } - *tA = (int)data->timeout_A; - *tAAAA = (int)data->timeout_AAAA; - *tother = (int)data->timeout_other; - lock_rw_unlock(&e->lock); - return ttl; -} - -int -infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version, - time_t timenow) -{ - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - nm, nmlen, 1); - struct infra_data* data; - int needtoinsert = 0; - if(!e) { - if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) - return 0; - needtoinsert = 1; - } else if(((struct infra_data*)e->data)->ttl < timenow) { - data_entry_init(infra, e, timenow); - } - /* have an entry, update the rtt, and the ttl */ - data = (struct infra_data*)e->data; - /* do not update if noEDNS and stored is yesEDNS */ - if(!(edns_version == -1 && (data->edns_version != -1 && - data->edns_lame_known))) { - data->edns_version = edns_version; - data->edns_lame_known = 1; - } - - if(needtoinsert) - slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); - else { lock_rw_unlock(&e->lock); } - return 1; -} - -int -infra_get_lame_rtt(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* name, size_t namelen, uint16_t qtype, - int* lame, int* dnsseclame, int* reclame, int* rtt, time_t timenow) -{ - struct infra_data* host; - struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, - name, namelen, 0); - if(!e) - return 0; - host = (struct infra_data*)e->data; - *rtt = rtt_unclamped(&host->rtt); - if(host->rtt.rto >= PROBE_MAXRTO && timenow >= host->probedelay - && infra->infra_keep_probing) { - /* single probe, keep probing */ - if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT) - *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; - } else if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay - && rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) { - /* single probe for this domain, and we are not probing */ - /* unless the query type allows a probe to happen */ - if(qtype == LDNS_RR_TYPE_A) { - if(host->timeout_A >= TIMEOUT_COUNT_MAX) - *rtt = USEFUL_SERVER_TOP_TIMEOUT; - else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; - } else if(qtype == LDNS_RR_TYPE_AAAA) { - if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX) - *rtt = USEFUL_SERVER_TOP_TIMEOUT; - else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; - } else { - if(host->timeout_other >= TIMEOUT_COUNT_MAX) - *rtt = USEFUL_SERVER_TOP_TIMEOUT; - else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; - } - } - /* expired entry */ - if(timenow > host->ttl) { - - /* see if this can be a re-probe of an unresponsive server */ - /* minus 1000 because that is outside of the RTTBAND, so - * blacklisted servers stay blacklisted if this is chosen */ - if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) { - lock_rw_unlock(&e->lock); - *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; - *lame = 0; - *dnsseclame = 0; - *reclame = 0; - return 1; - } - lock_rw_unlock(&e->lock); - return 0; - } - /* check lameness first */ - if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) { - lock_rw_unlock(&e->lock); - *lame = 1; - *dnsseclame = 0; - *reclame = 0; - return 1; - } else if(host->lame_other && qtype != LDNS_RR_TYPE_A) { - lock_rw_unlock(&e->lock); - *lame = 1; - *dnsseclame = 0; - *reclame = 0; - return 1; - } else if(host->isdnsseclame) { - lock_rw_unlock(&e->lock); - *lame = 0; - *dnsseclame = 1; - *reclame = 0; - return 1; - } else if(host->rec_lame) { - lock_rw_unlock(&e->lock); - *lame = 0; - *dnsseclame = 0; - *reclame = 1; - return 1; - } - /* no lameness for this type of query */ - lock_rw_unlock(&e->lock); - *lame = 0; - *dnsseclame = 0; - *reclame = 0; - return 1; -} - -int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name, - size_t namelen) -{ - int labs = dname_count_labels(name); - struct domain_limit_data* d = (struct domain_limit_data*) - name_tree_lookup(&infra->domain_limits, name, namelen, labs, - LDNS_RR_CLASS_IN); - if(!d) return infra_dp_ratelimit; - - if(d->node.labs == labs && d->lim != -1) - return d->lim; /* exact match */ - - /* find 'below match' */ - if(d->node.labs == labs) - d = (struct domain_limit_data*)d->node.parent; - while(d) { - if(d->below != -1) - return d->below; - d = (struct domain_limit_data*)d->node.parent; - } - return infra_dp_ratelimit; -} - -size_t ip_rate_sizefunc(void* k, void* ATTR_UNUSED(d)) -{ - struct ip_rate_key* key = (struct ip_rate_key*)k; - return sizeof(*key) + sizeof(struct ip_rate_data) - + lock_get_mem(&key->entry.lock); -} - -int ip_rate_compfunc(void* key1, void* key2) -{ - struct ip_rate_key* k1 = (struct ip_rate_key*)key1; - struct ip_rate_key* k2 = (struct ip_rate_key*)key2; - return sockaddr_cmp_addr(&k1->addr, k1->addrlen, - &k2->addr, k2->addrlen); -} - -void ip_rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg)) -{ - struct ip_rate_key* key = (struct ip_rate_key*)k; - if(!key) - return; - lock_rw_destroy(&key->entry.lock); - free(key); -} - -/** find data item in array, for write access, caller unlocks */ -static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra, - uint8_t* name, size_t namelen, int wr) -{ - struct rate_key key; - hashvalue_type h = dname_query_hash(name, 0xab); - memset(&key, 0, sizeof(key)); - key.name = name; - key.namelen = namelen; - key.entry.hash = h; - return slabhash_lookup(infra->domain_rates, h, &key, wr); -} - -/** find data item in array for ip addresses */ -static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, int wr) -{ - struct ip_rate_key key; - hashvalue_type h = hash_addr(addr, addrlen, 0); - memset(&key, 0, sizeof(key)); - key.addr = *addr; - key.addrlen = addrlen; - key.entry.hash = h; - return slabhash_lookup(infra->client_ip_rates, h, &key, wr); -} - -/** create rate data item for name, number 1 in now */ -static void infra_create_ratedata(struct infra_cache* infra, - uint8_t* name, size_t namelen, time_t timenow) -{ - hashvalue_type h = dname_query_hash(name, 0xab); - struct rate_key* k = (struct rate_key*)calloc(1, sizeof(*k)); - struct rate_data* d = (struct rate_data*)calloc(1, sizeof(*d)); - if(!k || !d) { - free(k); - free(d); - return; /* alloc failure */ - } - k->namelen = namelen; - k->name = memdup(name, namelen); - if(!k->name) { - free(k); - free(d); - return; /* alloc failure */ - } - lock_rw_init(&k->entry.lock); - k->entry.hash = h; - k->entry.key = k; - k->entry.data = d; - d->qps[0] = 1; - d->timestamp[0] = timenow; - slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL); -} - -/** create rate data item for ip address */ -static void infra_ip_create_ratedata(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow) -{ - hashvalue_type h = hash_addr(addr, addrlen, 0); - struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k)); - struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d)); - if(!k || !d) { - free(k); - free(d); - return; /* alloc failure */ - } - k->addr = *addr; - k->addrlen = addrlen; - lock_rw_init(&k->entry.lock); - k->entry.hash = h; - k->entry.key = k; - k->entry.data = d; - d->qps[0] = 1; - d->timestamp[0] = timenow; - slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL); -} - -/** Find the second and return its rate counter. If none and should_add, remove - * oldest to accommodate. Else return none. */ -static int* infra_rate_find_second_or_none(void* data, time_t t, int should_add) -{ - struct rate_data* d = (struct rate_data*)data; - int i, oldest; - for(i=0; itimestamp[i] == t) - return &(d->qps[i]); - } - if(!should_add) return NULL; - /* remove oldest timestamp, and insert it at t with 0 qps */ - oldest = 0; - for(i=0; itimestamp[i] < d->timestamp[oldest]) - oldest = i; - } - d->timestamp[oldest] = t; - d->qps[oldest] = 0; - return &(d->qps[oldest]); -} - -/** find the second and return its rate counter, if none, remove oldest to - * accommodate */ -static int* infra_rate_give_second(void* data, time_t t) -{ - return infra_rate_find_second_or_none(data, t, 1); -} - -/** find the second and return its rate counter only if it exists. Caller - * should check for NULL return value */ -static int* infra_rate_get_second(void* data, time_t t) -{ - return infra_rate_find_second_or_none(data, t, 0); -} - -int infra_rate_max(void* data, time_t now, int backoff) -{ - struct rate_data* d = (struct rate_data*)data; - int i, max = 0; - for(i=0; itimestamp[i] <= RATE_WINDOW && - d->qps[i] > max) { - max = d->qps[i]; - } - } else { - if(now == d->timestamp[i]) { - return d->qps[i]; - } - } - } - return max; -} - -int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow, int backoff, struct query_info* qinfo, - struct comm_reply* replylist) -{ - int lim, max; - struct lruhash_entry* entry; - - if(!infra_dp_ratelimit) - return 1; /* not enabled */ - - /* find ratelimit */ - lim = infra_find_ratelimit(infra, name, namelen); - if(!lim) - return 1; /* disabled for this domain */ - - /* find or insert ratedata */ - entry = infra_find_ratedata(infra, name, namelen, 1); - if(entry) { - int premax = infra_rate_max(entry->data, timenow, backoff); - int* cur = infra_rate_give_second(entry->data, timenow); - (*cur)++; - max = infra_rate_max(entry->data, timenow, backoff); - lock_rw_unlock(&entry->lock); - - if(premax <= lim && max > lim) { - char buf[257], qnm[257], ts[12], cs[12], ip[128]; - dname_str(name, buf); - dname_str(qinfo->qname, qnm); - sldns_wire2str_type_buf(qinfo->qtype, ts, sizeof(ts)); - sldns_wire2str_class_buf(qinfo->qclass, cs, sizeof(cs)); - ip[0]=0; - if(replylist) { - addr_to_str((struct sockaddr_storage *)&replylist->remote_addr, - replylist->remote_addrlen, ip, sizeof(ip)); - verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s from %s", buf, lim, qnm, cs, ts, ip); - } else { - verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts); - } - } - return (max <= lim); - } - - /* create */ - infra_create_ratedata(infra, name, namelen, timenow); - return (1 <= lim); -} - -void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow) -{ - struct lruhash_entry* entry; - int* cur; - if(!infra_dp_ratelimit) - return; /* not enabled */ - entry = infra_find_ratedata(infra, name, namelen, 1); - if(!entry) return; /* not cached */ - cur = infra_rate_get_second(entry->data, timenow); - if(cur == NULL) { - /* our timenow is not available anymore; nothing to decrease */ - lock_rw_unlock(&entry->lock); - return; - } - if((*cur) > 0) - (*cur)--; - lock_rw_unlock(&entry->lock); -} - -int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow, int backoff) -{ - struct lruhash_entry* entry; - int lim, max; - if(!infra_dp_ratelimit) - return 0; /* not enabled */ - - /* find ratelimit */ - lim = infra_find_ratelimit(infra, name, namelen); - if(!lim) - return 0; /* disabled for this domain */ - - /* find current rate */ - entry = infra_find_ratedata(infra, name, namelen, 0); - if(!entry) - return 0; /* not cached */ - max = infra_rate_max(entry->data, timenow, backoff); - lock_rw_unlock(&entry->lock); - - return (max > lim); -} - -size_t -infra_get_mem(struct infra_cache* infra) -{ - size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts); - if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates); - if(infra->client_ip_rates) s += slabhash_get_mem(infra->client_ip_rates); - /* ignore domain_limits because walk through tree is big */ - return s; -} - -/* Returns 1 if the limit has not been exceeded, 0 otherwise. */ -static int -check_ip_ratelimit(struct sockaddr_storage* addr, socklen_t addrlen, - struct sldns_buffer* buffer, int premax, int max, int has_cookie) -{ - int limit; - - if(has_cookie) limit = infra_ip_ratelimit_cookie; - else limit = infra_ip_ratelimit; - - /* Disabled */ - if(limit == 0) return 1; - - if(premax <= limit && max > limit) { - char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12]; - addr_to_str(addr, addrlen, client_ip, sizeof(client_ip)); - qnm[0]=0; - if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE && - LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) { - (void)sldns_wire2str_rrquestion_buf( - sldns_buffer_at(buffer, LDNS_HEADER_SIZE), - sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE, - qnm, sizeof(qnm)); - if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n') - qnm[strlen(qnm)-1] = 0; /*remove newline*/ - if(strchr(qnm, '\t')) - *strchr(qnm, '\t') = ' '; - if(strchr(qnm, '\t')) - *strchr(qnm, '\t') = ' '; - verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s %s", - client_ip, limit, - has_cookie?"(cookie)":"", qnm); - } else { - verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s (no query name)", - client_ip, limit, - has_cookie?"(cookie)":""); - } - } - return (max <= limit); -} - -int infra_ip_ratelimit_inc(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow, - int has_cookie, int backoff, struct sldns_buffer* buffer) -{ - int max; - struct lruhash_entry* entry; - - /* not enabled */ - if(!infra_ip_ratelimit) { - return 1; - } - /* find or insert ratedata */ - entry = infra_find_ip_ratedata(infra, addr, addrlen, 1); - if(entry) { - int premax = infra_rate_max(entry->data, timenow, backoff); - int* cur = infra_rate_give_second(entry->data, timenow); - (*cur)++; - max = infra_rate_max(entry->data, timenow, backoff); - lock_rw_unlock(&entry->lock); - return check_ip_ratelimit(addr, addrlen, buffer, premax, max, - has_cookie); - } - - /* create */ - infra_ip_create_ratedata(infra, addr, addrlen, timenow); - return 1; -} diff --git a/crates/libunbound-sys/unbound/services/cache/infra.h b/crates/libunbound-sys/unbound/services/cache/infra.h deleted file mode 100644 index 525073bf..00000000 --- a/crates/libunbound-sys/unbound/services/cache/infra.h +++ /dev/null @@ -1,477 +0,0 @@ -/* - * services/cache/infra.h - infrastructure cache, server rtt and capabilities - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the infrastructure cache, as well as rate limiting. - * Note that there are two sorts of rate-limiting here: - * - Pre-cache, per-query rate limiting (query ratelimits) - * - Post-cache, per-domain name rate limiting (infra-ratelimits) - */ - -#ifndef SERVICES_CACHE_INFRA_H -#define SERVICES_CACHE_INFRA_H -#include "util/storage/lruhash.h" -#include "util/storage/dnstree.h" -#include "util/rtt.h" -#include "util/netevent.h" -#include "util/data/msgreply.h" -struct slabhash; -struct config_file; - -/** - * Host information kept for every server, per zone. - */ -struct infra_key { - /** the host address. */ - struct sockaddr_storage addr; - /** length of addr. */ - socklen_t addrlen; - /** zone name in wireformat */ - uint8_t* zonename; - /** length of zonename */ - size_t namelen; - /** hash table entry, data of type infra_data. */ - struct lruhash_entry entry; -}; - -/** - * Host information encompasses host capabilities and retransmission timeouts. - * And lameness information (notAuthoritative, noEDNS, Recursive) - */ -struct infra_data { - /** TTL value for this entry. absolute time. */ - time_t ttl; - - /** time in seconds (absolute) when probing re-commences, 0 disabled */ - time_t probedelay; - /** round trip times for timeout calculation */ - struct rtt_info rtt; - - /** edns version that the host supports, -1 means no EDNS */ - int edns_version; - /** if the EDNS lameness is already known or not. - * EDNS lame is when EDNS queries or replies are dropped, - * and cause a timeout */ - uint8_t edns_lame_known; - - /** is the host lame (does not serve the zone authoritatively), - * or is the host dnssec lame (does not serve DNSSEC data) */ - uint8_t isdnsseclame; - /** is the host recursion lame (not AA, but RA) */ - uint8_t rec_lame; - /** the host is lame (not authoritative) for A records */ - uint8_t lame_type_A; - /** the host is lame (not authoritative) for other query types */ - uint8_t lame_other; - - /** timeouts counter for type A */ - uint8_t timeout_A; - /** timeouts counter for type AAAA */ - uint8_t timeout_AAAA; - /** timeouts counter for others */ - uint8_t timeout_other; -}; - -/** - * Infra cache - */ -struct infra_cache { - /** The hash table with hosts */ - struct slabhash* hosts; - /** TTL value for host information, in seconds */ - int host_ttl; - /** the hosts that are down are kept probed for recovery */ - int infra_keep_probing; - /** hash table with query rates per name: rate_key, rate_data */ - struct slabhash* domain_rates; - /** ratelimit settings for domains, struct domain_limit_data */ - rbtree_type domain_limits; - /** hash table with query rates per client ip: ip_rate_key, ip_rate_data */ - struct slabhash* client_ip_rates; -}; - -/** ratelimit, unless overridden by domain_limits, 0 is off */ -extern int infra_dp_ratelimit; - -/** - * ratelimit settings for domains - */ -struct domain_limit_data { - /** key for rbtree, must be first in struct, name of domain */ - struct name_tree_node node; - /** ratelimit for exact match with this name, -1 if not set */ - int lim; - /** ratelimit for names below this name, -1 if not set */ - int below; -}; - -/** - * key for ratelimit lookups, a domain name - */ -struct rate_key { - /** lruhash key entry */ - struct lruhash_entry entry; - /** domain name in uncompressed wireformat */ - uint8_t* name; - /** length of name */ - size_t namelen; -}; - -/** ip ratelimit, 0 is off */ -extern int infra_ip_ratelimit; -/** ip ratelimit for DNS Cookie clients, 0 is off */ -extern int infra_ip_ratelimit_cookie; - -/** - * key for ip_ratelimit lookups, a source IP. - */ -struct ip_rate_key { - /** lruhash key entry */ - struct lruhash_entry entry; - /** client ip information */ - struct sockaddr_storage addr; - /** length of address */ - socklen_t addrlen; -}; - -/** number of seconds to track qps rate */ -#define RATE_WINDOW 2 - -/** - * Data for ratelimits per domain name - * It is incremented when a non-cache-lookup happens for that domain name. - * The name is the delegation point we have for the name. - * If a new delegation point is found (a referral reply), the previous - * delegation point is decremented, and the new one is charged with the query. - */ -struct rate_data { - /** queries counted, for that second. 0 if not in use. */ - int qps[RATE_WINDOW]; - /** what the timestamp is of the qps array members, counter is - * valid for that timestamp. Usually now and now-1. */ - time_t timestamp[RATE_WINDOW]; -}; - -#define ip_rate_data rate_data - -/** infra host cache default hash lookup size */ -#define INFRA_HOST_STARTSIZE 32 -/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */ -#define INFRA_BYTES_NAME 14 - -/** - * Create infra cache. - * @param cfg: config parameters or NULL for defaults. - * @return: new infra cache, or NULL. - */ -struct infra_cache* infra_create(struct config_file* cfg); - -/** - * Delete infra cache. - * @param infra: infrastructure cache to delete. - */ -void infra_delete(struct infra_cache* infra); - -/** - * Adjust infra cache to use updated configuration settings. - * This may clean the cache. Operates a bit like realloc. - * There may be no threading or use by other threads. - * @param infra: existing cache. If NULL a new infra cache is returned. - * @param cfg: config options. - * @return the new infra cache pointer or NULL on error. - */ -struct infra_cache* infra_adjust(struct infra_cache* infra, - struct config_file* cfg); - -/** - * Plain find infra data function (used by the the other functions) - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: domain name of zone. - * @param namelen: length of domain name. - * @param wr: if true, writelock, else readlock. - * @return the entry, could be expired (this is not checked) or NULL. - */ -struct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, - size_t namelen, int wr); - -/** - * Find host information to send a packet. Creates new entry if not found. - * Lameness is empty. EDNS is 0 (try with first), and rtt is returned for - * the first message to it. - * Use this to send a packet only, because it also locks out others when - * probing is restricted. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: domain name of zone. - * @param namelen: length of domain name. - * @param timenow: what time it is now. - * @param edns_vs: edns version it supports, is returned. - * @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has - * already been probed, is returned. - * @param to: timeout to use, is returned. - * @return: 0 on error. - */ -int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* name, size_t namelen, - time_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to); - -/** - * Set a host to be lame for the given zone. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: domain name of zone apex. - * @param namelen: length of domain name. - * @param timenow: what time it is now. - * @param dnsseclame: if true the host is set dnssec lame. - * if false, the host is marked lame (not serving the zone). - * @param reclame: if true host is a recursor not AA server. - * if false, dnsseclame or marked lame. - * @param qtype: the query type for which it is lame. - * @return: 0 on error. - */ -int infra_set_lame(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* name, size_t namelen, time_t timenow, int dnsseclame, - int reclame, uint16_t qtype); - -/** - * Update rtt information for the host. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: zone name - * @param namelen: zone name length - * @param qtype: query type. - * @param roundtrip: estimate of roundtrip time in milliseconds or -1 for - * timeout. - * @param orig_rtt: original rtt for the query that timed out (roundtrip==-1). - * ignored if roundtrip != -1. - * @param timenow: what time it is now. - * @return: 0 on error. new rto otherwise. - */ -int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* name, size_t namelen, int qtype, - int roundtrip, int orig_rtt, time_t timenow); - -/** - * Update information for the host, store that a TCP transaction works. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: name of zone - * @param namelen: length of name - */ -void infra_update_tcp_works(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* name, size_t namelen); - -/** - * Update edns information for the host. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: name of zone - * @param namelen: length of name - * @param edns_version: the version that it publishes. - * If it is known to support EDNS then no-EDNS is not stored over it. - * @param timenow: what time it is now. - * @return: 0 on error. - */ -int infra_edns_update(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* name, size_t namelen, int edns_version, time_t timenow); - -/** - * Get Lameness information and average RTT if host is in the cache. - * This information is to be used for server selection. - * @param infra: infrastructure cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: zone name. - * @param namelen: zone name length. - * @param qtype: the query to be made. - * @param lame: if function returns true, this returns lameness of the zone. - * @param dnsseclame: if function returns true, this returns if the zone - * is dnssec-lame. - * @param reclame: if function returns true, this is if it is recursion lame. - * @param rtt: if function returns true, this returns avg rtt of the server. - * The rtt value is unclamped and reflects recent timeouts. - * @param timenow: what time it is now. - * @return if found in cache, or false if not (or TTL bad). - */ -int infra_get_lame_rtt(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* name, size_t namelen, uint16_t qtype, - int* lame, int* dnsseclame, int* reclame, int* rtt, time_t timenow); - -/** - * Get additional (debug) info on timing. - * @param infra: infra cache. - * @param addr: host address. - * @param addrlen: length of addr. - * @param name: zone name - * @param namelen: zone name length - * @param rtt: the rtt_info is copied into here (caller alloced return struct). - * @param delay: probe delay (if any). - * @param timenow: what time it is now. - * @param tA: timeout counter on type A. - * @param tAAAA: timeout counter on type AAAA. - * @param tother: timeout counter on type other. - * @return TTL the infra host element is valid for. If -1: not found in cache. - * TTL -2: found but expired. - */ -long long infra_get_host_rto(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, - size_t namelen, struct rtt_info* rtt, int* delay, time_t timenow, - int* tA, int* tAAAA, int* tother); - -/** - * Increment the query rate counter for a delegation point. - * @param infra: infra cache. - * @param name: zone name - * @param namelen: zone name length - * @param timenow: what time it is now. - * @param backoff: if backoff is enabled. - * @param qinfo: for logging, query name. - * @param replylist: for logging, querier's address (if any). - * @return 1 if it could be incremented. 0 if the increment overshot the - * ratelimit or if in the previous second the ratelimit was exceeded. - * Failures like alloc failures are not returned (probably as 1). - */ -int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow, int backoff, struct query_info* qinfo, - struct comm_reply* replylist); - -/** - * Decrement the query rate counter for a delegation point. - * Because the reply received for the delegation point was pleasant, - * we do not charge this delegation point with it (i.e. it was a referral). - * Should call it with same second as when inc() was called. - * @param infra: infra cache. - * @param name: zone name - * @param namelen: zone name length - * @param timenow: what time it is now. - */ -void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow); - -/** - * See if the query rate counter for a delegation point is exceeded. - * So, no queries are going to be allowed. - * @param infra: infra cache. - * @param name: zone name - * @param namelen: zone name length - * @param timenow: what time it is now. - * @param backoff: if backoff is enabled. - * @return true if exceeded. - */ -int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name, - size_t namelen, time_t timenow, int backoff); - -/** find the maximum rate stored. 0 if no information. - * When backoff is enabled look for the maximum in the whole RATE_WINDOW. */ -int infra_rate_max(void* data, time_t now, int backoff); - -/** find the ratelimit in qps for a domain. 0 if no limit for domain. */ -int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name, - size_t namelen); - -/** Update query ratelimit hash and decide - * whether or not a query should be dropped. - * @param infra: infra cache - * @param addr: client address - * @param addrlen: client address length - * @param timenow: what time it is now. - * @param has_cookie: if the request came with a DNS Cookie. - * @param backoff: if backoff is enabled. - * @param buffer: with query for logging. - * @return 1 if it could be incremented. 0 if the increment overshot the - * ratelimit and the query should be dropped. */ -int infra_ip_ratelimit_inc(struct infra_cache* infra, - struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow, - int has_cookie, int backoff, struct sldns_buffer* buffer); - -/** - * Get memory used by the infra cache. - * @param infra: infrastructure cache. - * @return memory in use in bytes. - */ -size_t infra_get_mem(struct infra_cache* infra); - -/** calculate size for the hashtable, does not count size of lameness, - * so the hashtable is a fixed number of items */ -size_t infra_sizefunc(void* k, void* d); - -/** compare two addresses, returns -1, 0, or +1 */ -int infra_compfunc(void* key1, void* key2); - -/** delete key, and destroy the lock */ -void infra_delkeyfunc(void* k, void* arg); - -/** delete data and destroy the lameness hashtable */ -void infra_deldatafunc(void* d, void* arg); - -/** calculate size for the hashtable */ -size_t rate_sizefunc(void* k, void* d); - -/** compare two names, returns -1, 0, or +1 */ -int rate_compfunc(void* key1, void* key2); - -/** delete key, and destroy the lock */ -void rate_delkeyfunc(void* k, void* arg); - -/** delete data */ -void rate_deldatafunc(void* d, void* arg); - -/* calculate size for the client ip hashtable */ -size_t ip_rate_sizefunc(void* k, void* d); - -/* compare two addresses */ -int ip_rate_compfunc(void* key1, void* key2); - -/* delete key, and destroy the lock */ -void ip_rate_delkeyfunc(void* d, void* arg); - -/* delete data */ -#define ip_rate_deldatafunc rate_deldatafunc - -#endif /* SERVICES_CACHE_INFRA_H */ diff --git a/crates/libunbound-sys/unbound/services/cache/rrset.c b/crates/libunbound-sys/unbound/services/cache/rrset.c deleted file mode 100644 index 4e3d08bd..00000000 --- a/crates/libunbound-sys/unbound/services/cache/rrset.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * services/cache/rrset.c - Resource record set cache. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the rrset cache. - */ -#include "config.h" -#include "services/cache/rrset.h" -#include "sldns/rrdef.h" -#include "util/storage/slabhash.h" -#include "util/config_file.h" -#include "util/data/packed_rrset.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -#include "util/regional.h" -#include "util/alloc.h" -#include "util/net_help.h" - -void -rrset_markdel(void* key) -{ - struct ub_packed_rrset_key* r = (struct ub_packed_rrset_key*)key; - r->id = 0; -} - -struct rrset_cache* rrset_cache_create(struct config_file* cfg, - struct alloc_cache* alloc) -{ - size_t slabs = (cfg?cfg->rrset_cache_slabs:HASH_DEFAULT_SLABS); - size_t startarray = HASH_DEFAULT_STARTARRAY; - size_t maxmem = (cfg?cfg->rrset_cache_size:HASH_DEFAULT_MAXMEM); - - struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs, - startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare, - ub_rrset_key_delete, rrset_data_delete, alloc); - slabhash_setmarkdel(&r->table, &rrset_markdel); - return r; -} - -void rrset_cache_delete(struct rrset_cache* r) -{ - if(!r) - return; - slabhash_delete(&r->table); - /* slabhash delete also does free(r), since table is first in struct*/ -} - -struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r, - struct config_file* cfg, struct alloc_cache* alloc) -{ - if(!r || !cfg || !slabhash_is_size(&r->table, cfg->rrset_cache_size, - cfg->rrset_cache_slabs)) - { - rrset_cache_delete(r); - r = rrset_cache_create(cfg, alloc); - } - return r; -} - -void -rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, - hashvalue_type hash, rrset_id_type id) -{ - struct lruhash* table = slabhash_gettable(&r->table, hash); - /* - * This leads to locking problems, deadlocks, if the caller is - * holding any other rrset lock. - * Because a lookup through the hashtable does: - * tablelock -> entrylock (for that entry caller holds) - * And this would do - * entrylock(already held) -> tablelock - * And if two threads do this, it results in deadlock. - * So, the caller must not hold entrylock. - */ - lock_quick_lock(&table->lock); - /* we have locked the hash table, the item can still be deleted. - * because it could already have been reclaimed, but not yet set id=0. - * This is because some lruhash routines have lazy deletion. - * so, we must acquire a lock on the item to verify the id != 0. - * also, with hash not changed, we are using the right slab. - */ - lock_rw_rdlock(&key->entry.lock); - if(key->id == id && key->entry.hash == hash) { - lru_touch(table, &key->entry); - } - lock_rw_unlock(&key->entry.lock); - lock_quick_unlock(&table->lock); -} - -/** see if rrset needs to be updated in the cache */ -static int -need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns) -{ - struct packed_rrset_data* newd = (struct packed_rrset_data*)nd; - struct packed_rrset_data* cached = (struct packed_rrset_data*)cd; - /* o store if rrset has been validated - * everything better than bogus data - * secure is preferred */ - if( newd->security == sec_status_secure && - cached->security != sec_status_secure) - return 1; - if( cached->security == sec_status_bogus && - newd->security != sec_status_bogus && !equal) - return 1; - /* o if current RRset is more trustworthy - insert it */ - if( newd->trust > cached->trust ) { - /* if the cached rrset is bogus, and this one equal, - * do not update the TTL - let it expire. */ - if(equal && cached->ttl >= timenow && - cached->security == sec_status_bogus) - return 0; - return 1; - } - /* o item in cache has expired */ - if( cached->ttl < timenow ) - return 1; - /* o same trust, but different in data - insert it */ - if( newd->trust == cached->trust && !equal ) { - /* if this is type NS, do not 'stick' to owner that changes - * the NS RRset, but use the old TTL for the new data, and - * update to fetch the latest data. ttl is not expired, because - * that check was before this one. */ - if(ns) { - size_t i; - newd->ttl = cached->ttl; - for(i=0; i<(newd->count+newd->rrsig_count); i++) - if(newd->rr_ttl[i] > newd->ttl) - newd->rr_ttl[i] = newd->ttl; - } - return 1; - } - return 0; -} - -/** Update RRSet special key ID */ -static void -rrset_update_id(struct rrset_ref* ref, struct alloc_cache* alloc) -{ - /* this may clear the cache and invalidate lock below */ - uint64_t newid = alloc_get_id(alloc); - /* obtain writelock */ - lock_rw_wrlock(&ref->key->entry.lock); - /* check if it was deleted in the meantime, if so, skip update */ - if(ref->key->id == ref->id) { - ref->key->id = newid; - ref->id = newid; - } - lock_rw_unlock(&ref->key->entry.lock); -} - -int -rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, - struct alloc_cache* alloc, time_t timenow) -{ - struct lruhash_entry* e; - struct ub_packed_rrset_key* k = ref->key; - hashvalue_type h = k->entry.hash; - uint16_t rrset_type = ntohs(k->rk.type); - int equal = 0; - log_assert(ref->id != 0 && k->id != 0); - log_assert(k->rk.dname != NULL); - /* looks up item with a readlock - no editing! */ - if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) { - /* return id and key as they will be used in the cache - * since the lruhash_insert, if item already exists, deallocs - * the passed key in favor of the already stored key. - * because of the small gap (see below) this key ptr and id - * may prove later to be already deleted, which is no problem - * as it only makes a cache miss. - */ - ref->key = (struct ub_packed_rrset_key*)e->key; - ref->id = ref->key->id; - equal = rrsetdata_equal((struct packed_rrset_data*)k->entry. - data, (struct packed_rrset_data*)e->data); - if(!need_to_update_rrset(k->entry.data, e->data, timenow, - equal, (rrset_type==LDNS_RR_TYPE_NS))) { - /* cache is superior, return that value */ - lock_rw_unlock(&e->lock); - ub_packed_rrset_parsedelete(k, alloc); - if(equal) return 2; - return 1; - } - lock_rw_unlock(&e->lock); - /* Go on and insert the passed item. - * small gap here, where entry is not locked. - * possibly entry is updated with something else. - * we then overwrite that with our data. - * this is just too bad, its cache anyway. */ - /* use insert to update entry to manage lruhash - * cache size values nicely. */ - } - log_assert(ref->key->id != 0); - slabhash_insert(&r->table, h, &k->entry, k->entry.data, alloc); - if(e) { - /* For NSEC, NSEC3, DNAME, when rdata is updated, update - * the ID number so that proofs in message cache are - * invalidated */ - if((rrset_type == LDNS_RR_TYPE_NSEC - || rrset_type == LDNS_RR_TYPE_NSEC3 - || rrset_type == LDNS_RR_TYPE_DNAME) && !equal) { - rrset_update_id(ref, alloc); - } - return 1; - } - return 0; -} - -void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache, - struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len, - struct alloc_cache* alloc, time_t timenow) -{ - struct rrset_ref ref; - uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3]; - rrset = packed_rrset_copy_alloc(rrset, alloc, timenow); - if(!rrset) { - log_err("malloc failure in rrset_cache_update_wildcard"); - return; - } - /* ce has at least one label less then qname, we can therefore safely - * add the wildcard label. */ - wc_dname[0] = 1; - wc_dname[1] = (uint8_t)'*'; - memmove(wc_dname+2, ce, ce_len); - - free(rrset->rk.dname); - rrset->rk.dname_len = ce_len + 2; - rrset->rk.dname = (uint8_t*)memdup(wc_dname, rrset->rk.dname_len); - if(!rrset->rk.dname) { - alloc_special_release(alloc, rrset); - log_err("memdup failure in rrset_cache_update_wildcard"); - return; - } - - rrset->entry.hash = rrset_key_hash(&rrset->rk); - ref.key = rrset; - ref.id = rrset->id; - /* ignore ret: if it was in the cache, ref updated */ - (void)rrset_cache_update(rrset_cache, &ref, alloc, timenow); -} - -struct ub_packed_rrset_key* -rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint32_t flags, time_t timenow, - int wr) -{ - struct lruhash_entry* e; - struct ub_packed_rrset_key key; - - key.entry.key = &key; - key.entry.data = NULL; - key.rk.dname = qname; - key.rk.dname_len = qnamelen; - key.rk.type = htons(qtype); - key.rk.rrset_class = htons(qclass); - key.rk.flags = flags; - - key.entry.hash = rrset_key_hash(&key.rk); - - if((e = slabhash_lookup(&r->table, key.entry.hash, &key, wr))) { - /* check TTL */ - struct packed_rrset_data* data = - (struct packed_rrset_data*)e->data; - if(timenow > data->ttl) { - lock_rw_unlock(&e->lock); - return NULL; - } - /* we're done */ - return (struct ub_packed_rrset_key*)e->key; - } - return NULL; -} - -int -rrset_array_lock(struct rrset_ref* ref, size_t count, time_t timenow) -{ - size_t i; - for(i=0; i0 && ref[i].key == ref[i-1].key) - continue; /* only lock items once */ - lock_rw_rdlock(&ref[i].key->entry.lock); - if(ref[i].id != ref[i].key->id || timenow > - ((struct packed_rrset_data*)(ref[i].key->entry.data)) - ->ttl) { - /* failure! rollback our readlocks */ - rrset_array_unlock(ref, i+1); - return 0; - } - } - return 1; -} - -void -rrset_array_unlock(struct rrset_ref* ref, size_t count) -{ - size_t i; - for(i=0; i0 && ref[i].key == ref[i-1].key) - continue; /* only unlock items once */ - lock_rw_unlock(&ref[i].key->entry.lock); - } -} - -void -rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch, - struct rrset_ref* ref, size_t count) -{ - hashvalue_type* h; - size_t i; - if(count > RR_COUNT_MAX || !(h = (hashvalue_type*)regional_alloc( - scratch, sizeof(hashvalue_type)*count))) { - log_warn("rrset LRU: memory allocation failed"); - h = NULL; - } else /* store hash values */ - for(i=0; ientry.hash; - /* unlock */ - for(i=0; i0 && ref[i].key == ref[i-1].key) - continue; /* only unlock items once */ - lock_rw_unlock(&ref[i].key->entry.lock); - } - if(h) { - /* LRU touch, with no rrset locks held */ - for(i=0; i0 && ref[i].key == ref[i-1].key) - continue; /* only touch items once */ - rrset_cache_touch(r, ref[i].key, h[i], ref[i].id); - } - } -} - -void -rrset_update_sec_status(struct rrset_cache* r, - struct ub_packed_rrset_key* rrset, time_t now) -{ - struct packed_rrset_data* updata = - (struct packed_rrset_data*)rrset->entry.data; - struct lruhash_entry* e; - struct packed_rrset_data* cachedata; - - /* hash it again to make sure it has a hash */ - rrset->entry.hash = rrset_key_hash(&rrset->rk); - - e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 1); - if(!e) - return; /* not in the cache anymore */ - cachedata = (struct packed_rrset_data*)e->data; - if(!rrsetdata_equal(updata, cachedata)) { - lock_rw_unlock(&e->lock); - return; /* rrset has changed in the meantime */ - } - /* update the cached rrset */ - if(updata->security > cachedata->security) { - size_t i; - if(updata->trust > cachedata->trust) - cachedata->trust = updata->trust; - cachedata->security = updata->security; - /* for NS records only shorter TTLs, other types: update it */ - if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_NS || - updata->ttl+now < cachedata->ttl || - cachedata->ttl < now || - updata->security == sec_status_bogus) { - cachedata->ttl = updata->ttl + now; - for(i=0; icount+cachedata->rrsig_count; i++) - cachedata->rr_ttl[i] = updata->rr_ttl[i]+now; - cachedata->ttl_add = now; - } - } - lock_rw_unlock(&e->lock); -} - -void -rrset_check_sec_status(struct rrset_cache* r, - struct ub_packed_rrset_key* rrset, time_t now) -{ - struct packed_rrset_data* updata = - (struct packed_rrset_data*)rrset->entry.data; - struct lruhash_entry* e; - struct packed_rrset_data* cachedata; - - /* hash it again to make sure it has a hash */ - rrset->entry.hash = rrset_key_hash(&rrset->rk); - - e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 0); - if(!e) - return; /* not in the cache anymore */ - cachedata = (struct packed_rrset_data*)e->data; - if(now > cachedata->ttl || !rrsetdata_equal(updata, cachedata)) { - lock_rw_unlock(&e->lock); - return; /* expired, or rrset has changed in the meantime */ - } - if(cachedata->security > updata->security) { - updata->security = cachedata->security; - if(cachedata->security == sec_status_bogus) { - size_t i; - updata->ttl = cachedata->ttl - now; - for(i=0; icount+cachedata->rrsig_count; i++) - if(cachedata->rr_ttl[i] < now) - updata->rr_ttl[i] = 0; - else updata->rr_ttl[i] = - cachedata->rr_ttl[i]-now; - } - if(cachedata->trust > updata->trust) - updata->trust = cachedata->trust; - } - lock_rw_unlock(&e->lock); -} - -void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen, - uint16_t type, uint16_t dclass, uint32_t flags) -{ - struct ub_packed_rrset_key key; - key.entry.key = &key; - key.rk.dname = nm; - key.rk.dname_len = nmlen; - key.rk.rrset_class = htons(dclass); - key.rk.type = htons(type); - key.rk.flags = flags; - key.entry.hash = rrset_key_hash(&key.rk); - slabhash_remove(&r->table, key.entry.hash, &key); -} diff --git a/crates/libunbound-sys/unbound/services/cache/rrset.h b/crates/libunbound-sys/unbound/services/cache/rrset.h deleted file mode 100644 index 7c36d403..00000000 --- a/crates/libunbound-sys/unbound/services/cache/rrset.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * services/cache/rrset.h - Resource record set cache. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the rrset cache. - */ - -#ifndef SERVICES_CACHE_RRSET_H -#define SERVICES_CACHE_RRSET_H -#include "util/storage/lruhash.h" -#include "util/storage/slabhash.h" -#include "util/data/packed_rrset.h" -struct config_file; -struct alloc_cache; -struct rrset_ref; -struct regional; - -/** - * The rrset cache - * Thin wrapper around hashtable, like a typedef. - */ -struct rrset_cache { - /** uses partitioned hash table */ - struct slabhash table; -}; - -/** - * Create rrset cache - * @param cfg: config settings or NULL for defaults. - * @param alloc: initial default rrset key allocation. - * @return: NULL on error. - */ -struct rrset_cache* rrset_cache_create(struct config_file* cfg, - struct alloc_cache* alloc); - -/** - * Delete rrset cache - * @param r: rrset cache to delete. - */ -void rrset_cache_delete(struct rrset_cache* r); - -/** - * Adjust settings of the cache to settings from the config file. - * May purge the cache. May recreate the cache. - * There may be no threading or use by other threads. - * @param r: rrset cache to adjust (like realloc). - * @param cfg: config settings or NULL for defaults. - * @param alloc: initial default rrset key allocation. - * @return 0 on error, or new rrset cache pointer on success. - */ -struct rrset_cache* rrset_cache_adjust(struct rrset_cache* r, - struct config_file* cfg, struct alloc_cache* alloc); - -/** - * Touch rrset, with given pointer and id. - * Caller may not hold a lock on ANY rrset, this could give deadlock. - * - * This routine is faster than a hashtable lookup: - * o no bin_lock is acquired. - * o no walk through the bin-overflow-list. - * o no comparison of the entry key to find it. - * - * @param r: rrset cache. - * @param key: rrset key. Marked recently used (if it was not deleted - * before the lock is acquired, in that case nothing happens). - * @param hash: hash value of the item. Please read it from the key when - * you have it locked. Used to find slab from slabhash. - * @param id: used to check that the item is unchanged and not deleted. - */ -void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, - hashvalue_type hash, rrset_id_type id); - -/** - * Update an rrset in the rrset cache. Stores the information for later use. - * Will lookup if the rrset is in the cache and perform an update if necessary. - * If the item was present, and superior, references are returned to that. - * The passed item is then deallocated with rrset_parsedelete. - * - * A superior rrset is: - * o rrset with better trust value. - * o same trust value, different rdata, newly passed rrset is inserted. - * If rdata is the same, TTL in the cache is updated. - * - * @param r: the rrset cache. - * @param ref: reference (ptr and id) to the rrset. Pass reference setup for - * the new rrset. The reference may be changed if the cached rrset is - * superior. - * Before calling the rrset is presumed newly allocated and changeable. - * After calling you do not hold a lock, and the rrset is inserted in - * the hashtable so you need a lock to change it. - * @param alloc: how to allocate (and deallocate) the special rrset key. - * @param timenow: current time (to see if ttl in cache is expired). - * @return: true if the passed reference is updated, false if it is unchanged. - * 0: reference unchanged, inserted in cache. - * 1: reference updated, item is inserted in cache. - * 2: reference updated, item in cache is considered superior. - * also the rdata is equal (but other parameters in cache are superior). - */ -int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, - struct alloc_cache* alloc, time_t timenow); - -/** - * Update or add an rrset in the rrset cache using a wildcard dname. - * Generates wildcard dname by prepending the wildcard label to the closest - * encloser. Will lookup if the rrset is in the cache and perform an update if - * necessary. - * - * @param rrset_cache: the rrset cache. - * @param rrset: which rrset to cache as wildcard. This rrset is left - * untouched. - * @param ce: the closest encloser, will be uses to generate the wildcard dname. - * @param ce_len: the closest encloser length. - * @param alloc: how to allocate (and deallocate) the special rrset key. - * @param timenow: current time (to see if ttl in cache is expired). - */ -void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache, - struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len, - struct alloc_cache* alloc, time_t timenow); - -/** - * Lookup rrset. You obtain read/write lock. You must unlock before lookup - * anything of else. - * @param r: the rrset cache. - * @param qname: name of rrset to lookup. - * @param qnamelen: length of name of rrset to lookup. - * @param qtype: type of rrset to lookup (host order). - * @param qclass: class of rrset to lookup (host order). - * @param flags: rrset flags, or 0. - * @param timenow: used to compare with TTL. - * @param wr: set true to get writelock. - * @return packed rrset key pointer. Remember to unlock the key.entry.lock. - * or NULL if could not be found or it was timed out. - */ -struct ub_packed_rrset_key* rrset_cache_lookup(struct rrset_cache* r, - uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint32_t flags, time_t timenow, int wr); - -/** - * Obtain readlock on a (sorted) list of rrset references. - * Checks TTLs and IDs of the rrsets and rollbacks locking if not Ok. - * @param ref: array of rrset references (key pointer and ID value). - * duplicate references are allowed and handled. - * @param count: size of array. - * @param timenow: used to compare with TTL. - * @return true on success, false on a failure, which can be that some - * RRsets have timed out, or that they do not exist any more, the - * RRsets have been purged from the cache. - * If true, you hold readlocks on all the ref items. - */ -int rrset_array_lock(struct rrset_ref* ref, size_t count, time_t timenow); - -/** - * Unlock array (sorted) of rrset references. - * @param ref: array of rrset references (key pointer and ID value). - * duplicate references are allowed and handled. - * @param count: size of array. - */ -void rrset_array_unlock(struct rrset_ref* ref, size_t count); - -/** - * Unlock array (sorted) of rrset references and at the same time - * touch LRU on the rrsets. It needs the scratch region for temporary - * storage as it uses the initial locks to obtain hash values. - * @param r: the rrset cache. In this cache LRU is updated. - * @param scratch: region for temporary storage of hash values. - * if memory allocation fails, the lru touch fails silently, - * but locks are released. memory errors are logged. - * @param ref: array of rrset references (key pointer and ID value). - * duplicate references are allowed and handled. - * @param count: size of array. - */ -void rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch, - struct rrset_ref* ref, size_t count); - -/** - * Update security status of an rrset. Looks up the rrset. - * If found, checks if rdata is equal. - * If so, it will update the security, trust and rrset-ttl values. - * The values are only updated if security is increased (towards secure). - * @param r: the rrset cache. - * @param rrset: which rrset to attempt to update. This rrset is left - * untouched. The rrset in the cache is updated in-place. - * @param now: current time. - */ -void rrset_update_sec_status(struct rrset_cache* r, - struct ub_packed_rrset_key* rrset, time_t now); - -/** - * Looks up security status of an rrset. Looks up the rrset. - * If found, checks if rdata is equal, and entry did not expire. - * If so, it will update the security, trust and rrset-ttl values. - * @param r: the rrset cache. - * @param rrset: This rrset may change security status due to the cache. - * But its status will only improve, towards secure. - * @param now: current time. - */ -void rrset_check_sec_status(struct rrset_cache* r, - struct ub_packed_rrset_key* rrset, time_t now); - -/** - * Remove an rrset from the cache, by name and type and flags - * @param r: rrset cache - * @param nm: name of rrset - * @param nmlen: length of name - * @param type: type of rrset - * @param dclass: class of rrset, host order - * @param flags: flags of rrset, host order - */ -void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen, - uint16_t type, uint16_t dclass, uint32_t flags); - -/** mark rrset to be deleted, set id=0 */ -void rrset_markdel(void* key); - -#endif /* SERVICES_CACHE_RRSET_H */ diff --git a/crates/libunbound-sys/unbound/services/listen_dnsport.c b/crates/libunbound-sys/unbound/services/listen_dnsport.c deleted file mode 100644 index 60f9b41e..00000000 --- a/crates/libunbound-sys/unbound/services/listen_dnsport.c +++ /dev/null @@ -1,3139 +0,0 @@ -/* - * services/listen_dnsport.c - listen on port 53 for incoming DNS queries. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has functions to get queries from clients. - */ -#include "config.h" -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#include -#include -#ifdef USE_TCP_FASTOPEN -#include -#endif -#include -#include "services/listen_dnsport.h" -#include "services/outside_network.h" -#include "util/netevent.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "sldns/sbuffer.h" -#include "sldns/parseutil.h" -#include "services/mesh.h" -#include "util/fptr_wlist.h" -#include "util/locks.h" - -#ifdef HAVE_NETDB_H -#include -#endif -#include - -#ifdef HAVE_SYS_UN_H -#include -#endif - -#ifdef HAVE_SYSTEMD -#include -#endif - -#ifdef HAVE_IFADDRS_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_LINUX_NET_TSTAMP_H -#include -#endif -/** number of queued TCP connections for listen() */ -#define TCP_BACKLOG 256 - -#ifndef THREADS_DISABLED -/** lock on the counter of stream buffer memory */ -static lock_basic_type stream_wait_count_lock; -/** lock on the counter of HTTP2 query buffer memory */ -static lock_basic_type http2_query_buffer_count_lock; -/** lock on the counter of HTTP2 response buffer memory */ -static lock_basic_type http2_response_buffer_count_lock; -#endif -/** size (in bytes) of stream wait buffers */ -static size_t stream_wait_count = 0; -/** is the lock initialised for stream wait buffers */ -static int stream_wait_lock_inited = 0; -/** size (in bytes) of HTTP2 query buffers */ -static size_t http2_query_buffer_count = 0; -/** is the lock initialised for HTTP2 query buffers */ -static int http2_query_buffer_lock_inited = 0; -/** size (in bytes) of HTTP2 response buffers */ -static size_t http2_response_buffer_count = 0; -/** is the lock initialised for HTTP2 response buffers */ -static int http2_response_buffer_lock_inited = 0; - -/** - * Debug print of the getaddrinfo returned address. - * @param addr: the address returned. - */ -static void -verbose_print_addr(struct addrinfo *addr) -{ - if(verbosity >= VERB_ALGO) { - char buf[100]; - void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr; -#ifdef INET6 - if(addr->ai_family == AF_INET6) - sinaddr = &((struct sockaddr_in6*)addr->ai_addr)-> - sin6_addr; -#endif /* INET6 */ - if(inet_ntop(addr->ai_family, sinaddr, buf, - (socklen_t)sizeof(buf)) == 0) { - (void)strlcpy(buf, "(null)", sizeof(buf)); - } - buf[sizeof(buf)-1] = 0; - verbose(VERB_ALGO, "creating %s%s socket %s %d", - addr->ai_socktype==SOCK_DGRAM?"udp": - addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto", - addr->ai_family==AF_INET?"4": - addr->ai_family==AF_INET6?"6": - "_otherfam", buf, - ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port)); - } -} - -void -verbose_print_unbound_socket(struct unbound_socket* ub_sock) -{ - if(verbosity >= VERB_ALGO) { - log_info("listing of unbound_socket structure:"); - verbose_print_addr(ub_sock->addr); - log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s, - ub_sock->fam == AF_INET?"AF_INET":"AF_INET6", - ub_sock->acl?"yes":"no"); - } -} - -#ifdef HAVE_SYSTEMD -static int -systemd_get_activated(int family, int socktype, int listen, - struct sockaddr *addr, socklen_t addrlen, - const char *path) -{ - int i = 0; - int r = 0; - int s = -1; - const char* listen_pid, *listen_fds; - - /* We should use "listen" option only for stream protocols. For UDP it should be -1 */ - - if((r = sd_booted()) < 1) { - if(r == 0) - log_warn("systemd is not running"); - else - log_err("systemd sd_booted(): %s", strerror(-r)); - return -1; - } - - listen_pid = getenv("LISTEN_PID"); - listen_fds = getenv("LISTEN_FDS"); - - if (!listen_pid) { - log_warn("Systemd mandatory ENV variable is not defined: LISTEN_PID"); - return -1; - } - - if (!listen_fds) { - log_warn("Systemd mandatory ENV variable is not defined: LISTEN_FDS"); - return -1; - } - - if((r = sd_listen_fds(0)) < 1) { - if(r == 0) - log_warn("systemd: did not return socket, check unit configuration"); - else - log_err("systemd sd_listen_fds(): %s", strerror(-r)); - return -1; - } - - for(i = 0; i < r; i++) { - if(sd_is_socket(SD_LISTEN_FDS_START + i, family, socktype, listen)) { - s = SD_LISTEN_FDS_START + i; - break; - } - } - if (s == -1) { - if (addr) - log_err_addr("systemd sd_listen_fds()", - "no such socket", - (struct sockaddr_storage *)addr, addrlen); - else - log_err("systemd sd_listen_fds(): %s", path); - } - return s; -} -#endif - -int -create_udp_sock(int family, int socktype, struct sockaddr* addr, - socklen_t addrlen, int v6only, int* inuse, int* noproto, - int rcv, int snd, int listen, int* reuseport, int transparent, - int freebind, int use_systemd, int dscp) -{ - int s; - char* err; -#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined (SO_BINDANY) - int on=1; -#endif -#ifdef IPV6_MTU - int mtu = IPV6_MIN_MTU; -#endif -#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF) - (void)rcv; -#endif -#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF) - (void)snd; -#endif -#ifndef IPV6_V6ONLY - (void)v6only; -#endif -#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY) && !defined(SO_BINDANY) - (void)transparent; -#endif -#if !defined(IP_FREEBIND) - (void)freebind; -#endif -#ifdef HAVE_SYSTEMD - int got_fd_from_systemd = 0; - - if (!use_systemd - || (use_systemd - && (s = systemd_get_activated(family, socktype, -1, addr, - addrlen, NULL)) == -1)) { -#else - (void)use_systemd; -#endif - if((s = socket(family, socktype, 0)) == -1) { - *inuse = 0; -#ifndef USE_WINSOCK - if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { - *noproto = 1; - return -1; - } -#else - if(WSAGetLastError() == WSAEAFNOSUPPORT || - WSAGetLastError() == WSAEPROTONOSUPPORT) { - *noproto = 1; - return -1; - } -#endif - log_err("can't create socket: %s", sock_strerror(errno)); - *noproto = 0; - return -1; - } -#ifdef HAVE_SYSTEMD - } else { - got_fd_from_systemd = 1; - } -#endif - if(listen) { -#ifdef SO_REUSEADDR - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", - sock_strerror(errno)); -#ifndef USE_WINSOCK - if(errno != ENOSYS) { - close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -#else - closesocket(s); - *noproto = 0; - *inuse = 0; - return -1; -#endif - } -#endif /* SO_REUSEADDR */ -#ifdef SO_REUSEPORT -# ifdef SO_REUSEPORT_LB - /* on FreeBSD 12 we have SO_REUSEPORT_LB that does loadbalance - * like SO_REUSEPORT on Linux. This is what the users want - * with the config option in unbound.conf; if we actually - * need local address and port reuse they'll also need to - * have SO_REUSEPORT set for them, assume it was _LB they want. - */ - if (reuseport && *reuseport && - setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB, (void*)&on, - (socklen_t)sizeof(on)) < 0) { -#ifdef ENOPROTOOPT - if(errno != ENOPROTOOPT || verbosity >= 3) - log_warn("setsockopt(.. SO_REUSEPORT_LB ..) failed: %s", - strerror(errno)); -#endif - /* this option is not essential, we can continue */ - *reuseport = 0; - } -# else /* no SO_REUSEPORT_LB */ - - /* try to set SO_REUSEPORT so that incoming - * queries are distributed evenly among the receiving threads. - * Each thread must have its own socket bound to the same port, - * with SO_REUSEPORT set on each socket. - */ - if (reuseport && *reuseport && - setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, - (socklen_t)sizeof(on)) < 0) { -#ifdef ENOPROTOOPT - if(errno != ENOPROTOOPT || verbosity >= 3) - log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", - strerror(errno)); -#endif - /* this option is not essential, we can continue */ - *reuseport = 0; - } -# endif /* SO_REUSEPORT_LB */ -#else - (void)reuseport; -#endif /* defined(SO_REUSEPORT) */ -#ifdef IP_TRANSPARENT - if (transparent && - setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s", - strerror(errno)); - } -#elif defined(IP_BINDANY) - if (transparent && - setsockopt(s, (family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP), - (family == AF_INET6? IPV6_BINDANY:IP_BINDANY), - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s", - (family==AF_INET6?"V6":""), strerror(errno)); - } -#elif defined(SO_BINDANY) - if (transparent && - setsockopt(s, SOL_SOCKET, SO_BINDANY, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. SO_BINDANY ..) failed: %s", - strerror(errno)); - } -#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */ - } -#ifdef IP_FREEBIND - if(freebind && - setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s", - strerror(errno)); - } -#endif /* IP_FREEBIND */ - if(rcv) { -#ifdef SO_RCVBUF - int got; - socklen_t slen = (socklen_t)sizeof(got); -# ifdef SO_RCVBUFFORCE - /* Linux specific: try to use root permission to override - * system limits on rcvbuf. The limit is stored in - * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */ - if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, - (socklen_t)sizeof(rcv)) < 0) { - if(errno != EPERM) { - log_err("setsockopt(..., SO_RCVBUFFORCE, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -# endif /* SO_RCVBUFFORCE */ - if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, - (socklen_t)sizeof(rcv)) < 0) { - log_err("setsockopt(..., SO_RCVBUF, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - /* check if we got the right thing or if system - * reduced to some system max. Warn if so */ - if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, - &slen) >= 0 && got < rcv/2) { - log_warn("so-rcvbuf %u was not granted. " - "Got %u. To fix: start with " - "root permissions(linux) or sysctl " - "bigger net.core.rmem_max(linux) or " - "kern.ipc.maxsockbuf(bsd) values.", - (unsigned)rcv, (unsigned)got); - } -# ifdef SO_RCVBUFFORCE - } -# endif -#endif /* SO_RCVBUF */ - } - /* first do RCVBUF as the receive buffer is more important */ - if(snd) { -#ifdef SO_SNDBUF - int got; - socklen_t slen = (socklen_t)sizeof(got); -# ifdef SO_SNDBUFFORCE - /* Linux specific: try to use root permission to override - * system limits on sndbuf. The limit is stored in - * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */ - if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, - (socklen_t)sizeof(snd)) < 0) { - if(errno != EPERM) { - log_err("setsockopt(..., SO_SNDBUFFORCE, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -# endif /* SO_SNDBUFFORCE */ - if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, - (socklen_t)sizeof(snd)) < 0) { - log_err("setsockopt(..., SO_SNDBUF, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - /* check if we got the right thing or if system - * reduced to some system max. Warn if so */ - if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, - &slen) >= 0 && got < snd/2) { - log_warn("so-sndbuf %u was not granted. " - "Got %u. To fix: start with " - "root permissions(linux) or sysctl " - "bigger net.core.wmem_max(linux) or " - "kern.ipc.maxsockbuf(bsd) values.", - (unsigned)snd, (unsigned)got); - } -# ifdef SO_SNDBUFFORCE - } -# endif -#endif /* SO_SNDBUF */ - } - err = set_ip_dscp(s, family, dscp); - if(err != NULL) - log_warn("error setting IP DiffServ codepoint %d on UDP socket: %s", dscp, err); - if(family == AF_INET6) { -# if defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - int omit6_set = 0; - int action; -# endif -# if defined(IPV6_V6ONLY) - if(v6only -# ifdef HAVE_SYSTEMD - /* Systemd wants to control if the socket is v6 only - * or both, with BindIPv6Only=default, ipv6-only or - * both in systemd.socket, so it is not set here. */ - && !got_fd_from_systemd -# endif - ) { - int val=(v6only==2)?0:1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - (void*)&val, (socklen_t)sizeof(val)) < 0) { - log_err("setsockopt(..., IPV6_V6ONLY" - ", ...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } -# endif -# if defined(IPV6_USE_MIN_MTU) - /* - * There is no fragmentation of IPv6 datagrams - * during forwarding in the network. Therefore - * we do not send UDP datagrams larger than - * the minimum IPv6 MTU of 1280 octets. The - * EDNS0 message length can be larger if the - * network stack supports IPV6_USE_MIN_MTU. - */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IPV6_USE_MIN_MTU, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -# elif defined(IPV6_MTU) -# ifndef USE_WINSOCK - /* - * On Linux, to send no larger than 1280, the PMTUD is - * disabled by default for datagrams anyway, so we set - * the MTU to use. - */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU, - (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) { - log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", - sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -# elif defined(IPV6_USER_MTU) - /* As later versions of the mingw crosscompiler define - * IPV6_MTU, do the same for windows but use IPV6_USER_MTU - * instead which is writable; IPV6_MTU is readonly there. */ - if (setsockopt(s, IPPROTO_IPV6, IPV6_USER_MTU, - (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) { - if (WSAGetLastError() != WSAENOPROTOOPT) { - log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s", - wsa_strerror(WSAGetLastError())); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } -# endif /* USE_WINSOCK */ -# endif /* IPv6 MTU */ -# if defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) -# if defined(IP_PMTUDISC_OMIT) - action = IP_PMTUDISC_OMIT; - if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU_DISCOVER, - &action, (socklen_t)sizeof(action)) < 0) { - - if (errno != EINVAL) { - log_err("setsockopt(..., IPV6_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s", - strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } - else - { - omit6_set = 1; - } -# endif - if (omit6_set == 0) { - action = IP_PMTUDISC_DONT; - if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU_DISCOVER, - &action, (socklen_t)sizeof(action)) < 0) { - log_err("setsockopt(..., IPV6_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s", - strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } -# endif /* IPV6_MTU_DISCOVER */ - } else if(family == AF_INET) { -# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) -/* linux 3.15 has IP_PMTUDISC_OMIT, Hannes Frederic Sowa made it so that - * PMTU information is not accepted, but fragmentation is allowed - * if and only if the packet size exceeds the outgoing interface MTU - * (and also uses the interface mtu to determine the size of the packets). - * So there won't be any EMSGSIZE error. Against DNS fragmentation attacks. - * FreeBSD already has same semantics without setting the option. */ - int omit_set = 0; - int action; -# if defined(IP_PMTUDISC_OMIT) - action = IP_PMTUDISC_OMIT; - if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, - &action, (socklen_t)sizeof(action)) < 0) { - - if (errno != EINVAL) { - log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s", - strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } - else - { - omit_set = 1; - } -# endif - if (omit_set == 0) { - action = IP_PMTUDISC_DONT; - if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, - &action, (socklen_t)sizeof(action)) < 0) { - log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s", - strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } - } -# elif defined(IP_DONTFRAG) && !defined(__APPLE__) - /* the IP_DONTFRAG option if defined in the 11.0 OSX headers, - * but does not work on that version, so we exclude it */ - int off = 0; - if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, - &off, (socklen_t)sizeof(off)) < 0) { - log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s", - strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; - } -# endif /* IPv4 MTU */ - } - if( -#ifdef HAVE_SYSTEMD - !got_fd_from_systemd && -#endif - bind(s, (struct sockaddr*)addr, addrlen) != 0) { - *noproto = 0; - *inuse = 0; -#ifndef USE_WINSOCK -#ifdef EADDRINUSE - *inuse = (errno == EADDRINUSE); - /* detect freebsd jail with no ipv6 permission */ - if(family==AF_INET6 && errno==EINVAL) - *noproto = 1; - else if(errno != EADDRINUSE && - !(errno == EACCES && verbosity < 4 && !listen) -#ifdef EADDRNOTAVAIL - && !(errno == EADDRNOTAVAIL && verbosity < 4 && !listen) -#endif - ) { - log_err_addr("can't bind socket", strerror(errno), - (struct sockaddr_storage*)addr, addrlen); - } -#endif /* EADDRINUSE */ -#else /* USE_WINSOCK */ - if(WSAGetLastError() != WSAEADDRINUSE && - WSAGetLastError() != WSAEADDRNOTAVAIL && - !(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) { - log_err_addr("can't bind socket", - wsa_strerror(WSAGetLastError()), - (struct sockaddr_storage*)addr, addrlen); - } -#endif /* USE_WINSOCK */ - sock_close(s); - return -1; - } - if(!fd_set_nonblock(s)) { - *noproto = 0; - *inuse = 0; - sock_close(s); - return -1; - } - return s; -} - -int -create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto, - int* reuseport, int transparent, int mss, int nodelay, int freebind, - int use_systemd, int dscp) -{ - int s; - char* err; -#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY) - int on = 1; -#endif -#ifdef HAVE_SYSTEMD - int got_fd_from_systemd = 0; -#endif -#ifdef USE_TCP_FASTOPEN - int qlen; -#endif -#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY) && !defined(SO_BINDANY) - (void)transparent; -#endif -#if !defined(IP_FREEBIND) - (void)freebind; -#endif - verbose_print_addr(addr); - *noproto = 0; -#ifdef HAVE_SYSTEMD - if (!use_systemd || - (use_systemd - && (s = systemd_get_activated(addr->ai_family, addr->ai_socktype, 1, - addr->ai_addr, addr->ai_addrlen, - NULL)) == -1)) { -#else - (void)use_systemd; -#endif - if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) { -#ifndef USE_WINSOCK - if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { - *noproto = 1; - return -1; - } -#else - if(WSAGetLastError() == WSAEAFNOSUPPORT || - WSAGetLastError() == WSAEPROTONOSUPPORT) { - *noproto = 1; - return -1; - } -#endif - log_err("can't create socket: %s", sock_strerror(errno)); - return -1; - } - if(nodelay) { -#if defined(IPPROTO_TCP) && defined(TCP_NODELAY) - if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - #ifndef USE_WINSOCK - log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s", - strerror(errno)); - #else - log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s", - wsa_strerror(WSAGetLastError())); - #endif - } -#else - log_warn(" setsockopt(TCP_NODELAY) unsupported"); -#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */ - } - if (mss > 0) { -#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG) - if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss, - (socklen_t)sizeof(mss)) < 0) { - log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s", - sock_strerror(errno)); - } else { - verbose(VERB_ALGO, - " tcp socket mss set to %d", mss); - } -#else - log_warn(" setsockopt(TCP_MAXSEG) unsupported"); -#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */ - } -#ifdef HAVE_SYSTEMD - } else { - got_fd_from_systemd = 1; - } -#endif -#ifdef SO_REUSEADDR - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", - sock_strerror(errno)); - sock_close(s); - return -1; - } -#endif /* SO_REUSEADDR */ -#ifdef IP_FREEBIND - if (freebind && setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s", - strerror(errno)); - } -#endif /* IP_FREEBIND */ -#ifdef SO_REUSEPORT - /* try to set SO_REUSEPORT so that incoming - * connections are distributed evenly among the receiving threads. - * Each thread must have its own socket bound to the same port, - * with SO_REUSEPORT set on each socket. - */ - if (reuseport && *reuseport && - setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, - (socklen_t)sizeof(on)) < 0) { -#ifdef ENOPROTOOPT - if(errno != ENOPROTOOPT || verbosity >= 3) - log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", - strerror(errno)); -#endif - /* this option is not essential, we can continue */ - *reuseport = 0; - } -#else - (void)reuseport; -#endif /* defined(SO_REUSEPORT) */ -#if defined(IPV6_V6ONLY) - if(addr->ai_family == AF_INET6 && v6only -# ifdef HAVE_SYSTEMD - /* Systemd wants to control if the socket is v6 only - * or both, with BindIPv6Only=default, ipv6-only or - * both in systemd.socket, so it is not set here. */ - && !got_fd_from_systemd -# endif - ) { - if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s", - sock_strerror(errno)); - sock_close(s); - return -1; - } - } -#else - (void)v6only; -#endif /* IPV6_V6ONLY */ -#ifdef IP_TRANSPARENT - if (transparent && - setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s", - strerror(errno)); - } -#elif defined(IP_BINDANY) - if (transparent && - setsockopt(s, (addr->ai_family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP), - (addr->ai_family == AF_INET6? IPV6_BINDANY:IP_BINDANY), - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s", - (addr->ai_family==AF_INET6?"V6":""), strerror(errno)); - } -#elif defined(SO_BINDANY) - if (transparent && - setsockopt(s, SOL_SOCKET, SO_BINDANY, (void*)&on, (socklen_t) - sizeof(on)) < 0) { - log_warn("setsockopt(.. SO_BINDANY ..) failed: %s", - strerror(errno)); - } -#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */ - err = set_ip_dscp(s, addr->ai_family, dscp); - if(err != NULL) - log_warn("error setting IP DiffServ codepoint %d on TCP socket: %s", dscp, err); - if( -#ifdef HAVE_SYSTEMD - !got_fd_from_systemd && -#endif - bind(s, addr->ai_addr, addr->ai_addrlen) != 0) { -#ifndef USE_WINSOCK - /* detect freebsd jail with no ipv6 permission */ - if(addr->ai_family==AF_INET6 && errno==EINVAL) - *noproto = 1; - else { - log_err_addr("can't bind socket", strerror(errno), - (struct sockaddr_storage*)addr->ai_addr, - addr->ai_addrlen); - } -#else - log_err_addr("can't bind socket", - wsa_strerror(WSAGetLastError()), - (struct sockaddr_storage*)addr->ai_addr, - addr->ai_addrlen); -#endif - sock_close(s); - return -1; - } - if(!fd_set_nonblock(s)) { - sock_close(s); - return -1; - } - if(listen(s, TCP_BACKLOG) == -1) { - log_err("can't listen: %s", sock_strerror(errno)); - sock_close(s); - return -1; - } -#ifdef USE_TCP_FASTOPEN - /* qlen specifies how many outstanding TFO requests to allow. Limit is a defense - against IP spoofing attacks as suggested in RFC7413 */ -#ifdef __APPLE__ - /* OS X implementation only supports qlen of 1 via this call. Actual - value is configured by the net.inet.tcp.fastopen_backlog kernel parm. */ - qlen = 1; -#else - /* 5 is recommended on linux */ - qlen = 5; -#endif - if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen, - sizeof(qlen))) == -1 ) { -#ifdef ENOPROTOOPT - /* squelch ENOPROTOOPT: freebsd server mode with kernel support - disabled, except when verbosity enabled for debugging */ - if(errno != ENOPROTOOPT || verbosity >= 3) { -#endif - if(errno == EPERM) { - log_warn("Setting TCP Fast Open as server failed: %s ; this could likely be because sysctl net.inet.tcp.fastopen.enabled, net.inet.tcp.fastopen.server_enable, or net.ipv4.tcp_fastopen is disabled", strerror(errno)); - } else { - log_err("Setting TCP Fast Open as server failed: %s", strerror(errno)); - } -#ifdef ENOPROTOOPT - } -#endif - } -#endif - return s; -} - -char* -set_ip_dscp(int socket, int addrfamily, int dscp) -{ - int ds; - - if(dscp == 0) - return NULL; - ds = dscp << 2; - switch(addrfamily) { - case AF_INET6: - #ifdef IPV6_TCLASS - if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&ds, - sizeof(ds)) < 0) - return sock_strerror(errno); - break; - #else - return "IPV6_TCLASS not defined on this system"; - #endif - default: - if(setsockopt(socket, IPPROTO_IP, IP_TOS, (void*)&ds, sizeof(ds)) < 0) - return sock_strerror(errno); - break; - } - return NULL; -} - -int -create_local_accept_sock(const char *path, int* noproto, int use_systemd) -{ -#ifdef HAVE_SYSTEMD - int ret; - - if (use_systemd && (ret = systemd_get_activated(AF_LOCAL, SOCK_STREAM, 1, NULL, 0, path)) != -1) - return ret; - else { -#endif -#ifdef HAVE_SYS_UN_H - int s; - struct sockaddr_un usock; -#ifndef HAVE_SYSTEMD - (void)use_systemd; -#endif - - verbose(VERB_ALGO, "creating unix socket %s", path); -#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - /* this member exists on BSDs, not Linux */ - usock.sun_len = (unsigned)sizeof(usock); -#endif - usock.sun_family = AF_LOCAL; - /* length is 92-108, 104 on FreeBSD */ - (void)strlcpy(usock.sun_path, path, sizeof(usock.sun_path)); - - if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { - log_err("Cannot create local socket %s (%s)", - path, strerror(errno)); - return -1; - } - - if (unlink(path) && errno != ENOENT) { - /* The socket already exists and cannot be removed */ - log_err("Cannot remove old local socket %s (%s)", - path, strerror(errno)); - goto err; - } - - if (bind(s, (struct sockaddr *)&usock, - (socklen_t)sizeof(struct sockaddr_un)) == -1) { - log_err("Cannot bind local socket %s (%s)", - path, strerror(errno)); - goto err; - } - - if (!fd_set_nonblock(s)) { - log_err("Cannot set non-blocking mode"); - goto err; - } - - if (listen(s, TCP_BACKLOG) == -1) { - log_err("can't listen: %s", strerror(errno)); - goto err; - } - - (void)noproto; /*unused*/ - return s; - -err: - sock_close(s); - return -1; - -#ifdef HAVE_SYSTEMD - } -#endif -#else - (void)use_systemd; - (void)path; - log_err("Local sockets are not supported"); - *noproto = 1; - return -1; -#endif -} - - -/** - * Create socket from getaddrinfo results - */ -static int -make_sock(int stype, const char* ifname, const char* port, - struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, - int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind, - int use_systemd, int dscp, struct unbound_socket* ub_sock) -{ - struct addrinfo *res = NULL; - int r, s, inuse, noproto; - hints->ai_socktype = stype; - *noip6 = 0; - if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) { -#ifdef USE_WINSOCK - if(r == EAI_NONAME && hints->ai_family == AF_INET6){ - *noip6 = 1; /* 'Host not found' for IP6 on winXP */ - return -1; - } -#endif - log_err("node %s:%s getaddrinfo: %s %s", - ifname?ifname:"default", port, gai_strerror(r), -#ifdef EAI_SYSTEM - (r==EAI_SYSTEM?(char*)strerror(errno):"") -#else - "" -#endif - ); - return -1; - } - if(stype == SOCK_DGRAM) { - verbose_print_addr(res); - s = create_udp_sock(res->ai_family, res->ai_socktype, - (struct sockaddr*)res->ai_addr, res->ai_addrlen, - v6only, &inuse, &noproto, (int)rcv, (int)snd, 1, - reuseport, transparent, freebind, use_systemd, dscp); - if(s == -1 && inuse) { - log_err("bind: address already in use"); - } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ - *noip6 = 1; - } - } else { - s = create_tcp_accept_sock(res, v6only, &noproto, reuseport, - transparent, tcp_mss, nodelay, freebind, use_systemd, - dscp); - if(s == -1 && noproto && hints->ai_family == AF_INET6){ - *noip6 = 1; - } - } - - ub_sock->addr = res; - ub_sock->s = s; - ub_sock->fam = hints->ai_family; - ub_sock->acl = NULL; - - return s; -} - -/** make socket and first see if ifname contains port override info */ -static int -make_sock_port(int stype, const char* ifname, const char* port, - struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, - int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind, - int use_systemd, int dscp, struct unbound_socket* ub_sock) -{ - char* s = strchr(ifname, '@'); - if(s) { - /* override port with ifspec@port */ - char p[16]; - char newif[128]; - if((size_t)(s-ifname) >= sizeof(newif)) { - log_err("ifname too long: %s", ifname); - *noip6 = 0; - return -1; - } - if(strlen(s+1) >= sizeof(p)) { - log_err("portnumber too long: %s", ifname); - *noip6 = 0; - return -1; - } - (void)strlcpy(newif, ifname, sizeof(newif)); - newif[s-ifname] = 0; - (void)strlcpy(p, s+1, sizeof(p)); - p[strlen(s+1)]=0; - return make_sock(stype, newif, p, hints, v6only, noip6, rcv, - snd, reuseport, transparent, tcp_mss, nodelay, freebind, - use_systemd, dscp, ub_sock); - } - return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd, - reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd, - dscp, ub_sock); -} - -/** - * Add port to open ports list. - * @param list: list head. changed. - * @param s: fd. - * @param ftype: if fd is UDP. - * @param pp2_enabled: if PROXYv2 is enabled for this port. - * @param ub_sock: socket with address. - * @return false on failure. list in unchanged then. - */ -static int -port_insert(struct listen_port** list, int s, enum listen_type ftype, - int pp2_enabled, struct unbound_socket* ub_sock) -{ - struct listen_port* item = (struct listen_port*)malloc( - sizeof(struct listen_port)); - if(!item) - return 0; - item->next = *list; - item->fd = s; - item->ftype = ftype; - item->pp2_enabled = pp2_enabled; - item->socket = ub_sock; - *list = item; - return 1; -} - -/** set fd to receive software timestamps */ -static int -set_recvtimestamp(int s) -{ -#ifdef HAVE_LINUX_NET_TSTAMP_H - int opt = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; - if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMPNS, (void*)&opt, (socklen_t)sizeof(opt)) < 0) { - log_err("setsockopt(..., SO_TIMESTAMPNS, ...) failed: %s", - strerror(errno)); - return 0; - } - return 1; -#else - log_err("packets timestamping is not supported on this platform"); - (void)s; - return 0; -#endif -} - -/** set fd to receive source address packet info */ -static int -set_recvpktinfo(int s, int family) -{ -#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO) - int on = 1; -#else - (void)s; -#endif - if(family == AF_INET6) { -# ifdef IPV6_RECVPKTINFO - if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s", - strerror(errno)); - return 0; - } -# elif defined(IPV6_PKTINFO) - if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s", - strerror(errno)); - return 0; - } -# else - log_err("no IPV6_RECVPKTINFO and IPV6_PKTINFO options, please " - "disable interface-automatic or do-ip6 in config"); - return 0; -# endif /* defined IPV6_RECVPKTINFO */ - - } else if(family == AF_INET) { -# ifdef IP_PKTINFO - if(setsockopt(s, IPPROTO_IP, IP_PKTINFO, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s", - strerror(errno)); - return 0; - } -# elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR) - if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, - (void*)&on, (socklen_t)sizeof(on)) < 0) { - log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s", - strerror(errno)); - return 0; - } -# else - log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable " - "interface-automatic or do-ip4 in config"); - return 0; -# endif /* IP_PKTINFO */ - - } - return 1; -} - -/** see if interface is ssl, its port number == the ssl port number */ -static int -if_is_ssl(const char* ifname, const char* port, int ssl_port, - struct config_strlist* tls_additional_port) -{ - struct config_strlist* s; - char* p = strchr(ifname, '@'); - if(!p && atoi(port) == ssl_port) - return 1; - if(p && atoi(p+1) == ssl_port) - return 1; - for(s = tls_additional_port; s; s = s->next) { - if(p && atoi(p+1) == atoi(s->str)) - return 1; - if(!p && atoi(port) == atoi(s->str)) - return 1; - } - return 0; -} - -/** - * Helper for ports_open. Creates one interface (or NULL for default). - * @param ifname: The interface ip address. - * @param do_auto: use automatic interface detection. - * If enabled, then ifname must be the wildcard name. - * @param do_udp: if udp should be used. - * @param do_tcp: if tcp should be used. - * @param hints: for getaddrinfo. family and flags have to be set by caller. - * @param port: Port number to use (as string). - * @param list: list of open ports, appended to, changed to point to list head. - * @param rcv: receive buffer size for UDP - * @param snd: send buffer size for UDP - * @param ssl_port: ssl service port number - * @param tls_additional_port: list of additional ssl service port numbers. - * @param https_port: DoH service port number - * @param proxy_protocol_port: list of PROXYv2 port numbers. - * @param reuseport: try to set SO_REUSEPORT if nonNULL and true. - * set to false on exit if reuseport failed due to no kernel support. - * @param transparent: set IP_TRANSPARENT socket option. - * @param tcp_mss: maximum segment size of tcp socket. default if zero. - * @param freebind: set IP_FREEBIND socket option. - * @param http2_nodelay: set TCP_NODELAY on HTTP/2 connection - * @param use_systemd: if true, fetch sockets from systemd. - * @param dnscrypt_port: dnscrypt service port number - * @param dscp: DSCP to use. - * @param sock_queue_timeout: the sock_queue_timeout from config. Seconds to - * wait to discard if UDP packets have waited for long in the socket - * buffer. - * @return: returns false on error. - */ -static int -ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, - struct addrinfo *hints, const char* port, struct listen_port** list, - size_t rcv, size_t snd, int ssl_port, - struct config_strlist* tls_additional_port, int https_port, - struct config_strlist* proxy_protocol_port, - int* reuseport, int transparent, int tcp_mss, int freebind, - int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp, - int sock_queue_timeout) -{ - int s, noip6=0; - int is_https = if_is_https(ifname, port, https_port); - int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port); - int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port); - int nodelay = is_https && http2_nodelay; - struct unbound_socket* ub_sock; - - if(!do_udp && !do_tcp) - return 0; - - if(is_pp2) { - if(is_dnscrypt) { - fatal_exit("PROXYv2 and DNSCrypt combination not " - "supported!"); - } else if(is_https) { - fatal_exit("PROXYv2 and DoH combination not " - "supported!"); - } - } - - if(do_auto) { - ub_sock = calloc(1, sizeof(struct unbound_socket)); - if(!ub_sock) - return 0; - if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, - &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) { - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - if(noip6) { - log_warn("IPv6 protocol not available"); - return 1; - } - return 0; - } - /* getting source addr packet info is highly non-portable */ - if(!set_recvpktinfo(s, hints->ai_family)) { - sock_close(s); - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - return 0; - } - if (sock_queue_timeout && !set_recvtimestamp(s)) { - log_warn("socket timestamping is not available"); - } - if(!port_insert(list, s, is_dnscrypt - ?listen_type_udpancil_dnscrypt:listen_type_udpancil, - is_pp2, ub_sock)) { - sock_close(s); - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - return 0; - } - } else if(do_udp) { - ub_sock = calloc(1, sizeof(struct unbound_socket)); - if(!ub_sock) - return 0; - /* regular udp socket */ - if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, - &noip6, rcv, snd, reuseport, transparent, - tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) { - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - if(noip6) { - log_warn("IPv6 protocol not available"); - return 1; - } - return 0; - } - if (sock_queue_timeout && !set_recvtimestamp(s)) { - log_warn("socket timestamping is not available"); - } - if(!port_insert(list, s, is_dnscrypt - ?listen_type_udp_dnscrypt:listen_type_udp, - is_pp2, ub_sock)) { - sock_close(s); - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - return 0; - } - } - if(do_tcp) { - int is_ssl = if_is_ssl(ifname, port, ssl_port, - tls_additional_port); - enum listen_type port_type; - ub_sock = calloc(1, sizeof(struct unbound_socket)); - if(!ub_sock) - return 0; - if(is_ssl) - port_type = listen_type_ssl; - else if(is_https) - port_type = listen_type_http; - else if(is_dnscrypt) - port_type = listen_type_tcp_dnscrypt; - else - port_type = listen_type_tcp; - if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, - &noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay, - freebind, use_systemd, dscp, ub_sock)) == -1) { - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - if(noip6) { - /*log_warn("IPv6 protocol not available");*/ - return 1; - } - return 0; - } - if(is_ssl) - verbose(VERB_ALGO, "setup TCP for SSL service"); - if(!port_insert(list, s, port_type, is_pp2, ub_sock)) { - sock_close(s); - if(ub_sock->addr) - freeaddrinfo(ub_sock->addr); - free(ub_sock); - return 0; - } - } - return 1; -} - -/** - * Add items to commpoint list in front. - * @param c: commpoint to add. - * @param front: listen struct. - * @return: false on failure. - */ -static int -listen_cp_insert(struct comm_point* c, struct listen_dnsport* front) -{ - struct listen_list* item = (struct listen_list*)malloc( - sizeof(struct listen_list)); - if(!item) - return 0; - item->com = c; - item->next = front->cps; - front->cps = item; - return 1; -} - -void listen_setup_locks(void) -{ - if(!stream_wait_lock_inited) { - lock_basic_init(&stream_wait_count_lock); - stream_wait_lock_inited = 1; - } - if(!http2_query_buffer_lock_inited) { - lock_basic_init(&http2_query_buffer_count_lock); - http2_query_buffer_lock_inited = 1; - } - if(!http2_response_buffer_lock_inited) { - lock_basic_init(&http2_response_buffer_count_lock); - http2_response_buffer_lock_inited = 1; - } -} - -void listen_desetup_locks(void) -{ - if(stream_wait_lock_inited) { - stream_wait_lock_inited = 0; - lock_basic_destroy(&stream_wait_count_lock); - } - if(http2_query_buffer_lock_inited) { - http2_query_buffer_lock_inited = 0; - lock_basic_destroy(&http2_query_buffer_count_lock); - } - if(http2_response_buffer_lock_inited) { - http2_response_buffer_lock_inited = 0; - lock_basic_destroy(&http2_response_buffer_count_lock); - } -} - -struct listen_dnsport* -listen_create(struct comm_base* base, struct listen_port* ports, - size_t bufsize, int tcp_accept_count, int tcp_idle_timeout, - int harden_large_queries, uint32_t http_max_streams, - char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit, - void* sslctx, struct dt_env* dtenv, comm_point_callback_type* cb, - void *cb_arg) -{ - struct listen_dnsport* front = (struct listen_dnsport*) - malloc(sizeof(struct listen_dnsport)); - if(!front) - return NULL; - front->cps = NULL; - front->udp_buff = sldns_buffer_new(bufsize); -#ifdef USE_DNSCRYPT - front->dnscrypt_udp_buff = NULL; -#endif - if(!front->udp_buff) { - free(front); - return NULL; - } - - /* create comm points as needed */ - while(ports) { - struct comm_point* cp = NULL; - if(ports->ftype == listen_type_udp || - ports->ftype == listen_type_udp_dnscrypt) { - cp = comm_point_create_udp(base, ports->fd, - front->udp_buff, ports->pp2_enabled, cb, - cb_arg, ports->socket); - } else if(ports->ftype == listen_type_tcp || - ports->ftype == listen_type_tcp_dnscrypt) { - cp = comm_point_create_tcp(base, ports->fd, - tcp_accept_count, tcp_idle_timeout, - harden_large_queries, 0, NULL, - tcp_conn_limit, bufsize, front->udp_buff, - ports->ftype, ports->pp2_enabled, cb, cb_arg, - ports->socket); - } else if(ports->ftype == listen_type_ssl || - ports->ftype == listen_type_http) { - cp = comm_point_create_tcp(base, ports->fd, - tcp_accept_count, tcp_idle_timeout, - harden_large_queries, - http_max_streams, http_endpoint, - tcp_conn_limit, bufsize, front->udp_buff, - ports->ftype, ports->pp2_enabled, cb, cb_arg, - ports->socket); - if(ports->ftype == listen_type_http) { - if(!sslctx && !http_notls) { - log_warn("HTTPS port configured, but " - "no TLS tls-service-key or " - "tls-service-pem set"); - } -#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB - if(!http_notls) { - log_warn("Unbound is not compiled " - "with an OpenSSL version " - "supporting ALPN " - "(OpenSSL >= 1.0.2). This " - "is required to use " - "DNS-over-HTTPS"); - } -#endif -#ifndef HAVE_NGHTTP2_NGHTTP2_H - log_warn("Unbound is not compiled with " - "nghttp2. This is required to use " - "DNS-over-HTTPS."); -#endif - } - } else if(ports->ftype == listen_type_udpancil || - ports->ftype == listen_type_udpancil_dnscrypt) { - cp = comm_point_create_udp_ancil(base, ports->fd, - front->udp_buff, ports->pp2_enabled, cb, - cb_arg, ports->socket); - } - if(!cp) { - log_err("can't create commpoint"); - listen_delete(front); - return NULL; - } - if((http_notls && ports->ftype == listen_type_http) || - (ports->ftype == listen_type_tcp) || - (ports->ftype == listen_type_udp) || - (ports->ftype == listen_type_udpancil) || - (ports->ftype == listen_type_tcp_dnscrypt) || - (ports->ftype == listen_type_udp_dnscrypt) || - (ports->ftype == listen_type_udpancil_dnscrypt)) - cp->ssl = NULL; - else - cp->ssl = sslctx; - cp->dtenv = dtenv; - cp->do_not_close = 1; -#ifdef USE_DNSCRYPT - if (ports->ftype == listen_type_udp_dnscrypt || - ports->ftype == listen_type_tcp_dnscrypt || - ports->ftype == listen_type_udpancil_dnscrypt) { - cp->dnscrypt = 1; - cp->dnscrypt_buffer = sldns_buffer_new(bufsize); - if(!cp->dnscrypt_buffer) { - log_err("can't alloc dnscrypt_buffer"); - comm_point_delete(cp); - listen_delete(front); - return NULL; - } - front->dnscrypt_udp_buff = cp->dnscrypt_buffer; - } -#endif - if(!listen_cp_insert(cp, front)) { - log_err("malloc failed"); - comm_point_delete(cp); - listen_delete(front); - return NULL; - } - ports = ports->next; - } - if(!front->cps) { - log_err("Could not open sockets to accept queries."); - listen_delete(front); - return NULL; - } - - return front; -} - -void -listen_list_delete(struct listen_list* list) -{ - struct listen_list *p = list, *pn; - while(p) { - pn = p->next; - comm_point_delete(p->com); - free(p); - p = pn; - } -} - -void -listen_delete(struct listen_dnsport* front) -{ - if(!front) - return; - listen_list_delete(front->cps); -#ifdef USE_DNSCRYPT - if(front->dnscrypt_udp_buff && - front->udp_buff != front->dnscrypt_udp_buff) { - sldns_buffer_free(front->dnscrypt_udp_buff); - } -#endif - sldns_buffer_free(front->udp_buff); - free(front); -} - -#ifdef HAVE_GETIFADDRS -static int -resolve_ifa_name(struct ifaddrs *ifas, const char *search_ifa, char ***ip_addresses, int *ip_addresses_size) -{ - struct ifaddrs *ifa; - void *tmpbuf; - int last_ip_addresses_size = *ip_addresses_size; - - for(ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { - sa_family_t family; - const char* atsign; -#ifdef INET6 /* | address ip | % | ifa name | @ | port | nul */ - char addr_buf[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1 + 16 + 1]; -#else - char addr_buf[INET_ADDRSTRLEN + 1 + 16 + 1]; -#endif - - if((atsign=strrchr(search_ifa, '@')) != NULL) { - if(strlen(ifa->ifa_name) != (size_t)(atsign-search_ifa) - || strncmp(ifa->ifa_name, search_ifa, - atsign-search_ifa) != 0) - continue; - } else { - if(strcmp(ifa->ifa_name, search_ifa) != 0) - continue; - atsign = ""; - } - - if(ifa->ifa_addr == NULL) - continue; - - family = ifa->ifa_addr->sa_family; - if(family == AF_INET) { - char a4[INET_ADDRSTRLEN + 1]; - struct sockaddr_in *in4 = (struct sockaddr_in *) - ifa->ifa_addr; - if(!inet_ntop(family, &in4->sin_addr, a4, sizeof(a4))) { - log_err("inet_ntop failed"); - return 0; - } - snprintf(addr_buf, sizeof(addr_buf), "%s%s", - a4, atsign); - } -#ifdef INET6 - else if(family == AF_INET6) { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) - ifa->ifa_addr; - char a6[INET6_ADDRSTRLEN + 1]; - char if_index_name[IF_NAMESIZE + 1]; - if_index_name[0] = 0; - if(!inet_ntop(family, &in6->sin6_addr, a6, sizeof(a6))) { - log_err("inet_ntop failed"); - return 0; - } - (void)if_indextoname(in6->sin6_scope_id, - (char *)if_index_name); - if (strlen(if_index_name) != 0) { - snprintf(addr_buf, sizeof(addr_buf), - "%s%%%s%s", a6, if_index_name, atsign); - } else { - snprintf(addr_buf, sizeof(addr_buf), "%s%s", - a6, atsign); - } - } -#endif - else { - continue; - } - verbose(4, "interface %s has address %s", search_ifa, addr_buf); - - tmpbuf = realloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1)); - if(!tmpbuf) { - log_err("realloc failed: out of memory"); - return 0; - } else { - *ip_addresses = tmpbuf; - } - (*ip_addresses)[*ip_addresses_size] = strdup(addr_buf); - if(!(*ip_addresses)[*ip_addresses_size]) { - log_err("strdup failed: out of memory"); - return 0; - } - (*ip_addresses_size)++; - } - - if (*ip_addresses_size == last_ip_addresses_size) { - tmpbuf = realloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1)); - if(!tmpbuf) { - log_err("realloc failed: out of memory"); - return 0; - } else { - *ip_addresses = tmpbuf; - } - (*ip_addresses)[*ip_addresses_size] = strdup(search_ifa); - if(!(*ip_addresses)[*ip_addresses_size]) { - log_err("strdup failed: out of memory"); - return 0; - } - (*ip_addresses_size)++; - } - return 1; -} -#endif /* HAVE_GETIFADDRS */ - -int resolve_interface_names(char** ifs, int num_ifs, - struct config_strlist* list, char*** resif, int* num_resif) -{ -#ifdef HAVE_GETIFADDRS - struct ifaddrs *addrs = NULL; - if(num_ifs == 0 && list == NULL) { - *resif = NULL; - *num_resif = 0; - return 1; - } - if(getifaddrs(&addrs) == -1) { - log_err("failed to list interfaces: getifaddrs: %s", - strerror(errno)); - freeifaddrs(addrs); - return 0; - } - if(ifs) { - int i; - for(i=0; inext) { - if(!resolve_ifa_name(addrs, p->str, resif, num_resif)) { - freeifaddrs(addrs); - config_del_strarray(*resif, *num_resif); - *resif = NULL; - *num_resif = 0; - return 0; - } -} - } - freeifaddrs(addrs); - return 1; -#else - struct config_strlist* p; - if(num_ifs == 0 && list == NULL) { - *resif = NULL; - *num_resif = 0; - return 1; - } - *num_resif = num_ifs; - for(p = list; p; p = p->next) { - (*num_resif)++; - } - *resif = calloc(*num_resif, sizeof(**resif)); - if(!*resif) { - log_err("out of memory"); - return 0; - } - if(ifs) { - int i; - for(i=0; inext) { - (*resif)[idx] = strdup(p->str); - if(!((*resif)[idx])) { - log_err("out of memory"); - config_del_strarray(*resif, *num_resif); - *resif = NULL; - *num_resif = 0; - return 0; - } - idx++; - } - } - return 1; -#endif /* HAVE_GETIFADDRS */ -} - -struct listen_port* -listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs, - int* reuseport) -{ - struct listen_port* list = NULL; - struct addrinfo hints; - int i, do_ip4, do_ip6; - int do_tcp, do_auto; - char portbuf[32]; - snprintf(portbuf, sizeof(portbuf), "%d", cfg->port); - do_ip4 = cfg->do_ip4; - do_ip6 = cfg->do_ip6; - do_tcp = cfg->do_tcp; - do_auto = cfg->if_automatic && cfg->do_udp; - if(cfg->incoming_num_tcp == 0) - do_tcp = 0; - - /* getaddrinfo */ - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; - /* no name lookups on our listening ports */ - if(num_ifs > 0) - hints.ai_flags |= AI_NUMERICHOST; - hints.ai_family = AF_UNSPEC; -#ifndef INET6 - do_ip6 = 0; -#endif - if(!do_ip4 && !do_ip6) { - return NULL; - } - /* create ip4 and ip6 ports so that return addresses are nice. */ - if(do_auto || num_ifs == 0) { - if(do_auto && cfg->if_automatic_ports && - cfg->if_automatic_ports[0]!=0) { - char* now = cfg->if_automatic_ports; - while(now && *now) { - char* after; - int extraport; - while(isspace((unsigned char)*now)) - now++; - if(!*now) - break; - after = now; - extraport = (int)strtol(now, &after, 10); - if(extraport < 0 || extraport > 65535) { - log_err("interface-automatic-ports port number out of range, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports); - listening_ports_free(list); - return NULL; - } - if(extraport == 0 && now == after) { - log_err("interface-automatic-ports could not be parsed, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports); - listening_ports_free(list); - return NULL; - } - now = after; - snprintf(portbuf, sizeof(portbuf), "%d", extraport); - if(do_ip6) { - hints.ai_family = AF_INET6; - if(!ports_create_if("::0", - do_auto, cfg->do_udp, do_tcp, - &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, - cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } - if(do_ip4) { - hints.ai_family = AF_INET; - if(!ports_create_if("0.0.0.0", - do_auto, cfg->do_udp, do_tcp, - &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, - cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } - } - return list; - } - if(do_ip6) { - hints.ai_family = AF_INET6; - if(!ports_create_if(do_auto?"::0":"::1", - do_auto, cfg->do_udp, do_tcp, - &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } - if(do_ip4) { - hints.ai_family = AF_INET; - if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1", - do_auto, cfg->do_udp, do_tcp, - &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } - } else for(i = 0; ido_udp, - do_tcp, &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } else { - if(!do_ip4) - continue; - hints.ai_family = AF_INET; - if(!ports_create_if(ifs[i], 0, cfg->do_udp, - do_tcp, &hints, portbuf, &list, - cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port, cfg->tls_additional_port, - cfg->https_port, cfg->proxy_protocol_port, - reuseport, cfg->ip_transparent, - cfg->tcp_mss, cfg->ip_freebind, - cfg->http_nodelay, cfg->use_systemd, - cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) { - listening_ports_free(list); - return NULL; - } - } - } - - return list; -} - -void listening_ports_free(struct listen_port* list) -{ - struct listen_port* nx; - while(list) { - nx = list->next; - if(list->fd != -1) { - sock_close(list->fd); - } - /* rc_ports don't have ub_socket */ - if(list->socket) { - if(list->socket->addr) - freeaddrinfo(list->socket->addr); - free(list->socket); - } - free(list); - list = nx; - } -} - -size_t listen_get_mem(struct listen_dnsport* listen) -{ - struct listen_list* p; - size_t s = sizeof(*listen) + sizeof(*listen->base) + - sizeof(*listen->udp_buff) + - sldns_buffer_capacity(listen->udp_buff); -#ifdef USE_DNSCRYPT - s += sizeof(*listen->dnscrypt_udp_buff); - if(listen->udp_buff != listen->dnscrypt_udp_buff){ - s += sldns_buffer_capacity(listen->dnscrypt_udp_buff); - } -#endif - for(p = listen->cps; p; p = p->next) { - s += sizeof(*p); - s += comm_point_get_mem(p->com); - } - return s; -} - -void listen_stop_accept(struct listen_dnsport* listen) -{ - /* do not stop the ones that have no tcp_free list - * (they have already stopped listening) */ - struct listen_list* p; - for(p=listen->cps; p; p=p->next) { - if(p->com->type == comm_tcp_accept && - p->com->tcp_free != NULL) { - comm_point_stop_listening(p->com); - } - } -} - -void listen_start_accept(struct listen_dnsport* listen) -{ - /* do not start the ones that have no tcp_free list, it is no - * use to listen to them because they have no free tcp handlers */ - struct listen_list* p; - for(p=listen->cps; p; p=p->next) { - if(p->com->type == comm_tcp_accept && - p->com->tcp_free != NULL) { - comm_point_start_listening(p->com, -1, -1); - } - } -} - -struct tcp_req_info* -tcp_req_info_create(struct sldns_buffer* spoolbuf) -{ - struct tcp_req_info* req = (struct tcp_req_info*)malloc(sizeof(*req)); - if(!req) { - log_err("malloc failure for new stream outoforder processing structure"); - return NULL; - } - memset(req, 0, sizeof(*req)); - req->spool_buffer = spoolbuf; - return req; -} - -void -tcp_req_info_delete(struct tcp_req_info* req) -{ - if(!req) return; - tcp_req_info_clear(req); - /* cp is pointer back to commpoint that owns this struct and - * called delete on us */ - /* spool_buffer is shared udp buffer, not deleted here */ - free(req); -} - -void tcp_req_info_clear(struct tcp_req_info* req) -{ - struct tcp_req_open_item* open, *nopen; - struct tcp_req_done_item* item, *nitem; - if(!req) return; - - /* free outstanding request mesh reply entries */ - open = req->open_req_list; - while(open) { - nopen = open->next; - mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp); - free(open); - open = nopen; - } - req->open_req_list = NULL; - req->num_open_req = 0; - - /* free pending writable result packets */ - item = req->done_req_list; - while(item) { - nitem = item->next; - lock_basic_lock(&stream_wait_count_lock); - stream_wait_count -= (sizeof(struct tcp_req_done_item) - +item->len); - lock_basic_unlock(&stream_wait_count_lock); - free(item->buf); - free(item); - item = nitem; - } - req->done_req_list = NULL; - req->num_done_req = 0; - req->read_is_closed = 0; -} - -void -tcp_req_info_remove_mesh_state(struct tcp_req_info* req, struct mesh_state* m) -{ - struct tcp_req_open_item* open, *prev = NULL; - if(!req || !m) return; - open = req->open_req_list; - while(open) { - if(open->mesh_state == m) { - struct tcp_req_open_item* next; - if(prev) prev->next = open->next; - else req->open_req_list = open->next; - /* caller has to manage the mesh state reply entry */ - next = open->next; - free(open); - req->num_open_req --; - - /* prev = prev; */ - open = next; - continue; - } - prev = open; - open = open->next; - } -} - -/** setup listening for read or write */ -static void -tcp_req_info_setup_listen(struct tcp_req_info* req) -{ - int wr = 0; - int rd = 0; - - if(req->cp->tcp_byte_count != 0) { - /* cannot change, halfway through */ - return; - } - - if(!req->cp->tcp_is_reading) - wr = 1; - if(!req->read_is_closed) - rd = 1; - - if(wr) { - req->cp->tcp_is_reading = 0; - comm_point_stop_listening(req->cp); - comm_point_start_listening(req->cp, -1, - adjusted_tcp_timeout(req->cp)); - } else if(rd) { - req->cp->tcp_is_reading = 1; - comm_point_stop_listening(req->cp); - comm_point_start_listening(req->cp, -1, - adjusted_tcp_timeout(req->cp)); - /* and also read it (from SSL stack buffers), so - * no event read event is expected since the remainder of - * the TLS frame is sitting in the buffers. */ - req->read_again = 1; - } else { - comm_point_stop_listening(req->cp); - comm_point_start_listening(req->cp, -1, - adjusted_tcp_timeout(req->cp)); - comm_point_listen_for_rw(req->cp, 0, 0); - } -} - -/** remove first item from list of pending results */ -static struct tcp_req_done_item* -tcp_req_info_pop_done(struct tcp_req_info* req) -{ - struct tcp_req_done_item* item; - log_assert(req->num_done_req > 0 && req->done_req_list); - item = req->done_req_list; - lock_basic_lock(&stream_wait_count_lock); - stream_wait_count -= (sizeof(struct tcp_req_done_item)+item->len); - lock_basic_unlock(&stream_wait_count_lock); - req->done_req_list = req->done_req_list->next; - req->num_done_req --; - return item; -} - -/** Send given buffer and setup to write */ -static void -tcp_req_info_start_write_buf(struct tcp_req_info* req, uint8_t* buf, - size_t len) -{ - sldns_buffer_clear(req->cp->buffer); - sldns_buffer_write(req->cp->buffer, buf, len); - sldns_buffer_flip(req->cp->buffer); - - req->cp->tcp_is_reading = 0; /* we are now writing */ -} - -/** pick up the next result and start writing it to the channel */ -static void -tcp_req_pickup_next_result(struct tcp_req_info* req) -{ - if(req->num_done_req > 0) { - /* unlist the done item from the list of pending results */ - struct tcp_req_done_item* item = tcp_req_info_pop_done(req); - tcp_req_info_start_write_buf(req, item->buf, item->len); - free(item->buf); - free(item); - } -} - -/** the read channel has closed */ -int -tcp_req_info_handle_read_close(struct tcp_req_info* req) -{ - verbose(VERB_ALGO, "tcp channel read side closed %d", req->cp->fd); - /* reset byte count for (potential) partial read */ - req->cp->tcp_byte_count = 0; - /* if we still have results to write, pick up next and write it */ - if(req->num_done_req != 0) { - tcp_req_pickup_next_result(req); - tcp_req_info_setup_listen(req); - return 1; - } - /* if nothing to do, this closes the connection */ - if(req->num_open_req == 0 && req->num_done_req == 0) - return 0; - /* otherwise, we must be waiting for dns resolve, wait with timeout */ - req->read_is_closed = 1; - tcp_req_info_setup_listen(req); - return 1; -} - -void -tcp_req_info_handle_writedone(struct tcp_req_info* req) -{ - /* back to reading state, we finished this write event */ - sldns_buffer_clear(req->cp->buffer); - if(req->num_done_req == 0 && req->read_is_closed) { - /* no more to write and nothing to read, close it */ - comm_point_drop_reply(&req->cp->repinfo); - return; - } - req->cp->tcp_is_reading = 1; - /* see if another result needs writing */ - tcp_req_pickup_next_result(req); - - /* see if there is more to write, if not stop_listening for writing */ - /* see if new requests are allowed, if so, start_listening - * for reading */ - tcp_req_info_setup_listen(req); -} - -void -tcp_req_info_handle_readdone(struct tcp_req_info* req) -{ - struct comm_point* c = req->cp; - - /* we want to read up several requests, unless there are - * pending answers */ - - req->is_drop = 0; - req->is_reply = 0; - req->in_worker_handle = 1; - sldns_buffer_set_limit(req->spool_buffer, 0); - /* handle the current request */ - /* this calls the worker handle request routine that could give - * a cache response, or localdata response, or drop the reply, - * or schedule a mesh entry for later */ - fptr_ok(fptr_whitelist_comm_point(c->callback)); - if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) { - req->in_worker_handle = 0; - /* there is an answer, put it up. It is already in the - * c->buffer, just send it. */ - /* since we were just reading a query, the channel is - * clear to write to */ - send_it: - c->tcp_is_reading = 0; - comm_point_stop_listening(c); - comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); - return; - } - req->in_worker_handle = 0; - /* it should be waiting in the mesh for recursion. - * If mesh failed to add a new entry and called commpoint_drop_reply. - * Then the mesh state has been cleared. */ - if(req->is_drop) { - /* the reply has been dropped, stream has been closed. */ - return; - } - /* If mesh failed(mallocfail) and called commpoint_send_reply with - * something like servfail then we pick up that reply below. */ - if(req->is_reply) { - goto send_it; - } - - sldns_buffer_clear(c->buffer); - /* if pending answers, pick up an answer and start sending it */ - tcp_req_pickup_next_result(req); - - /* if answers pending, start sending answers */ - /* read more requests if we can have more requests */ - tcp_req_info_setup_listen(req); -} - -int -tcp_req_info_add_meshstate(struct tcp_req_info* req, - struct mesh_area* mesh, struct mesh_state* m) -{ - struct tcp_req_open_item* item; - log_assert(req && mesh && m); - item = (struct tcp_req_open_item*)malloc(sizeof(*item)); - if(!item) return 0; - item->next = req->open_req_list; - item->mesh = mesh; - item->mesh_state = m; - req->open_req_list = item; - req->num_open_req++; - return 1; -} - -/** Add a result to the result list. At the end. */ -static int -tcp_req_info_add_result(struct tcp_req_info* req, uint8_t* buf, size_t len) -{ - struct tcp_req_done_item* last = NULL; - struct tcp_req_done_item* item; - size_t space; - - /* see if we have space */ - space = sizeof(struct tcp_req_done_item) + len; - lock_basic_lock(&stream_wait_count_lock); - if(stream_wait_count + space > stream_wait_max) { - lock_basic_unlock(&stream_wait_count_lock); - verbose(VERB_ALGO, "drop stream reply, no space left, in stream-wait-size"); - return 0; - } - stream_wait_count += space; - lock_basic_unlock(&stream_wait_count_lock); - - /* find last element */ - last = req->done_req_list; - while(last && last->next) - last = last->next; - - /* create new element */ - item = (struct tcp_req_done_item*)malloc(sizeof(*item)); - if(!item) { - log_err("malloc failure, for stream result list"); - return 0; - } - item->next = NULL; - item->len = len; - item->buf = memdup(buf, len); - if(!item->buf) { - free(item); - log_err("malloc failure, adding reply to stream result list"); - return 0; - } - - /* link in */ - if(last) last->next = item; - else req->done_req_list = item; - req->num_done_req++; - return 1; -} - -void -tcp_req_info_send_reply(struct tcp_req_info* req) -{ - if(req->in_worker_handle) { - /* reply from mesh is in the spool_buffer */ - /* copy now, so that the spool buffer is free for other tasks - * before the callback is done */ - sldns_buffer_clear(req->cp->buffer); - sldns_buffer_write(req->cp->buffer, - sldns_buffer_begin(req->spool_buffer), - sldns_buffer_limit(req->spool_buffer)); - sldns_buffer_flip(req->cp->buffer); - req->is_reply = 1; - return; - } - /* now that the query has been handled, that mesh_reply entry - * should be removed, from the tcp_req_info list, - * the mesh state cleanup removes then with region_cleanup and - * replies_sent true. */ - /* see if we can send it straight away (we are not doing - * anything else). If so, copy to buffer and start */ - if(req->cp->tcp_is_reading && req->cp->tcp_byte_count == 0) { - /* buffer is free, and was ready to read new query into, - * but we are now going to use it to send this answer */ - tcp_req_info_start_write_buf(req, - sldns_buffer_begin(req->spool_buffer), - sldns_buffer_limit(req->spool_buffer)); - /* switch to listen to write events */ - comm_point_stop_listening(req->cp); - comm_point_start_listening(req->cp, -1, - adjusted_tcp_timeout(req->cp)); - return; - } - /* queue up the answer behind the others already pending */ - if(!tcp_req_info_add_result(req, sldns_buffer_begin(req->spool_buffer), - sldns_buffer_limit(req->spool_buffer))) { - /* drop the connection, we are out of resources */ - comm_point_drop_reply(&req->cp->repinfo); - } -} - -size_t tcp_req_info_get_stream_buffer_size(void) -{ - size_t s; - if(!stream_wait_lock_inited) - return stream_wait_count; - lock_basic_lock(&stream_wait_count_lock); - s = stream_wait_count; - lock_basic_unlock(&stream_wait_count_lock); - return s; -} - -size_t http2_get_query_buffer_size(void) -{ - size_t s; - if(!http2_query_buffer_lock_inited) - return http2_query_buffer_count; - lock_basic_lock(&http2_query_buffer_count_lock); - s = http2_query_buffer_count; - lock_basic_unlock(&http2_query_buffer_count_lock); - return s; -} - -size_t http2_get_response_buffer_size(void) -{ - size_t s; - if(!http2_response_buffer_lock_inited) - return http2_response_buffer_count; - lock_basic_lock(&http2_response_buffer_count_lock); - s = http2_response_buffer_count; - lock_basic_unlock(&http2_response_buffer_count_lock); - return s; -} - -#ifdef HAVE_NGHTTP2 -/** nghttp2 callback. Used to copy response from rbuffer to nghttp2 session */ -static ssize_t http2_submit_response_read_callback( - nghttp2_session* ATTR_UNUSED(session), - int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags, - nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg)) -{ - struct http2_stream* h2_stream; - struct http2_session* h2_session = source->ptr; - size_t copylen = length; - if(!(h2_stream = nghttp2_session_get_stream_user_data( - h2_session->session, stream_id))) { - verbose(VERB_QUERY, "http2: cannot get stream data, closing " - "stream"); - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - if(!h2_stream->rbuffer || - sldns_buffer_remaining(h2_stream->rbuffer) == 0) { - verbose(VERB_QUERY, "http2: cannot submit buffer. No data " - "available in rbuffer"); - /* rbuffer will be free'd in frame close cb */ - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - if(copylen > sldns_buffer_remaining(h2_stream->rbuffer)) - copylen = sldns_buffer_remaining(h2_stream->rbuffer); - if(copylen > SSIZE_MAX) - copylen = SSIZE_MAX; /* will probably never happen */ - - memcpy(buf, sldns_buffer_current(h2_stream->rbuffer), copylen); - sldns_buffer_skip(h2_stream->rbuffer, copylen); - - if(sldns_buffer_remaining(h2_stream->rbuffer) == 0) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - lock_basic_lock(&http2_response_buffer_count_lock); - http2_response_buffer_count -= - sldns_buffer_capacity(h2_stream->rbuffer); - lock_basic_unlock(&http2_response_buffer_count_lock); - sldns_buffer_free(h2_stream->rbuffer); - h2_stream->rbuffer = NULL; - } - - return copylen; -} - -/** - * Send RST_STREAM frame for stream. - * @param h2_session: http2 session to submit frame to - * @param h2_stream: http2 stream containing frame ID to use in RST_STREAM - * @return 0 on error, 1 otherwise - */ -static int http2_submit_rst_stream(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - int ret = nghttp2_submit_rst_stream(h2_session->session, - NGHTTP2_FLAG_NONE, h2_stream->stream_id, - NGHTTP2_INTERNAL_ERROR); - if(ret) { - verbose(VERB_QUERY, "http2: nghttp2_submit_rst_stream failed, " - "error: %s", nghttp2_strerror(ret)); - return 0; - } - return 1; -} - -/** - * DNS response ready to be submitted to nghttp2, to be prepared for sending - * out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer - * might be used before this will be sent out. - * @param h2_session: http2 session, containing c->buffer which contains answer - * @return 0 on error, 1 otherwise - */ -int http2_submit_dns_response(struct http2_session* h2_session) -{ - int ret; - nghttp2_data_provider data_prd; - char status[4]; - nghttp2_nv headers[3]; - struct http2_stream* h2_stream = h2_session->c->h2_stream; - size_t rlen; - char rlen_str[32]; - - if(h2_stream->rbuffer) { - log_err("http2 submit response error: rbuffer already " - "exists"); - return 0; - } - if(sldns_buffer_remaining(h2_session->c->buffer) == 0) { - log_err("http2 submit response error: c->buffer not complete"); - return 0; - } - - if(snprintf(status, 4, "%d", h2_stream->status) != 3) { - verbose(VERB_QUERY, "http2: submit response error: " - "invalid status"); - return 0; - } - - rlen = sldns_buffer_remaining(h2_session->c->buffer); - snprintf(rlen_str, sizeof(rlen_str), "%u", (unsigned)rlen); - - lock_basic_lock(&http2_response_buffer_count_lock); - if(http2_response_buffer_count + rlen > http2_response_buffer_max) { - lock_basic_unlock(&http2_response_buffer_count_lock); - verbose(VERB_ALGO, "reset HTTP2 stream, no space left, " - "in https-response-buffer-size"); - return http2_submit_rst_stream(h2_session, h2_stream); - } - http2_response_buffer_count += rlen; - lock_basic_unlock(&http2_response_buffer_count_lock); - - if(!(h2_stream->rbuffer = sldns_buffer_new(rlen))) { - lock_basic_lock(&http2_response_buffer_count_lock); - http2_response_buffer_count -= rlen; - lock_basic_unlock(&http2_response_buffer_count_lock); - log_err("http2 submit response error: malloc failure"); - return 0; - } - - headers[0].name = (uint8_t*)":status"; - headers[0].namelen = 7; - headers[0].value = (uint8_t*)status; - headers[0].valuelen = 3; - headers[0].flags = NGHTTP2_NV_FLAG_NONE; - - headers[1].name = (uint8_t*)"content-type"; - headers[1].namelen = 12; - headers[1].value = (uint8_t*)"application/dns-message"; - headers[1].valuelen = 23; - headers[1].flags = NGHTTP2_NV_FLAG_NONE; - - headers[2].name = (uint8_t*)"content-length"; - headers[2].namelen = 14; - headers[2].value = (uint8_t*)rlen_str; - headers[2].valuelen = strlen(rlen_str); - headers[2].flags = NGHTTP2_NV_FLAG_NONE; - - sldns_buffer_write(h2_stream->rbuffer, - sldns_buffer_current(h2_session->c->buffer), - sldns_buffer_remaining(h2_session->c->buffer)); - sldns_buffer_flip(h2_stream->rbuffer); - - data_prd.source.ptr = h2_session; - data_prd.read_callback = http2_submit_response_read_callback; - ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id, - headers, 3, &data_prd); - if(ret) { - verbose(VERB_QUERY, "http2: set_stream_user_data failed, " - "error: %s", nghttp2_strerror(ret)); - return 0; - } - return 1; -} -#else -int http2_submit_dns_response(void* ATTR_UNUSED(v)) -{ - return 0; -} -#endif - -#ifdef HAVE_NGHTTP2 -/** HTTP status to descriptive string */ -static char* http_status_to_str(enum http_status s) -{ - switch(s) { - case HTTP_STATUS_OK: - return "OK"; - case HTTP_STATUS_BAD_REQUEST: - return "Bad Request"; - case HTTP_STATUS_NOT_FOUND: - return "Not Found"; - case HTTP_STATUS_PAYLOAD_TOO_LARGE: - return "Payload Too Large"; - case HTTP_STATUS_URI_TOO_LONG: - return "URI Too Long"; - case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: - return "Unsupported Media Type"; - case HTTP_STATUS_NOT_IMPLEMENTED: - return "Not Implemented"; - } - return "Status Unknown"; -} - -/** nghttp2 callback. Used to copy error message to nghttp2 session */ -static ssize_t http2_submit_error_read_callback( - nghttp2_session* ATTR_UNUSED(session), - int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags, - nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg)) -{ - struct http2_stream* h2_stream; - struct http2_session* h2_session = source->ptr; - char* msg; - if(!(h2_stream = nghttp2_session_get_stream_user_data( - h2_session->session, stream_id))) { - verbose(VERB_QUERY, "http2: cannot get stream data, closing " - "stream"); - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - msg = http_status_to_str(h2_stream->status); - if(length < strlen(msg)) - return 0; /* not worth trying over multiple frames */ - memcpy(buf, msg, strlen(msg)); - return strlen(msg); - -} - -/** - * HTTP error response ready to be submitted to nghttp2, to be prepared for - * sending out. Message body will contain descriptive string for HTTP status. - * @param h2_session: http2 session to submit to - * @param h2_stream: http2 stream containing HTTP status to use for error - * @return 0 on error, 1 otherwise - */ -static int http2_submit_error(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - int ret; - char status[4]; - nghttp2_data_provider data_prd; - nghttp2_nv headers[1]; /* will be copied by nghttp */ - if(snprintf(status, 4, "%d", h2_stream->status) != 3) { - verbose(VERB_QUERY, "http2: submit error failed, " - "invalid status"); - return 0; - } - headers[0].name = (uint8_t*)":status"; - headers[0].namelen = 7; - headers[0].value = (uint8_t*)status; - headers[0].valuelen = 3; - headers[0].flags = NGHTTP2_NV_FLAG_NONE; - - data_prd.source.ptr = h2_session; - data_prd.read_callback = http2_submit_error_read_callback; - - ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id, - headers, 1, &data_prd); - if(ret) { - verbose(VERB_QUERY, "http2: submit error failed, " - "error: %s", nghttp2_strerror(ret)); - return 0; - } - return 1; -} - -/** - * Start query handling. Query is stored in the stream, and will be free'd here. - * @param h2_session: http2 session, containing comm point - * @param h2_stream: stream containing buffered query - * @return: -1 on error, 1 if answer is stored in c->buffer, 0 if there is no - * reply available (yet). - */ -static int http2_query_read_done(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - log_assert(h2_stream->qbuffer); - - if(h2_session->c->h2_stream) { - verbose(VERB_ALGO, "http2_query_read_done failure: shared " - "buffer already assigned to stream"); - return -1; - } - - /* the c->buffer might be used by mesh_send_reply and no be cleard - * need to be cleared before use */ - sldns_buffer_clear(h2_session->c->buffer); - if(sldns_buffer_remaining(h2_session->c->buffer) < - sldns_buffer_remaining(h2_stream->qbuffer)) { - /* qbuffer will be free'd in frame close cb */ - sldns_buffer_clear(h2_session->c->buffer); - verbose(VERB_ALGO, "http2_query_read_done failure: can't fit " - "qbuffer in c->buffer"); - return -1; - } - - sldns_buffer_write(h2_session->c->buffer, - sldns_buffer_current(h2_stream->qbuffer), - sldns_buffer_remaining(h2_stream->qbuffer)); - - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= sldns_buffer_capacity(h2_stream->qbuffer); - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - - sldns_buffer_flip(h2_session->c->buffer); - h2_session->c->h2_stream = h2_stream; - fptr_ok(fptr_whitelist_comm_point(h2_session->c->callback)); - if((*h2_session->c->callback)(h2_session->c, h2_session->c->cb_arg, - NETEVENT_NOERROR, &h2_session->c->repinfo)) { - return 1; /* answer in c->buffer */ - } - sldns_buffer_clear(h2_session->c->buffer); - h2_session->c->h2_stream = NULL; - return 0; /* mesh state added, or dropped */ -} - -/** nghttp2 callback. Used to check if the received frame indicates the end of a - * stream. Gather collected request data and start query handling. */ -static int http2_req_frame_recv_cb(nghttp2_session* session, - const nghttp2_frame* frame, void* cb_arg) -{ - struct http2_session* h2_session = (struct http2_session*)cb_arg; - struct http2_stream* h2_stream; - int query_read_done; - - if((frame->hd.type != NGHTTP2_DATA && - frame->hd.type != NGHTTP2_HEADERS) || - !(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - return 0; - } - - if(!(h2_stream = nghttp2_session_get_stream_user_data( - session, frame->hd.stream_id))) - return 0; - - if(h2_stream->invalid_endpoint) { - h2_stream->status = HTTP_STATUS_NOT_FOUND; - goto submit_http_error; - } - - if(h2_stream->invalid_content_type) { - h2_stream->status = HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE; - goto submit_http_error; - } - - if(h2_stream->http_method != HTTP_METHOD_GET && - h2_stream->http_method != HTTP_METHOD_POST) { - h2_stream->status = HTTP_STATUS_NOT_IMPLEMENTED; - goto submit_http_error; - } - - if(h2_stream->query_too_large) { - if(h2_stream->http_method == HTTP_METHOD_POST) - h2_stream->status = HTTP_STATUS_PAYLOAD_TOO_LARGE; - else - h2_stream->status = HTTP_STATUS_URI_TOO_LONG; - goto submit_http_error; - } - - if(!h2_stream->qbuffer) { - h2_stream->status = HTTP_STATUS_BAD_REQUEST; - goto submit_http_error; - } - - if(h2_stream->status) { -submit_http_error: - verbose(VERB_QUERY, "http2 request invalid, returning :status=" - "%d", h2_stream->status); - if(!http2_submit_error(h2_session, h2_stream)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - h2_stream->status = HTTP_STATUS_OK; - - sldns_buffer_flip(h2_stream->qbuffer); - h2_session->postpone_drop = 1; - query_read_done = http2_query_read_done(h2_session, h2_stream); - if(query_read_done < 0) - return NGHTTP2_ERR_CALLBACK_FAILURE; - else if(!query_read_done) { - if(h2_session->is_drop) { - /* connection needs to be closed. Return failure to make - * sure no other action are taken anymore on comm point. - * failure will result in reclaiming (and closing) - * of comm point. */ - verbose(VERB_QUERY, "http2 query dropped in worker cb"); - h2_session->postpone_drop = 0; - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - /* nothing to submit right now, query added to mesh. */ - h2_session->postpone_drop = 0; - return 0; - } - if(!http2_submit_dns_response(h2_session)) { - sldns_buffer_clear(h2_session->c->buffer); - h2_session->c->h2_stream = NULL; - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - verbose(VERB_QUERY, "http2 query submitted to session"); - sldns_buffer_clear(h2_session->c->buffer); - h2_session->c->h2_stream = NULL; - return 0; -} - -/** nghttp2 callback. Used to detect start of new streams. */ -static int http2_req_begin_headers_cb(nghttp2_session* session, - const nghttp2_frame* frame, void* cb_arg) -{ - struct http2_session* h2_session = (struct http2_session*)cb_arg; - struct http2_stream* h2_stream; - int ret; - if(frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - /* only interested in request headers */ - return 0; - } - if(!(h2_stream = http2_stream_create(frame->hd.stream_id))) { - log_err("malloc failure while creating http2 stream"); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - http2_session_add_stream(h2_session, h2_stream); - ret = nghttp2_session_set_stream_user_data(session, - frame->hd.stream_id, h2_stream); - if(ret) { - /* stream does not exist */ - verbose(VERB_QUERY, "http2: set_stream_user_data failed, " - "error: %s", nghttp2_strerror(ret)); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - return 0; -} - -/** - * base64url decode, store in qbuffer - * @param h2_session: http2 session - * @param h2_stream: http2 stream - * @param start: start of the base64 string - * @param length: length of the base64 string - * @return: 0 on error, 1 otherwise. query will be stored in h2_stream->qbuffer, - * buffer will be NULL is unparseble. - */ -static int http2_buffer_uri_query(struct http2_session* h2_session, - struct http2_stream* h2_stream, const uint8_t* start, size_t length) -{ - size_t expectb64len; - int b64len; - if(h2_stream->http_method == HTTP_METHOD_POST) - return 1; - if(length == 0) - return 1; - if(h2_stream->qbuffer) { - verbose(VERB_ALGO, "http2_req_header fail, " - "qbuffer already set"); - return 0; - } - - /* calculate size, might be a bit bigger than the real - * decoded buffer size */ - expectb64len = sldns_b64_pton_calculate_size(length); - log_assert(expectb64len > 0); - if(expectb64len > - h2_session->c->http2_stream_max_qbuffer_size) { - h2_stream->query_too_large = 1; - return 1; - } - - lock_basic_lock(&http2_query_buffer_count_lock); - if(http2_query_buffer_count + expectb64len > http2_query_buffer_max) { - lock_basic_unlock(&http2_query_buffer_count_lock); - verbose(VERB_ALGO, "reset HTTP2 stream, no space left, " - "in http2-query-buffer-size"); - return http2_submit_rst_stream(h2_session, h2_stream); - } - http2_query_buffer_count += expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - if(!(h2_stream->qbuffer = sldns_buffer_new(expectb64len))) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - log_err("http2_req_header fail, qbuffer " - "malloc failure"); - return 0; - } - - if(sldns_b64_contains_nonurl((char const*)start, length)) { - char buf[65536+4]; - verbose(VERB_ALGO, "HTTP2 stream contains wrong b64 encoding"); - /* copy to the scratch buffer temporarily to terminate the - * string with a zero */ - if(length+1 > sizeof(buf)) { - /* too long */ - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - return 1; - } - memmove(buf, start, length); - buf[length] = 0; - if(!(b64len = sldns_b64_pton(buf, sldns_buffer_current( - h2_stream->qbuffer), expectb64len)) || b64len < 0) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - return 1; - } - } else { - if(!(b64len = sldns_b64url_pton( - (char const *)start, length, - sldns_buffer_current(h2_stream->qbuffer), - expectb64len)) || b64len < 0) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - /* return without error, method can be an - * unknown POST */ - return 1; - } - } - sldns_buffer_skip(h2_stream->qbuffer, (size_t)b64len); - return 1; -} - -/** nghttp2 callback. Used to parse headers from HEADER frames. */ -static int http2_req_header_cb(nghttp2_session* session, - const nghttp2_frame* frame, const uint8_t* name, size_t namelen, - const uint8_t* value, size_t valuelen, uint8_t ATTR_UNUSED(flags), - void* cb_arg) -{ - struct http2_stream* h2_stream = NULL; - struct http2_session* h2_session = (struct http2_session*)cb_arg; - /* nghttp2 deals with CONTINUATION frames and provides them as part of - * the HEADER */ - if(frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - /* only interested in request headers */ - return 0; - } - if(!(h2_stream = nghttp2_session_get_stream_user_data(session, - frame->hd.stream_id))) - return 0; - - /* earlier checks already indicate we can stop handling this query */ - if(h2_stream->http_method == HTTP_METHOD_UNSUPPORTED || - h2_stream->invalid_content_type || - h2_stream->invalid_endpoint) - return 0; - - - /* nghttp2 performs some sanity checks in the headers, including: - * name and value are guaranteed to be null terminated - * name is guaranteed to be lowercase - * content-length value is guaranteed to contain digits - */ - - if(!h2_stream->http_method && namelen == 7 && - memcmp(":method", name, namelen) == 0) { - /* Case insensitive check on :method value to be on the safe - * side. I failed to find text about case sensitivity in specs. - */ - if(valuelen == 3 && strcasecmp("GET", (const char*)value) == 0) - h2_stream->http_method = HTTP_METHOD_GET; - else if(valuelen == 4 && - strcasecmp("POST", (const char*)value) == 0) { - h2_stream->http_method = HTTP_METHOD_POST; - if(h2_stream->qbuffer) { - /* POST method uses query from DATA frames */ - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= - sldns_buffer_capacity(h2_stream->qbuffer); - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - } - } else - h2_stream->http_method = HTTP_METHOD_UNSUPPORTED; - return 0; - } - if(namelen == 5 && memcmp(":path", name, namelen) == 0) { - /* :path may contain DNS query, depending on method. Method might - * not be known yet here, so check after finishing receiving - * stream. */ -#define HTTP_QUERY_PARAM "?dns=" - size_t el = strlen(h2_session->c->http_endpoint); - size_t qpl = strlen(HTTP_QUERY_PARAM); - - if(valuelen < el || memcmp(h2_session->c->http_endpoint, - value, el) != 0) { - h2_stream->invalid_endpoint = 1; - return 0; - } - /* larger than endpoint only allowed if it is for the query - * parameter */ - if(valuelen <= el+qpl || - memcmp(HTTP_QUERY_PARAM, value+el, qpl) != 0) { - if(valuelen != el) - h2_stream->invalid_endpoint = 1; - return 0; - } - - if(!http2_buffer_uri_query(h2_session, h2_stream, - value+(el+qpl), valuelen-(el+qpl))) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - /* Content type is a SHOULD (rfc7231#section-3.1.1.5) when using POST, - * and not needed when using GET. Don't enfore. - * If set only allow lowercase "application/dns-message". - * - * Clients SHOULD (rfc8484#section-4.1) set an accept header, but MUST - * be able to handle "application/dns-message". Since that is the only - * content-type supported we can ignore the accept header. - */ - if((namelen == 12 && memcmp("content-type", name, namelen) == 0)) { - if(valuelen != 23 || memcmp("application/dns-message", value, - valuelen) != 0) { - h2_stream->invalid_content_type = 1; - } - } - - /* Only interested in content-lentg for POST (on not yet known) method. - */ - if((!h2_stream->http_method || - h2_stream->http_method == HTTP_METHOD_POST) && - !h2_stream->content_length && namelen == 14 && - memcmp("content-length", name, namelen) == 0) { - if(valuelen > 5) { - h2_stream->query_too_large = 1; - return 0; - } - /* guaranteed to only contain digits and be null terminated */ - h2_stream->content_length = atoi((const char*)value); - if(h2_stream->content_length > - h2_session->c->http2_stream_max_qbuffer_size) { - h2_stream->query_too_large = 1; - return 0; - } - } - return 0; -} - -/** nghttp2 callback. Used to get data from DATA frames, which can contain - * queries in POST requests. */ -static int http2_req_data_chunk_recv_cb(nghttp2_session* ATTR_UNUSED(session), - uint8_t ATTR_UNUSED(flags), int32_t stream_id, const uint8_t* data, - size_t len, void* cb_arg) -{ - struct http2_session* h2_session = (struct http2_session*)cb_arg; - struct http2_stream* h2_stream; - size_t qlen = 0; - - if(!(h2_stream = nghttp2_session_get_stream_user_data( - h2_session->session, stream_id))) { - return 0; - } - - if(h2_stream->query_too_large) - return 0; - - if(!h2_stream->qbuffer) { - if(h2_stream->content_length) { - if(h2_stream->content_length < len) - /* getting more data in DATA frame than - * advertised in content-length header. */ - return NGHTTP2_ERR_CALLBACK_FAILURE; - qlen = h2_stream->content_length; - } else if(len <= h2_session->c->http2_stream_max_qbuffer_size) { - /* setting this to msg-buffer-size can result in a lot - * of memory consuption. Most queries should fit in a - * single DATA frame, and most POST queries will - * contain content-length which does not impose this - * limit. */ - qlen = len; - } - } - if(!h2_stream->qbuffer && qlen) { - lock_basic_lock(&http2_query_buffer_count_lock); - if(http2_query_buffer_count + qlen > http2_query_buffer_max) { - lock_basic_unlock(&http2_query_buffer_count_lock); - verbose(VERB_ALGO, "reset HTTP2 stream, no space left, " - "in http2-query-buffer-size"); - return http2_submit_rst_stream(h2_session, h2_stream); - } - http2_query_buffer_count += qlen; - lock_basic_unlock(&http2_query_buffer_count_lock); - if(!(h2_stream->qbuffer = sldns_buffer_new(qlen))) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= qlen; - lock_basic_unlock(&http2_query_buffer_count_lock); - } - } - - if(!h2_stream->qbuffer || - sldns_buffer_remaining(h2_stream->qbuffer) < len) { - verbose(VERB_ALGO, "http2 data_chunck_recv failed. Not enough " - "buffer space for POST query. Can happen on multi " - "frame requests without content-length header"); - h2_stream->query_too_large = 1; - return 0; - } - - sldns_buffer_write(h2_stream->qbuffer, data, len); - - return 0; -} - -void http2_req_stream_clear(struct http2_stream* h2_stream) -{ - if(h2_stream->qbuffer) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= - sldns_buffer_capacity(h2_stream->qbuffer); - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - } - if(h2_stream->rbuffer) { - lock_basic_lock(&http2_response_buffer_count_lock); - http2_response_buffer_count -= - sldns_buffer_capacity(h2_stream->rbuffer); - lock_basic_unlock(&http2_response_buffer_count_lock); - sldns_buffer_free(h2_stream->rbuffer); - h2_stream->rbuffer = NULL; - } -} - -nghttp2_session_callbacks* http2_req_callbacks_create(void) -{ - nghttp2_session_callbacks *callbacks; - if(nghttp2_session_callbacks_new(&callbacks) == NGHTTP2_ERR_NOMEM) { - log_err("failed to initialize nghttp2 callback"); - return NULL; - } - /* reception of header block started, used to create h2_stream */ - nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks, - http2_req_begin_headers_cb); - /* complete frame received, used to get data from stream if frame - * has end stream flag, and start processing query */ - nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, - http2_req_frame_recv_cb); - /* get request info from headers */ - nghttp2_session_callbacks_set_on_header_callback(callbacks, - http2_req_header_cb); - /* get data from DATA frames, containing POST query */ - nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, - http2_req_data_chunk_recv_cb); - - /* generic HTTP2 callbacks */ - nghttp2_session_callbacks_set_recv_callback(callbacks, http2_recv_cb); - nghttp2_session_callbacks_set_send_callback(callbacks, http2_send_cb); - nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, - http2_stream_close_cb); - - return callbacks; -} -#endif /* HAVE_NGHTTP2 */ diff --git a/crates/libunbound-sys/unbound/services/listen_dnsport.h b/crates/libunbound-sys/unbound/services/listen_dnsport.h deleted file mode 100644 index 816d79ae..00000000 --- a/crates/libunbound-sys/unbound/services/listen_dnsport.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * services/listen_dnsport.h - listen on port 53 for incoming DNS queries. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has functions to get queries from clients. - */ - -#ifndef LISTEN_DNSPORT_H -#define LISTEN_DNSPORT_H - -#include "util/netevent.h" -#include "daemon/acl_list.h" -#ifdef HAVE_NGHTTP2_NGHTTP2_H -#include -#endif -struct listen_list; -struct config_file; -struct addrinfo; -struct sldns_buffer; -struct tcl_list; - -/** - * Listening for queries structure. - * Contains list of query-listen sockets. - */ -struct listen_dnsport { - /** Base for select calls */ - struct comm_base* base; - - /** buffer shared by UDP connections, since there is only one - datagram at any time. */ - struct sldns_buffer* udp_buff; -#ifdef USE_DNSCRYPT - struct sldns_buffer* dnscrypt_udp_buff; -#endif - /** list of comm points used to get incoming events */ - struct listen_list* cps; -}; - -/** - * Single linked list to store event points. - */ -struct listen_list { - /** next in list */ - struct listen_list* next; - /** event info */ - struct comm_point* com; -}; - -/** - * type of ports - */ -enum listen_type { - /** udp type */ - listen_type_udp, - /** tcp type */ - listen_type_tcp, - /** udp ipv6 (v4mapped) for use with ancillary data */ - listen_type_udpancil, - /** ssl over tcp type */ - listen_type_ssl, - /** udp type + dnscrypt*/ - listen_type_udp_dnscrypt, - /** tcp type + dnscrypt */ - listen_type_tcp_dnscrypt, - /** udp ipv6 (v4mapped) for use with ancillary data + dnscrypt*/ - listen_type_udpancil_dnscrypt, - /** HTTP(2) over TLS over TCP */ - listen_type_http -}; - -/* - * socket properties (just like NSD nsd_socket structure definition) - */ -struct unbound_socket { - /** socket-address structure */ - struct addrinfo* addr; - /** socket descriptor returned by socket() syscall */ - int s; - /** address family (AF_INET/IF_INET6) */ - int fam; - /** ACL on the socket (listening interface) */ - struct acl_addr* acl; -}; - -/** - * Single linked list to store shared ports that have been - * opened for use by all threads. - */ -struct listen_port { - /** next in list */ - struct listen_port* next; - /** file descriptor, open and ready for use */ - int fd; - /** type of file descriptor, udp or tcp */ - enum listen_type ftype; - /** if the port should support PROXYv2 */ - int pp2_enabled; - /** fill in unbound_socket structure for every opened socket at - * Unbound startup */ - struct unbound_socket* socket; -}; - -/** - * Create shared listening ports - * Getaddrinfo, create socket, bind and listen to zero or more - * interfaces for IP4 and/or IP6, for UDP and/or TCP. - * On the given port number. It creates the sockets. - * @param cfg: settings on what ports to open. - * @param ifs: interfaces to open, array of IP addresses, "ip[@port]". - * @param num_ifs: length of ifs. - * @param reuseport: set to true if you want reuseport, or NULL to not have it, - * set to false on exit if reuseport failed to apply (because of no - * kernel support). - * @return: linked list of ports or NULL on error. - */ -struct listen_port* listening_ports_open(struct config_file* cfg, - char** ifs, int num_ifs, int* reuseport); - -/** - * Close and delete the (list of) listening ports. - */ -void listening_ports_free(struct listen_port* list); - -struct config_strlist; -/** - * Resolve interface names in config and store result IP addresses - * @param ifs: array of interfaces. The list of interface names, if not NULL. - * @param num_ifs: length of ifs array. - * @param list: if not NULL, this is used as the list of interface names. - * @param resif: string array (malloced array of malloced strings) with - * result. NULL if cfg has none. - * @param num_resif: length of resif. Zero if cfg has zero num_ifs. - * @return 0 on failure. - */ -int resolve_interface_names(char** ifs, int num_ifs, - struct config_strlist* list, char*** resif, int* num_resif); - -/** - * Create commpoints with for this thread for the shared ports. - * @param base: the comm_base that provides event functionality. - * for default all ifs. - * @param ports: the list of shared ports. - * @param bufsize: size of datagram buffer. - * @param tcp_accept_count: max number of simultaneous TCP connections - * from clients. - * @param tcp_idle_timeout: idle timeout for TCP connections in msec. - * @param harden_large_queries: whether query size should be limited. - * @param http_max_streams: maximum number of HTTP/2 streams per connection. - * @param http_endpoint: HTTP endpoint to service queries on - * @param http_notls: no TLS for http downstream - * @param tcp_conn_limit: TCP connection limit info. - * @param sslctx: nonNULL if ssl context. - * @param dtenv: nonNULL if dnstap enabled. - * @param cb: callback function when a request arrives. It is passed - * the packet and user argument. Return true to send a reply. - * @param cb_arg: user data argument for callback function. - * @return: the malloced listening structure, ready for use. NULL on error. - */ -struct listen_dnsport* -listen_create(struct comm_base* base, struct listen_port* ports, - size_t bufsize, int tcp_accept_count, int tcp_idle_timeout, - int harden_large_queries, uint32_t http_max_streams, - char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit, - void* sslctx, struct dt_env* dtenv, comm_point_callback_type* cb, - void *cb_arg); - -/** - * delete the listening structure - * @param listen: listening structure. - */ -void listen_delete(struct listen_dnsport* listen); - -/** setup the locks for the listen ports */ -void listen_setup_locks(void); -/** desetup the locks for the listen ports */ -void listen_desetup_locks(void); - -/** - * delete listen_list of commpoints. Calls commpointdelete() on items. - * This may close the fds or not depending on flags. - * @param list: to delete. - */ -void listen_list_delete(struct listen_list* list); - -/** - * get memory size used by the listening structs - * @param listen: listening structure. - * @return: size in bytes. - */ -size_t listen_get_mem(struct listen_dnsport* listen); - -/** - * stop accept handlers for TCP (until enabled again) - * @param listen: listening structure. - */ -void listen_stop_accept(struct listen_dnsport* listen); - -/** - * start accept handlers for TCP (was stopped before) - * @param listen: listening structure. - */ -void listen_start_accept(struct listen_dnsport* listen); - -/** - * Create and bind nonblocking UDP socket - * @param family: for socket call. - * @param socktype: for socket call. - * @param addr: for bind call. - * @param addrlen: for bind call. - * @param v6only: if enabled, IP6 sockets get IP6ONLY option set. - * if enabled with value 2 IP6ONLY option is disabled. - * @param inuse: on error, this is set true if the port was in use. - * @param noproto: on error, this is set true if cause is that the - IPv6 proto (family) is not available. - * @param rcv: set size on rcvbuf with socket option, if 0 it is not set. - * @param snd: set size on sndbuf with socket option, if 0 it is not set. - * @param listen: if true, this is a listening UDP port, eg port 53, and - * set SO_REUSEADDR on it. - * @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on - * listening UDP port. Set to false on return if it failed to do so. - * @param transparent: set IP_TRANSPARENT socket option. - * @param freebind: set IP_FREEBIND socket option. - * @param use_systemd: if true, fetch sockets from systemd. - * @param dscp: DSCP to use. - * @return: the socket. -1 on error. - */ -int create_udp_sock(int family, int socktype, struct sockaddr* addr, - socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv, - int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd, int dscp); - -/** - * Create and bind TCP listening socket - * @param addr: address info ready to make socket. - * @param v6only: enable ip6 only flag on ip6 sockets. - * @param noproto: if error caused by lack of protocol support. - * @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on - * listening UDP port. Set to false on return if it failed to do so. - * @param transparent: set IP_TRANSPARENT socket option. - * @param mss: maximum segment size of the socket. if zero, leaves the default. - * @param nodelay: if true set TCP_NODELAY and TCP_QUICKACK socket options. - * @param freebind: set IP_FREEBIND socket option. - * @param use_systemd: if true, fetch sockets from systemd. - * @param dscp: DSCP to use. - * @return: the socket. -1 on error. - */ -int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto, - int* reuseport, int transparent, int mss, int nodelay, int freebind, - int use_systemd, int dscp); - -/** - * Create and bind local listening socket - * @param path: path to the socket. - * @param noproto: on error, this is set true if cause is that local sockets - * are not supported. - * @param use_systemd: if true, fetch sockets from systemd. - * @return: the socket. -1 on error. - */ -int create_local_accept_sock(const char* path, int* noproto, int use_systemd); - -/** - * TCP request info. List of requests outstanding on the channel, that - * are asked for but not yet answered back. - */ -struct tcp_req_info { - /** the TCP comm point for this. Its buffer is used for read/write */ - struct comm_point* cp; - /** the buffer to use to spool reply from mesh into, - * it can then be copied to the result list and written. - * it is a pointer to the shared udp buffer. */ - struct sldns_buffer* spool_buffer; - /** are we in worker_handle function call (for recursion callback)*/ - int in_worker_handle; - /** is the comm point dropped (by worker handle). - * That means we have to disconnect the channel. */ - int is_drop; - /** is the comm point set to send_reply (by mesh new client in worker - * handle), if so answer is available in c.buffer */ - int is_reply; - /** read channel has closed, just write pending results */ - int read_is_closed; - /** read again */ - int read_again; - /** number of outstanding requests */ - int num_open_req; - /** list of outstanding requests */ - struct tcp_req_open_item* open_req_list; - /** number of pending writeable results */ - int num_done_req; - /** list of pending writable result packets, malloced one at a time */ - struct tcp_req_done_item* done_req_list; -}; - -/** - * List of open items in TCP channel - */ -struct tcp_req_open_item { - /** next in list */ - struct tcp_req_open_item* next; - /** the mesh area of the mesh_state */ - struct mesh_area* mesh; - /** the mesh state */ - struct mesh_state* mesh_state; -}; - -/** - * List of done items in TCP channel - */ -struct tcp_req_done_item { - /** next in list */ - struct tcp_req_done_item* next; - /** the buffer with packet contents */ - uint8_t* buf; - /** length of the buffer */ - size_t len; -}; - -/** - * Create tcp request info structure that keeps track of open - * requests on the TCP channel that are resolved at the same time, - * and the pending results that have to get written back to that client. - * @param spoolbuf: shared buffer - * @return new structure or NULL on alloc failure. - */ -struct tcp_req_info* tcp_req_info_create(struct sldns_buffer* spoolbuf); - -/** - * Delete tcp request structure. Called by owning commpoint. - * Removes mesh entry references and stored results from the lists. - * @param req: the tcp request info - */ -void tcp_req_info_delete(struct tcp_req_info* req); - -/** - * Clear tcp request structure. Removes list entries, sets it up ready - * for the next connection. - * @param req: tcp request info structure. - */ -void tcp_req_info_clear(struct tcp_req_info* req); - -/** - * Remove mesh state entry from list in tcp_req_info. - * caller has to manage the mesh state reply entry in the mesh state. - * @param req: the tcp req info that has the entry removed from the list. - * @param m: the state removed from the list. - */ -void tcp_req_info_remove_mesh_state(struct tcp_req_info* req, - struct mesh_state* m); - -/** - * Handle write done of the last result packet - * @param req: the tcp req info. - */ -void tcp_req_info_handle_writedone(struct tcp_req_info* req); - -/** - * Handle read done of a new request from the client - * @param req: the tcp req info. - */ -void tcp_req_info_handle_readdone(struct tcp_req_info* req); - -/** - * Add mesh state to the tcp req list of open requests. - * So the comm_reply can be removed off the mesh reply list when - * the tcp channel has to be closed (for other reasons then that that - * request was done, eg. channel closed by client or some format error). - * @param req: tcp req info structure. It keeps track of the simultaneous - * requests and results on a tcp (or TLS) channel. - * @param mesh: mesh area for the state. - * @param m: mesh state to add. - * @return 0 on failure (malloc failure). - */ -int tcp_req_info_add_meshstate(struct tcp_req_info* req, - struct mesh_area* mesh, struct mesh_state* m); - -/** - * Send reply on tcp simultaneous answer channel. May queue it up. - * @param req: request info structure. - */ -void tcp_req_info_send_reply(struct tcp_req_info* req); - -/** the read channel has closed - * @param req: request. remaining queries are looked up and answered. - * @return zero if nothing to do, just close the tcp. - */ -int tcp_req_info_handle_read_close(struct tcp_req_info* req); - -/** get the size of currently used tcp stream wait buffers (in bytes) */ -size_t tcp_req_info_get_stream_buffer_size(void); - -/** get the size of currently used HTTP2 query buffers (in bytes) */ -size_t http2_get_query_buffer_size(void); -/** get the size of currently used HTTP2 response buffers (in bytes) */ -size_t http2_get_response_buffer_size(void); - -#ifdef HAVE_NGHTTP2 -/** - * Create nghttp2 callbacks to handle HTTP2 requests. - * @return malloc'ed struct, NULL on failure - */ -nghttp2_session_callbacks* http2_req_callbacks_create(void); - -/** Free http2 stream buffers and decrease buffer counters */ -void http2_req_stream_clear(struct http2_stream* h2_stream); - -/** - * DNS response ready to be submitted to nghttp2, to be prepared for sending - * out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer - * might be used before this will be send out. - * @param h2_session: http2 session, containing c->buffer which contains answer - * @param h2_stream: http2 stream, containing buffer to store answer in - * @return 0 on error, 1 otherwise - */ -int http2_submit_dns_response(struct http2_session* h2_session); -#else -int http2_submit_dns_response(void* v); -#endif /* HAVE_NGHTTP2 */ - -char* set_ip_dscp(int socket, int addrfamily, int ds); - -/** for debug and profiling purposes only - * @param ub_sock: the structure containing created socket info we want to print or log for - */ -void verbose_print_unbound_socket(struct unbound_socket* ub_sock); - -#endif /* LISTEN_DNSPORT_H */ diff --git a/crates/libunbound-sys/unbound/services/localzone.c b/crates/libunbound-sys/unbound/services/localzone.c deleted file mode 100644 index 44da22d7..00000000 --- a/crates/libunbound-sys/unbound/services/localzone.c +++ /dev/null @@ -1,2201 +0,0 @@ -/* - * services/localzone.c - local zones authority service. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable local zone authority service. - */ -#include "config.h" -#include "services/localzone.h" -#include "sldns/str2wire.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "util/data/dname.h" -#include "util/data/packed_rrset.h" -#include "util/data/msgencode.h" -#include "util/net_help.h" -#include "util/netevent.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -#include "util/as112.h" - -/* maximum RRs in an RRset, to cap possible 'endless' list RRs. - * with 16 bytes for an A record, a 64K packet has about 4000 max */ -#define LOCALZONE_RRSET_COUNT_MAX 4096 - -/** print all RRsets in local zone */ -static void -local_zone_out(struct local_zone* z) -{ - struct local_data* d; - struct local_rrset* p; - RBTREE_FOR(d, struct local_data*, &z->data) { - for(p = d->rrsets; p; p = p->next) { - log_nametypeclass(NO_VERBOSE, "rrset", d->name, - ntohs(p->rrset->rk.type), - ntohs(p->rrset->rk.rrset_class)); - } - } -} - -static void -local_zone_print(struct local_zone* z) -{ - char buf[64]; - lock_rw_rdlock(&z->lock); - snprintf(buf, sizeof(buf), "%s zone", - local_zone_type2str(z->type)); - log_nametypeclass(NO_VERBOSE, buf, z->name, 0, z->dclass); - local_zone_out(z); - lock_rw_unlock(&z->lock); -} - -void local_zones_print(struct local_zones* zones) -{ - struct local_zone* z; - lock_rw_rdlock(&zones->lock); - log_info("number of auth zones %u", (unsigned)zones->ztree.count); - RBTREE_FOR(z, struct local_zone*, &zones->ztree) { - local_zone_print(z); - } - lock_rw_unlock(&zones->lock); -} - -struct local_zones* -local_zones_create(void) -{ - struct local_zones* zones = (struct local_zones*)calloc(1, - sizeof(*zones)); - if(!zones) - return NULL; - rbtree_init(&zones->ztree, &local_zone_cmp); - lock_rw_init(&zones->lock); - lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree)); - /* also lock protects the rbnode's in struct local_zone */ - return zones; -} - -/** helper traverse to delete zones */ -static void -lzdel(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct local_zone* z = (struct local_zone*)n->key; - local_zone_delete(z); -} - -void -local_zones_delete(struct local_zones* zones) -{ - if(!zones) - return; - lock_rw_destroy(&zones->lock); - /* walk through zones and delete them all */ - traverse_postorder(&zones->ztree, lzdel, NULL); - free(zones); -} - -void -local_zone_delete(struct local_zone* z) -{ - if(!z) - return; - lock_rw_destroy(&z->lock); - regional_destroy(z->region); - free(z->name); - free(z->taglist); - free(z); -} - -int -local_zone_cmp(const void* z1, const void* z2) -{ - /* first sort on class, so that hierarchy can be maintained within - * a class */ - struct local_zone* a = (struct local_zone*)z1; - struct local_zone* b = (struct local_zone*)z2; - int m; - if(a->dclass != b->dclass) { - if(a->dclass < b->dclass) - return -1; - return 1; - } - return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m); -} - -int -local_data_cmp(const void* d1, const void* d2) -{ - struct local_data* a = (struct local_data*)d1; - struct local_data* b = (struct local_data*)d2; - int m; - return dname_canon_lab_cmp(a->name, a->namelabs, b->name, - b->namelabs, &m); -} - -/* form wireformat from text format domain name */ -int -parse_dname(const char* str, uint8_t** res, size_t* len, int* labs) -{ - *res = sldns_str2wire_dname(str, len); - *labs = 0; - if(!*res) { - log_err("cannot parse name %s", str); - return 0; - } - *labs = dname_count_size_labels(*res, len); - return 1; -} - -/** create a new localzone */ -static struct local_zone* -local_zone_create(uint8_t* nm, size_t len, int labs, - enum localzone_type t, uint16_t dclass) -{ - struct local_zone* z = (struct local_zone*)calloc(1, sizeof(*z)); - if(!z) { - return NULL; - } - z->node.key = z; - z->dclass = dclass; - z->type = t; - z->name = nm; - z->namelen = len; - z->namelabs = labs; - lock_rw_init(&z->lock); - z->region = regional_create_nochunk(sizeof(struct regional)); - if(!z->region) { - free(z); - return NULL; - } - rbtree_init(&z->data, &local_data_cmp); - lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_type)); - /* also the zones->lock protects node, parent, name*, class */ - return z; -} - -/** enter a new zone with allocated dname returns with WRlock */ -static struct local_zone* -lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len, - int labs, enum localzone_type t, uint16_t c) -{ - struct local_zone* z = local_zone_create(nm, len, labs, t, c); - if(!z) { - free(nm); - log_err("out of memory"); - return NULL; - } - - /* add to rbtree */ - lock_rw_wrlock(&zones->lock); - lock_rw_wrlock(&z->lock); - if(!rbtree_insert(&zones->ztree, &z->node)) { - struct local_zone* oldz; - char str[256]; - dname_str(nm, str); - log_warn("duplicate local-zone %s", str); - lock_rw_unlock(&z->lock); - /* save zone name locally before deallocation, - * otherwise, nm is gone if we zone_delete now. */ - oldz = z; - /* find the correct zone, so not an error for duplicate */ - z = local_zones_find(zones, nm, len, labs, c); - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - local_zone_delete(oldz); - return z; - } - lock_rw_unlock(&zones->lock); - return z; -} - -/** enter a new zone */ -static struct local_zone* -lz_enter_zone(struct local_zones* zones, const char* name, const char* type, - uint16_t dclass) -{ - struct local_zone* z; - enum localzone_type t; - uint8_t* nm; - size_t len; - int labs; - if(!parse_dname(name, &nm, &len, &labs)) { - log_err("bad zone name %s %s", name, type); - return NULL; - } - if(!local_zone_str2type(type, &t)) { - log_err("bad lz_enter_zone type %s %s", name, type); - free(nm); - return NULL; - } - if(!(z=lz_enter_zone_dname(zones, nm, len, labs, t, dclass))) { - log_err("could not enter zone %s %s", name, type); - return NULL; - } - return z; -} - -int -rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type, - uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len, - uint8_t** rdata, size_t* rdata_len) -{ - size_t dname_len = 0; - int e = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600, - NULL, 0, NULL, 0); - if(e) { - log_err("error parsing local-data at %d: '%s': %s", - LDNS_WIREPARSE_OFFSET(e), str, - sldns_get_errorstr_parse(e)); - return 0; - } - *nm = memdup(rr, dname_len); - if(!*nm) { - log_err("out of memory"); - return 0; - } - *dclass = sldns_wirerr_get_class(rr, len, dname_len); - *type = sldns_wirerr_get_type(rr, len, dname_len); - *ttl = (time_t)sldns_wirerr_get_ttl(rr, len, dname_len); - *rdata = sldns_wirerr_get_rdatawl(rr, len, dname_len); - *rdata_len = sldns_wirerr_get_rdatalen(rr, len, dname_len)+2; - return 1; -} - -/** return name and class of rr; parses string */ -static int -get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass, - uint16_t* dtype) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t len = sizeof(rr), dname_len = 0; - int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600, - NULL, 0, NULL, 0); - if(s != 0) { - log_err("error parsing local-data at %d '%s': %s", - LDNS_WIREPARSE_OFFSET(s), str, - sldns_get_errorstr_parse(s)); - return 0; - } - *nm = memdup(rr, dname_len); - *dclass = sldns_wirerr_get_class(rr, len, dname_len); - *dtype = sldns_wirerr_get_type(rr, len, dname_len); - if(!*nm) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** - * Find an rrset in local data structure. - * @param data: local data domain name structure. - * @param type: type to look for (host order). - * @param alias_ok: 1 if matching a non-exact, alias type such as CNAME is - * allowed. otherwise 0. - * @return rrset pointer or NULL if not found. - */ -static struct local_rrset* -local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) -{ - struct local_rrset* p; - type = htons(type); - for(p = data->rrsets; p; p = p->next) { - if(p->rrset->rk.type == type) - return p; - if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) - return p; - } - return NULL; -} - -/** check for RR duplicates */ -static int -rr_is_duplicate(struct packed_rrset_data* pd, uint8_t* rdata, size_t rdata_len) -{ - size_t i; - for(i=0; icount; i++) { - if(pd->rr_len[i] == rdata_len && - memcmp(pd->rr_data[i], rdata, rdata_len) == 0) - return 1; - } - return 0; -} - -/** new local_rrset */ -static struct local_rrset* -new_local_rrset(struct regional* region, struct local_data* node, - uint16_t rrtype, uint16_t rrclass) -{ - struct packed_rrset_data* pd; - struct local_rrset* rrset = (struct local_rrset*) - regional_alloc_zero(region, sizeof(*rrset)); - if(!rrset) { - log_err("out of memory"); - return NULL; - } - rrset->next = node->rrsets; - node->rrsets = rrset; - rrset->rrset = (struct ub_packed_rrset_key*) - regional_alloc_zero(region, sizeof(*rrset->rrset)); - if(!rrset->rrset) { - log_err("out of memory"); - return NULL; - } - rrset->rrset->entry.key = rrset->rrset; - pd = (struct packed_rrset_data*)regional_alloc_zero(region, - sizeof(*pd)); - if(!pd) { - log_err("out of memory"); - return NULL; - } - pd->trust = rrset_trust_prim_noglue; - pd->security = sec_status_insecure; - rrset->rrset->entry.data = pd; - rrset->rrset->rk.dname = node->name; - rrset->rrset->rk.dname_len = node->namelen; - rrset->rrset->rk.type = htons(rrtype); - rrset->rrset->rk.rrset_class = htons(rrclass); - return rrset; -} - -/** insert RR into RRset data structure; Wastes a couple of bytes */ -int -rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd, - uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr) -{ - size_t* oldlen = pd->rr_len; - time_t* oldttl = pd->rr_ttl; - uint8_t** olddata = pd->rr_data; - - /* add RR to rrset */ - if(pd->count > LOCALZONE_RRSET_COUNT_MAX) { - log_warn("RRset '%s' has more than %d records, record ignored", - rrstr, LOCALZONE_RRSET_COUNT_MAX); - return 1; - } - pd->count++; - pd->rr_len = regional_alloc(region, sizeof(*pd->rr_len)*pd->count); - pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count); - pd->rr_data = regional_alloc(region, sizeof(*pd->rr_data)*pd->count); - if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) { - log_err("out of memory"); - return 0; - } - if(pd->count > 1) { - memcpy(pd->rr_len+1, oldlen, - sizeof(*pd->rr_len)*(pd->count-1)); - memcpy(pd->rr_ttl+1, oldttl, - sizeof(*pd->rr_ttl)*(pd->count-1)); - memcpy(pd->rr_data+1, olddata, - sizeof(*pd->rr_data)*(pd->count-1)); - } - pd->rr_len[0] = rdata_len; - pd->rr_ttl[0] = ttl; - pd->rr_data[0] = regional_alloc_init(region, rdata, rdata_len); - if(!pd->rr_data[0]) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** Delete RR from local-zone RRset, wastes memory as the deleted RRs cannot be - * free'd (regionally alloc'd) */ -int -local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index) -{ - log_assert(pd->count > 0); - if(index >= pd->count) { - log_warn("Trying to remove RR with out of bound index"); - return 0; - } - if(index + 1 < pd->count) { - /* not removing last element */ - size_t nexti = index + 1; - size_t num = pd->count - nexti; - memmove(pd->rr_len+index, pd->rr_len+nexti, sizeof(*pd->rr_len)*num); - memmove(pd->rr_ttl+index, pd->rr_ttl+nexti, sizeof(*pd->rr_ttl)*num); - memmove(pd->rr_data+index, pd->rr_data+nexti, sizeof(*pd->rr_data)*num); - } - pd->count--; - return 1; -} - -struct local_data* -local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs) -{ - struct local_data key; - key.node.key = &key; - key.name = nm; - key.namelen = nmlen; - key.namelabs = nmlabs; - return (struct local_data*)rbtree_search(&z->data, &key.node); -} - -/** find a node, create it if not and all its empty nonterminal parents */ -static int -lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, - int nmlabs, struct local_data** res) -{ - struct local_data* ld = local_zone_find_data(z, nm, nmlen, nmlabs); - if(!ld) { - /* create a domain name to store rr. */ - ld = (struct local_data*)regional_alloc_zero(z->region, - sizeof(*ld)); - if(!ld) { - log_err("out of memory adding local data"); - return 0; - } - ld->node.key = ld; - ld->name = regional_alloc_init(z->region, nm, nmlen); - if(!ld->name) { - log_err("out of memory"); - return 0; - } - ld->namelen = nmlen; - ld->namelabs = nmlabs; - if(!rbtree_insert(&z->data, &ld->node)) { - log_assert(0); /* duplicate name */ - } - /* see if empty nonterminals need to be created */ - if(nmlabs > z->namelabs) { - dname_remove_label(&nm, &nmlen); - if(!lz_find_create_node(z, nm, nmlen, nmlabs-1, res)) - return 0; - } - } - *res = ld; - return 1; -} - -/* Mark the SOA record for the zone. This only marks the SOA rrset; the data - * for the RR is entered later on local_zone_enter_rr() as with the other - * records. An artificial soa_negative record with a modified TTL (minimum of - * the TTL and the SOA.MINIMUM) is also created and marked for usage with - * negative answers and to avoid allocations during those answers. */ -static int -lz_mark_soa_for_zone(struct local_zone* z, struct ub_packed_rrset_key* soa_rrset, - uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr) -{ - struct packed_rrset_data* pd = (struct packed_rrset_data*) - regional_alloc_zero(z->region, sizeof(*pd)); - struct ub_packed_rrset_key* rrset_negative = (struct ub_packed_rrset_key*) - regional_alloc_zero(z->region, sizeof(*rrset_negative)); - time_t minimum; - if(!rrset_negative||!pd) { - log_err("out of memory"); - return 0; - } - /* Mark the original SOA record and then continue with the negative one. */ - z->soa = soa_rrset; - rrset_negative->entry.key = rrset_negative; - pd->trust = rrset_trust_prim_noglue; - pd->security = sec_status_insecure; - rrset_negative->entry.data = pd; - rrset_negative->rk.dname = soa_rrset->rk.dname; - rrset_negative->rk.dname_len = soa_rrset->rk.dname_len; - rrset_negative->rk.type = soa_rrset->rk.type; - rrset_negative->rk.rrset_class = soa_rrset->rk.rrset_class; - if(!rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr)) - return 0; - /* last 4 bytes are minimum ttl in network format */ - if(pd->count == 0 || pd->rr_len[0] < 2+4) - return 0; - minimum = (time_t)sldns_read_uint32(pd->rr_data[0]+(pd->rr_len[0]-4)); - minimum = ttlttl = minimum; - pd->rr_ttl[0] = minimum; - - z->soa_negative = rrset_negative; - return 1; -} - -int -local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen, - int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl, - uint8_t* rdata, size_t rdata_len, const char* rrstr) -{ - struct local_data* node; - struct local_rrset* rrset; - struct packed_rrset_data* pd; - - if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) { - return 0; - } - log_assert(node); - - /* Reject it if we would end up having CNAME and other data (including - * another CNAME) for a redirect zone. */ - if((z->type == local_zone_redirect || - z->type == local_zone_inform_redirect) && node->rrsets) { - const char* othertype = NULL; - if (rrtype == LDNS_RR_TYPE_CNAME) - othertype = "other"; - else if (node->rrsets->rrset->rk.type == - htons(LDNS_RR_TYPE_CNAME)) { - othertype = "CNAME"; - } - if(othertype) { - log_err("local-data '%s' in redirect zone must not " - "coexist with %s local-data", rrstr, othertype); - return 0; - } - } - rrset = local_data_find_type(node, rrtype, 0); - if(!rrset) { - rrset = new_local_rrset(z->region, node, rrtype, rrclass); - if(!rrset) - return 0; - if(query_dname_compare(node->name, z->name) == 0) { - if(rrtype == LDNS_RR_TYPE_NSEC) - rrset->rrset->rk.flags = PACKED_RRSET_NSEC_AT_APEX; - if(rrtype == LDNS_RR_TYPE_SOA && - !lz_mark_soa_for_zone(z, rrset->rrset, rdata, rdata_len, ttl, - rrstr)) - return 0; - } - } - pd = (struct packed_rrset_data*)rrset->rrset->entry.data; - log_assert(rrset && pd); - - /* check for duplicate RR */ - if(rr_is_duplicate(pd, rdata, rdata_len)) { - verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr); - return 1; - } - return rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr); -} - -/** enter data RR into auth zone */ -static int -lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr) -{ - uint8_t* nm; - size_t nmlen; - int nmlabs, ret; - uint16_t rrtype = 0, rrclass = 0; - time_t ttl = 0; - uint8_t rr[LDNS_RR_BUF_SIZE]; - uint8_t* rdata; - size_t rdata_len; - if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr, - sizeof(rr), &rdata, &rdata_len)) { - log_err("bad local-data: %s", rrstr); - return 0; - } - log_assert(z->dclass == rrclass); - if((z->type == local_zone_redirect || - z->type == local_zone_inform_redirect) && - query_dname_compare(z->name, nm) != 0) { - log_err("local-data in redirect zone must reside at top of zone" - ", not at %s", rrstr); - free(nm); - return 0; - } - nmlabs = dname_count_size_labels(nm, &nmlen); - ret = local_zone_enter_rr(z, nm, nmlen, nmlabs, rrtype, rrclass, ttl, - rdata, rdata_len, rrstr); - free(nm); - return ret; -} - -/** enter a data RR into auth data; a zone for it must exist */ -static int -lz_enter_rr_str(struct local_zones* zones, const char* rr) -{ - uint8_t* rr_name; - uint16_t rr_class, rr_type; - size_t len; - int labs; - struct local_zone* z; - int r; - if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) { - log_err("bad rr %s", rr); - return 0; - } - labs = dname_count_size_labels(rr_name, &len); - lock_rw_rdlock(&zones->lock); - z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type); - if(!z) { - lock_rw_unlock(&zones->lock); - fatal_exit("internal error: no zone for rr %s", rr); - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - free(rr_name); - r = lz_enter_rr_into_zone(z, rr); - lock_rw_unlock(&z->lock); - return r; -} - -/** enter tagstring into zone */ -static int -lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list, - size_t len, uint16_t rr_class) -{ - uint8_t dname[LDNS_MAX_DOMAINLEN+1]; - size_t dname_len = sizeof(dname); - int dname_labs, r = 0; - struct local_zone* z; - - if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) { - log_err("cannot parse zone name in local-zone-tag: %s", zname); - return 0; - } - dname_labs = dname_count_labels(dname); - - lock_rw_rdlock(&zones->lock); - z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class); - if(!z) { - lock_rw_unlock(&zones->lock); - log_err("no local-zone for tag %s", zname); - return 0; - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - free(z->taglist); - z->taglist = memdup(list, len); - z->taglen = len; - if(z->taglist) - r = 1; - lock_rw_unlock(&z->lock); - return r; -} - -/** enter override into zone */ -static int -lz_enter_override(struct local_zones* zones, char* zname, char* netblock, - char* type, uint16_t rr_class) -{ - uint8_t dname[LDNS_MAX_DOMAINLEN+1]; - size_t dname_len = sizeof(dname); - int dname_labs; - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - struct local_zone* z; - enum localzone_type t; - - /* parse zone name */ - if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) { - log_err("cannot parse zone name in local-zone-override: %s %s", - zname, netblock); - return 0; - } - dname_labs = dname_count_labels(dname); - - /* parse netblock */ - if(!netblockstrtoaddr(netblock, UNBOUND_DNS_PORT, &addr, &addrlen, - &net)) { - log_err("cannot parse netblock in local-zone-override: %s %s", - zname, netblock); - return 0; - } - - /* parse zone type */ - if(!local_zone_str2type(type, &t)) { - log_err("cannot parse type in local-zone-override: %s %s %s", - zname, netblock, type); - return 0; - } - - /* find localzone entry */ - lock_rw_rdlock(&zones->lock); - z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class); - if(!z) { - lock_rw_unlock(&zones->lock); - log_err("no local-zone for local-zone-override %s", zname); - return 0; - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - - /* create netblock addr_tree if not present yet */ - if(!z->override_tree) { - z->override_tree = (struct rbtree_type*)regional_alloc_zero( - z->region, sizeof(*z->override_tree)); - if(!z->override_tree) { - lock_rw_unlock(&z->lock); - log_err("out of memory"); - return 0; - } - addr_tree_init(z->override_tree); - } - /* add new elem to tree */ - if(z->override_tree) { - struct local_zone_override* n; - n = (struct local_zone_override*)regional_alloc_zero( - z->region, sizeof(*n)); - if(!n) { - lock_rw_unlock(&z->lock); - log_err("out of memory"); - return 0; - } - n->type = t; - if(!addr_tree_insert(z->override_tree, - (struct addr_tree_node*)n, &addr, addrlen, net)) { - lock_rw_unlock(&z->lock); - log_err("duplicate local-zone-override %s %s", - zname, netblock); - return 1; - } - } - - lock_rw_unlock(&z->lock); - return 1; -} - -/** parse local-zone: statements */ -static int -lz_enter_zones(struct local_zones* zones, struct config_file* cfg) -{ - struct config_str2list* p; -#ifndef THREADS_DISABLED - struct local_zone* z; -#endif - for(p = cfg->local_zones; p; p = p->next) { - if(!( -#ifndef THREADS_DISABLED - z= -#endif - lz_enter_zone(zones, p->str, p->str2, - LDNS_RR_CLASS_IN))) - return 0; - lock_rw_unlock(&z->lock); - } - return 1; -} - -/** lookup a zone in rbtree; exact match only; SLOW due to parse */ -static int -lz_exists(struct local_zones* zones, const char* name) -{ - struct local_zone z; - z.node.key = &z; - z.dclass = LDNS_RR_CLASS_IN; - if(!parse_dname(name, &z.name, &z.namelen, &z.namelabs)) { - log_err("bad name %s", name); - return 0; - } - lock_rw_rdlock(&zones->lock); - if(rbtree_search(&zones->ztree, &z.node)) { - lock_rw_unlock(&zones->lock); - free(z.name); - return 1; - } - lock_rw_unlock(&zones->lock); - free(z.name); - return 0; -} - -/** lookup a zone in cfg->nodefault list */ -static int -lz_nodefault(struct config_file* cfg, const char* name) -{ - struct config_strlist* p; - size_t len = strlen(name); - if(len == 0) return 0; - if(name[len-1] == '.') len--; - - for(p = cfg->local_zones_nodefault; p; p = p->next) { - /* compare zone name, lowercase, compare without ending . */ - if(strncasecmp(p->str, name, len) == 0 && - (strlen(p->str) == len || (strlen(p->str)==len+1 && - p->str[len] == '.'))) - return 1; - } - return 0; -} - -/** enter (AS112) empty default zone */ -static int -add_empty_default(struct local_zones* zones, struct config_file* cfg, - const char* name) -{ - struct local_zone* z; - char str[1024]; /* known long enough */ - if(lz_exists(zones, name) || lz_nodefault(cfg, name)) - return 1; /* do not enter default content */ - if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN))) - return 0; - snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. " - "nobody.invalid. 1 3600 1200 604800 10800", name); - if(!lz_enter_rr_into_zone(z, str)) { - lock_rw_unlock(&z->lock); - return 0; - } - snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name); - if(!lz_enter_rr_into_zone(z, str)) { - lock_rw_unlock(&z->lock); - return 0; - } - lock_rw_unlock(&z->lock); - return 1; -} - -/** enter default zones */ -int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg) -{ - struct local_zone* z; - const char** zstr; - - /* Do not add any default */ - if(cfg->local_zones_disable_default) - return 1; - - /* this list of zones is from RFC 6303 and RFC 7686 */ - - /* block localhost level zones first, then onion and later the LAN zones */ - - /* localhost. zone */ - if(!lz_exists(zones, "localhost.") && - !lz_nodefault(cfg, "localhost.")) { - if(!(z=lz_enter_zone(zones, "localhost.", "redirect", - LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, - "localhost. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, - "localhost. 10800 IN SOA localhost. nobody.invalid. " - "1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, - "localhost. 10800 IN A 127.0.0.1") || - !lz_enter_rr_into_zone(z, - "localhost. 10800 IN AAAA ::1")) { - log_err("out of memory adding default zone"); - if(z) { lock_rw_unlock(&z->lock); } - return 0; - } - lock_rw_unlock(&z->lock); - } - /* reverse ip4 zone */ - if(!lz_exists(zones, "127.in-addr.arpa.") && - !lz_nodefault(cfg, "127.in-addr.arpa.")) { - if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static", - LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, - "127.in-addr.arpa. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, - "127.in-addr.arpa. 10800 IN SOA localhost. " - "nobody.invalid. 1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, - "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) { - log_err("out of memory adding default zone"); - if(z) { lock_rw_unlock(&z->lock); } - return 0; - } - lock_rw_unlock(&z->lock); - } - /* reverse ip6 zone */ - if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") && - !lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) { - if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static", - LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, - "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, - "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. " - "nobody.invalid. 1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, - "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) { - log_err("out of memory adding default zone"); - if(z) { lock_rw_unlock(&z->lock); } - return 0; - } - lock_rw_unlock(&z->lock); - } - /* home.arpa. zone (RFC 8375) */ - if(!add_empty_default(zones, cfg, "home.arpa.")) { - log_err("out of memory adding default zone"); - return 0; - } - /* onion. zone (RFC 7686) */ - if(!add_empty_default(zones, cfg, "onion.")) { - log_err("out of memory adding default zone"); - return 0; - } - /* test. zone (RFC 6761) */ - if(!add_empty_default(zones, cfg, "test.")) { - log_err("out of memory adding default zone"); - return 0; - } - /* invalid. zone (RFC 6761) */ - if(!add_empty_default(zones, cfg, "invalid.")) { - log_err("out of memory adding default zone"); - return 0; - } - /* block AS112 zones, unless asked not to */ - if(!cfg->unblock_lan_zones) { - for(zstr = as112_zones; *zstr; zstr++) { - if(!add_empty_default(zones, cfg, *zstr)) { - log_err("out of memory adding default zone"); - return 0; - } - } - } - return 1; -} - -/** parse local-zone-override: statements */ -static int -lz_enter_overrides(struct local_zones* zones, struct config_file* cfg) -{ - struct config_str3list* p; - for(p = cfg->local_zone_overrides; p; p = p->next) { - if(!lz_enter_override(zones, p->str, p->str2, p->str3, - LDNS_RR_CLASS_IN)) - return 0; - } - return 1; -} - -/** setup parent pointers, so that a lookup can be done for closest match */ -static void -init_parents(struct local_zones* zones) -{ - struct local_zone* node, *prev = NULL, *p; - int m; - lock_rw_wrlock(&zones->lock); - RBTREE_FOR(node, struct local_zone*, &zones->ztree) { - lock_rw_wrlock(&node->lock); - node->parent = NULL; - if(!prev || prev->dclass != node->dclass) { - prev = node; - lock_rw_unlock(&node->lock); - continue; - } - (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, - node->namelabs, &m); /* we know prev is smaller */ - /* sort order like: . com. bla.com. zwb.com. net. */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - /* looking for name with few labels, a parent */ - if(p->namelabs <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - - if(node->override_tree) - addr_tree_init_parents(node->override_tree); - lock_rw_unlock(&node->lock); - } - lock_rw_unlock(&zones->lock); -} - -/** enter implicit transparent zone for local-data: without local-zone: */ -static int -lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) -{ - /* walk over all items that have no parent zone and find - * the name that covers them all (could be the root) and - * add that as a transparent zone */ - struct config_strlist* p; - int have_name = 0; - int have_other_classes = 0; - uint16_t dclass = 0; - uint8_t* nm = 0; - size_t nmlen = 0; - int nmlabs = 0; - int match = 0; /* number of labels match count */ - - init_parents(zones); /* to enable local_zones_lookup() */ - for(p = cfg->local_data; p; p = p->next) { - uint8_t* rr_name; - uint16_t rr_class, rr_type; - size_t len; - int labs; - if(!get_rr_nameclass(p->str, &rr_name, &rr_class, &rr_type)) { - log_err("Bad local-data RR %s", p->str); - return 0; - } - labs = dname_count_size_labels(rr_name, &len); - lock_rw_rdlock(&zones->lock); - if(!local_zones_lookup(zones, rr_name, len, labs, rr_class, - rr_type)) { - /* Check if there is a zone that this could go - * under but for different class; created zones are - * always for LDNS_RR_CLASS_IN. Create the zone with - * a different class but the same configured - * local_zone_type. */ - struct local_zone* z = local_zones_lookup(zones, - rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type); - if(z) { - uint8_t* name = memdup(z->name, z->namelen); - size_t znamelen = z->namelen; - int znamelabs = z->namelabs; - enum localzone_type ztype = z->type; - lock_rw_unlock(&zones->lock); - if(!name) { - log_err("out of memory"); - free(rr_name); - return 0; - } - if(!( -#ifndef THREADS_DISABLED - z = -#endif - lz_enter_zone_dname(zones, name, - znamelen, znamelabs, - ztype, rr_class))) { - free(rr_name); - return 0; - } - lock_rw_unlock(&z->lock); - free(rr_name); - continue; - } - if(!have_name) { - dclass = rr_class; - nm = rr_name; - nmlen = len; - nmlabs = labs; - match = labs; - have_name = 1; - } else { - int m; - if(rr_class != dclass) { - /* process other classes later */ - free(rr_name); - have_other_classes = 1; - lock_rw_unlock(&zones->lock); - continue; - } - /* find smallest shared topdomain */ - (void)dname_lab_cmp(nm, nmlabs, - rr_name, labs, &m); - free(rr_name); - if(m < match) - match = m; - } - } else free(rr_name); - lock_rw_unlock(&zones->lock); - } - if(have_name) { - uint8_t* n2; -#ifndef THREADS_DISABLED - struct local_zone* z; -#endif - /* allocate zone of smallest shared topdomain to contain em */ - n2 = nm; - dname_remove_labels(&n2, &nmlen, nmlabs - match); - n2 = memdup(n2, nmlen); - free(nm); - if(!n2) { - log_err("out of memory"); - return 0; - } - log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", - n2, 0, dclass); - if(!( -#ifndef THREADS_DISABLED - z= -#endif - lz_enter_zone_dname(zones, n2, nmlen, match, - local_zone_transparent, dclass))) { - return 0; - } - lock_rw_unlock(&z->lock); - } - if(have_other_classes) { - /* restart to setup other class */ - return lz_setup_implicit(zones, cfg); - } - return 1; -} - -/** enter local-zone-tag info */ -static int -lz_enter_zone_tags(struct local_zones* zones, struct config_file* cfg) -{ - struct config_strbytelist* p; - int c = 0; - for(p = cfg->local_zone_tags; p; p = p->next) { - if(!lz_enter_zone_tag(zones, p->str, p->str2, p->str2len, - LDNS_RR_CLASS_IN)) - return 0; - c++; - } - if(c) verbose(VERB_ALGO, "applied tags to %d local zones", c); - return 1; -} - -/** enter auth data */ -static int -lz_enter_data(struct local_zones* zones, struct config_file* cfg) -{ - struct config_strlist* p; - for(p = cfg->local_data; p; p = p->next) { - if(!lz_enter_rr_str(zones, p->str)) - return 0; - } - return 1; -} - -/** free memory from config */ -static void -lz_freeup_cfg(struct config_file* cfg) -{ - config_deldblstrlist(cfg->local_zones); - cfg->local_zones = NULL; - config_delstrlist(cfg->local_zones_nodefault); - cfg->local_zones_nodefault = NULL; - config_delstrlist(cfg->local_data); - cfg->local_data = NULL; -} - -int -local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg) -{ - /* create zones from zone statements. */ - if(!lz_enter_zones(zones, cfg)) { - return 0; - } - /* apply default zones+content (unless disabled, or overridden) */ - if(!local_zone_enter_defaults(zones, cfg)) { - return 0; - } - /* enter local zone overrides */ - if(!lz_enter_overrides(zones, cfg)) { - return 0; - } - /* create implicit transparent zone from data. */ - if(!lz_setup_implicit(zones, cfg)) { - return 0; - } - - /* setup parent ptrs for lookup during data entry */ - init_parents(zones); - /* insert local zone tags */ - if(!lz_enter_zone_tags(zones, cfg)) { - return 0; - } - /* insert local data */ - if(!lz_enter_data(zones, cfg)) { - return 0; - } - /* freeup memory from cfg struct. */ - lz_freeup_cfg(cfg); - return 1; -} - -struct local_zone* -local_zones_lookup(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype) -{ - return local_zones_tags_lookup(zones, name, len, labs, - dclass, dtype, NULL, 0, 1); -} - -struct local_zone* -local_zones_tags_lookup(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype, - uint8_t* taglist, size_t taglen, int ignoretags) -{ - rbnode_type* res = NULL; - struct local_zone *result; - struct local_zone key; - int m; - /* for type DS use a zone higher when on a zonecut */ - if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) { - dname_remove_label(&name, &len); - labs--; - } - key.node.key = &key; - key.dclass = dclass; - key.name = name; - key.namelen = len; - key.namelabs = labs; - rbtree_find_less_equal(&zones->ztree, &key, &res); - result = (struct local_zone*)res; - /* exact or smaller element (or no element) */ - if(!result || result->dclass != dclass) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->namelabs, key.name, - key.namelabs, &m); - while(result) { /* go up until qname is zone or subdomain of zone */ - if(result->namelabs <= m) - if(ignoretags || !result->taglist || - taglist_intersect(result->taglist, - result->taglen, taglist, taglen)) - break; - result = result->parent; - } - return result; -} - -struct local_zone* -local_zones_find(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass) -{ - struct local_zone key; - key.node.key = &key; - key.dclass = dclass; - key.name = name; - key.namelen = len; - key.namelabs = labs; - /* exact */ - return (struct local_zone*)rbtree_search(&zones->ztree, &key); -} - -struct local_zone* -local_zones_find_le(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, - int* exact) -{ - struct local_zone key; - rbnode_type *node; - key.node.key = &key; - key.dclass = dclass; - key.name = name; - key.namelen = len; - key.namelabs = labs; - *exact = rbtree_find_less_equal(&zones->ztree, &key, &node); - return (struct local_zone*)node; -} - -/** encode answer consisting of 1 rrset */ -static int -local_encode(struct query_info* qinfo, struct module_env* env, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec, - int rcode) -{ - struct reply_info rep; - uint16_t udpsize; - /* make answer with time=0 for fixed TTL values */ - memset(&rep, 0, sizeof(rep)); - rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode); - rep.qdcount = 1; - if(ansec) - rep.an_numrrsets = 1; - else rep.ns_numrrsets = 1; - rep.rrset_count = 1; - rep.rrsets = &rrset; - rep.reason_bogus = LDNS_EDE_NONE; - udpsize = edns->udp_size; - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, - repinfo, temp, env->now_tv) || !reply_info_answer_encode(qinfo, &rep, - *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), - buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) { - error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, - *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), edns); - } - return 1; -} - -/** encode local error answer */ -static void -local_error_encode(struct query_info* qinfo, struct module_env* env, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, int rcode, int r, int ede_code, - const char* ede_txt) -{ - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - - if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, - rcode, edns, repinfo, temp, env->now_tv)) - edns->opt_list_inplace_cb_out = NULL; - - if(ede_code != LDNS_EDE_NONE && env->cfg->ede) { - edns_opt_list_append_ede(&edns->opt_list_out, temp, - ede_code, ede_txt); - } - - error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), edns); -} - -/** find local data tag string match for the given type in the list */ -int -local_data_find_tag_datas(const struct query_info* qinfo, - struct config_strlist* list, struct ub_packed_rrset_key* r, - struct regional* temp) -{ - struct config_strlist* p; - char buf[65536]; - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t len; - int res; - struct packed_rrset_data* d; - for(p=list; p; p=p->next) { - uint16_t rdr_type; - - len = sizeof(rr); - /* does this element match the type? */ - snprintf(buf, sizeof(buf), ". %s", p->str); - res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, - NULL, 0, NULL, 0); - if(res != 0) - /* parse errors are already checked before, in - * acllist check_data, skip this for robustness */ - continue; - if(len < 1 /* . */ + 8 /* typeclassttl*/ + 2 /*rdatalen*/) - continue; - rdr_type = sldns_wirerr_get_type(rr, len, 1); - if(rdr_type != qinfo->qtype && rdr_type != LDNS_RR_TYPE_CNAME) - continue; - - /* do we have entries already? if not setup key */ - if(r->rk.dname == NULL) { - r->entry.key = r; - r->rk.dname = qinfo->qname; - r->rk.dname_len = qinfo->qname_len; - r->rk.type = htons(rdr_type); - r->rk.rrset_class = htons(qinfo->qclass); - r->rk.flags = 0; - d = (struct packed_rrset_data*)regional_alloc_zero( - temp, sizeof(struct packed_rrset_data) - + sizeof(size_t) + sizeof(uint8_t*) + - sizeof(time_t)); - if(!d) return 0; /* out of memory */ - r->entry.data = d; - d->ttl = sldns_wirerr_get_ttl(rr, len, 1); - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - d->rr_data = (uint8_t**)&(d->rr_len[1]); - d->rr_ttl = (time_t*)&(d->rr_data[1]); - } - d = (struct packed_rrset_data*)r->entry.data; - /* add entry to the data */ - if(d->count != 0) { - size_t* oldlen = d->rr_len; - uint8_t** olddata = d->rr_data; - time_t* oldttl = d->rr_ttl; - /* increase arrays for lookup */ - /* this is of course slow for very many records, - * but most redirects are expected with few records */ - d->rr_len = (size_t*)regional_alloc_zero(temp, - (d->count+1)*sizeof(size_t)); - d->rr_data = (uint8_t**)regional_alloc_zero(temp, - (d->count+1)*sizeof(uint8_t*)); - d->rr_ttl = (time_t*)regional_alloc_zero(temp, - (d->count+1)*sizeof(time_t)); - if(!d->rr_len || !d->rr_data || !d->rr_ttl) - return 0; /* out of memory */ - /* first one was allocated after struct d, but new - * ones get their own array increment alloc, so - * copy old content */ - memmove(d->rr_len, oldlen, d->count*sizeof(size_t)); - memmove(d->rr_data, olddata, d->count*sizeof(uint8_t*)); - memmove(d->rr_ttl, oldttl, d->count*sizeof(time_t)); - } - - d->rr_len[d->count] = sldns_wirerr_get_rdatalen(rr, len, 1)+2; - d->rr_ttl[d->count] = sldns_wirerr_get_ttl(rr, len, 1); - d->rr_data[d->count] = regional_alloc_init(temp, - sldns_wirerr_get_rdatawl(rr, len, 1), - d->rr_len[d->count]); - if(!d->rr_data[d->count]) - return 0; /* out of memory */ - d->count++; - } - if(r->rk.dname) - return 1; - return 0; -} - -static int -find_tag_datas(struct query_info* qinfo, struct config_strlist* list, - struct ub_packed_rrset_key* r, struct regional* temp) -{ - int result = local_data_find_tag_datas(qinfo, list, r, temp); - - /* If we've found a non-exact alias type of local data, make a shallow - * copy of the RRset and remember it in qinfo to complete the alias - * chain later. */ - if(result && qinfo->qtype != LDNS_RR_TYPE_CNAME && - r->rk.type == htons(LDNS_RR_TYPE_CNAME)) { - qinfo->local_alias = - regional_alloc_zero(temp, sizeof(struct local_rrset)); - if(!qinfo->local_alias) - return 0; /* out of memory */ - qinfo->local_alias->rrset = - regional_alloc_init(temp, r, sizeof(*r)); - if(!qinfo->local_alias->rrset) - return 0; /* out of memory */ - } - return result; -} - -int -local_data_answer(struct local_zone* z, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, int labs, struct local_data** ldp, - enum localzone_type lz_type, int tag, struct config_strlist** tag_datas, - size_t tag_datas_size, char** tagname, int num_tags) -{ - struct local_data key; - struct local_data* ld; - struct local_rrset* lr; - key.node.key = &key; - key.name = qinfo->qname; - key.namelen = qinfo->qname_len; - key.namelabs = labs; - if(lz_type == local_zone_redirect || - lz_type == local_zone_inform_redirect) { - key.name = z->name; - key.namelen = z->namelen; - key.namelabs = z->namelabs; - if(tag != -1 && (size_t)taglocal_alias) - return 1; - return local_encode(qinfo, env, edns, repinfo, buf, temp, - &r, 1, LDNS_RCODE_NOERROR); - } - } - } - ld = (struct local_data*)rbtree_search(&z->data, &key.node); - *ldp = ld; - if(!ld) { - return 0; - } - lr = local_data_find_type(ld, qinfo->qtype, 1); - if(!lr) - return 0; - - /* Special case for alias matching. See local_data_answer(). */ - if((lz_type == local_zone_redirect || - lz_type == local_zone_inform_redirect) && - qinfo->qtype != LDNS_RR_TYPE_CNAME && - lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) { - uint8_t* ctarget; - size_t ctargetlen = 0; - - qinfo->local_alias = - regional_alloc_zero(temp, sizeof(struct local_rrset)); - if(!qinfo->local_alias) - return 0; /* out of memory */ - qinfo->local_alias->rrset = regional_alloc_init( - temp, lr->rrset, sizeof(*lr->rrset)); - if(!qinfo->local_alias->rrset) - return 0; /* out of memory */ - qinfo->local_alias->rrset->rk.dname = qinfo->qname; - qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len; - get_cname_target(lr->rrset, &ctarget, &ctargetlen); - if(!ctargetlen) - return 0; /* invalid cname */ - if(dname_is_wild(ctarget)) { - /* synthesize cname target */ - struct packed_rrset_data* d; - /* -3 for wildcard label and root label from qname */ - size_t newtargetlen = qinfo->qname_len + ctargetlen - 3; - - log_assert(ctargetlen >= 3); - log_assert(qinfo->qname_len >= 1); - - if(newtargetlen > LDNS_MAX_DOMAINLEN) { - qinfo->local_alias = NULL; - local_error_encode(qinfo, env, edns, repinfo, - buf, temp, LDNS_RCODE_YXDOMAIN, - (LDNS_RCODE_YXDOMAIN|BIT_AA), - LDNS_EDE_OTHER, - "DNAME expansion became too large"); - return 1; - } - memset(&qinfo->local_alias->rrset->entry, 0, - sizeof(qinfo->local_alias->rrset->entry)); - qinfo->local_alias->rrset->entry.key = - qinfo->local_alias->rrset; - qinfo->local_alias->rrset->entry.hash = - rrset_key_hash(&qinfo->local_alias->rrset->rk); - d = (struct packed_rrset_data*)regional_alloc_zero(temp, - sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t) - + newtargetlen); - if(!d) - return 0; /* out of memory */ - qinfo->local_alias->rrset->entry.data = d; - d->ttl = 0; /* 0 for synthesized CNAME TTL */ - d->count = 1; - d->rrsig_count = 0; - d->trust = rrset_trust_ans_noAA; - d->rr_len = (size_t*)((uint8_t*)d + - sizeof(struct packed_rrset_data)); - d->rr_len[0] = newtargetlen + sizeof(uint16_t); - packed_rrset_ptr_fixup(d); - d->rr_ttl[0] = d->ttl; - sldns_write_uint16(d->rr_data[0], newtargetlen); - /* write qname */ - memmove(d->rr_data[0] + sizeof(uint16_t), qinfo->qname, - qinfo->qname_len - 1); - /* write cname target wildcard label */ - memmove(d->rr_data[0] + sizeof(uint16_t) + - qinfo->qname_len - 1, ctarget + 2, - ctargetlen - 2); - } - return 1; - } - if(lz_type == local_zone_redirect || - lz_type == local_zone_inform_redirect) { - /* convert rrset name to query name; like a wildcard */ - struct ub_packed_rrset_key r = *lr->rrset; - r.rk.dname = qinfo->qname; - r.rk.dname_len = qinfo->qname_len; - return local_encode(qinfo, env, edns, repinfo, buf, temp, &r, 1, - LDNS_RCODE_NOERROR); - } - return local_encode(qinfo, env, edns, repinfo, buf, temp, lr->rrset, 1, - LDNS_RCODE_NOERROR); -} - -/** - * See if the local zone does not cover the name, eg. the name is not - * in the zone and the zone is transparent */ -static int -local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo, - int labs) -{ - struct local_data key; - struct local_data* ld = NULL; - struct local_rrset* lr = NULL; - if(z->type == local_zone_always_transparent || z->type == local_zone_block_a) - return 1; - if(z->type != local_zone_transparent - && z->type != local_zone_typetransparent - && z->type != local_zone_inform) - return 0; - key.node.key = &key; - key.name = qinfo->qname; - key.namelen = qinfo->qname_len; - key.namelabs = labs; - ld = (struct local_data*)rbtree_search(&z->data, &key.node); - if(z->type == local_zone_transparent || z->type == local_zone_inform) - return (ld == NULL); - if(ld) - lr = local_data_find_type(ld, qinfo->qtype, 1); - /* local_zone_typetransparent */ - return (lr == NULL); -} - -static inline int -local_zone_is_udp_query(struct comm_reply* repinfo) { - return repinfo != NULL - ? (repinfo->c != NULL - ? repinfo->c->type == comm_udp - : 0) - : 0; -} - -int -local_zones_zone_answer(struct local_zone* z, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp, - struct local_data* ld, enum localzone_type lz_type) -{ - if(lz_type == local_zone_deny || - lz_type == local_zone_always_deny || - lz_type == local_zone_inform_deny) { - /** no reply at all, signal caller by clearing buffer. */ - sldns_buffer_clear(buf); - sldns_buffer_flip(buf); - return 1; - } else if(lz_type == local_zone_refuse - || lz_type == local_zone_always_refuse) { - local_error_encode(qinfo, env, edns, repinfo, buf, temp, - LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA), - LDNS_EDE_NONE, NULL); - return 1; - } else if(lz_type == local_zone_static || - lz_type == local_zone_redirect || - lz_type == local_zone_inform_redirect || - lz_type == local_zone_always_nxdomain || - lz_type == local_zone_always_nodata || - (lz_type == local_zone_truncate - && local_zone_is_udp_query(repinfo))) { - /* for static, reply nodata or nxdomain - * for redirect, reply nodata */ - /* no additional section processing, - * cname, dname or wildcard processing, - * or using closest match for NSEC. - * or using closest match for returning delegation downwards - */ - int rcode = (ld || lz_type == local_zone_redirect || - lz_type == local_zone_inform_redirect || - lz_type == local_zone_always_nodata || - lz_type == local_zone_truncate)? - LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; - rcode = (lz_type == local_zone_truncate ? (rcode|BIT_TC) : rcode); - if(z != NULL && z->soa && z->soa_negative) - return local_encode(qinfo, env, edns, repinfo, buf, temp, - z->soa_negative, 0, rcode); - local_error_encode(qinfo, env, edns, repinfo, buf, temp, - rcode, (rcode|BIT_AA), LDNS_EDE_NONE, NULL); - return 1; - } else if(lz_type == local_zone_typetransparent - || lz_type == local_zone_always_transparent) { - /* no NODATA or NXDOMAINS for this zone type */ - return 0; - } else if(lz_type == local_zone_block_a) { - /* Return NODATA for all A queries */ - if(qinfo->qtype == LDNS_RR_TYPE_A) { - local_error_encode(qinfo, env, edns, repinfo, buf, temp, - LDNS_RCODE_NOERROR, (LDNS_RCODE_NOERROR|BIT_AA), - LDNS_EDE_NONE, NULL); - return 1; - } - - return 0; - } else if(lz_type == local_zone_always_null) { - /* 0.0.0.0 or ::0 or noerror/nodata for this zone type, - * used for blocklists. */ - if(qinfo->qtype == LDNS_RR_TYPE_A || - qinfo->qtype == LDNS_RR_TYPE_AAAA) { - struct ub_packed_rrset_key lrr; - struct packed_rrset_data d; - time_t rr_ttl = 3600; - size_t rr_len = 0; - uint8_t rr_data[2+16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t* rr_datas = rr_data; - memset(&lrr, 0, sizeof(lrr)); - memset(&d, 0, sizeof(d)); - lrr.entry.data = &d; - lrr.rk.dname = qinfo->qname; - lrr.rk.dname_len = qinfo->qname_len; - lrr.rk.type = htons(qinfo->qtype); - lrr.rk.rrset_class = htons(qinfo->qclass); - if(qinfo->qtype == LDNS_RR_TYPE_A) { - rr_len = 4; - sldns_write_uint16(rr_data, rr_len); - rr_len += 2; - } else { - rr_len = 16; - sldns_write_uint16(rr_data, rr_len); - rr_len += 2; - } - d.ttl = rr_ttl; - d.count = 1; - d.rr_len = &rr_len; - d.rr_data = &rr_datas; - d.rr_ttl = &rr_ttl; - return local_encode(qinfo, env, edns, repinfo, buf, temp, - &lrr, 1, LDNS_RCODE_NOERROR); - } else { - /* NODATA: No EDE needed */ - local_error_encode(qinfo, env, edns, repinfo, buf, - temp, LDNS_RCODE_NOERROR, - (LDNS_RCODE_NOERROR|BIT_AA), -1, NULL); - } - return 1; - } - /* else lz_type == local_zone_transparent */ - - /* if the zone is transparent and the name exists, but the type - * does not, then we should make this noerror/nodata */ - if(ld && ld->rrsets) { - int rcode = LDNS_RCODE_NOERROR; - if(z != NULL && z->soa && z->soa_negative) - return local_encode(qinfo, env, edns, repinfo, buf, temp, - z->soa_negative, 0, rcode); - /* NODATA: No EDE needed */ - local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, - (rcode|BIT_AA), LDNS_EDE_NONE, NULL); - return 1; - } - - /* stop here, and resolve further on */ - return 0; -} - -/** print log information for an inform zone query */ -static void -lz_inform_print(struct local_zone* z, struct query_info* qinfo, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - char ip[128], txt[512]; - char zname[LDNS_MAX_DOMAINLEN+1]; - uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port); - dname_str(z->name, zname); - addr_to_str(addr, addrlen, ip, sizeof(ip)); - snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip, - (unsigned)port); - log_nametypeclass(NO_VERBOSE, txt, qinfo->qname, qinfo->qtype, qinfo->qclass); -} - -static enum localzone_type -lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2, - uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt, - struct comm_reply* repinfo, struct rbtree_type* override_tree, - int* tag, char** tagname, int num_tags) -{ - struct local_zone_override* lzo; - if(repinfo && override_tree) { - lzo = (struct local_zone_override*)addr_tree_lookup( - override_tree, &repinfo->client_addr, - repinfo->client_addrlen); - if(lzo && lzo->type) { - verbose(VERB_ALGO, "local zone override to type %s", - local_zone_type2str(lzo->type)); - return lzo->type; - } - } - if(!taglist || !taglist2) - return lzt; - return local_data_find_tag_action(taglist, taglen, taglist2, taglen2, - tagactions, tagactionssize, lzt, tag, tagname, num_tags); -} - -enum localzone_type -local_data_find_tag_action(const uint8_t* taglist, size_t taglen, - const uint8_t* taglist2, size_t taglen2, const uint8_t* tagactions, - size_t tagactionssize, enum localzone_type lzt, int* tag, - char* const* tagname, int num_tags) -{ - size_t i, j; - uint8_t tagmatch; - - for(i=0; i0; j++) { - if((tagmatch & 0x1)) { - *tag = (int)(i*8+j); - verbose(VERB_ALGO, "matched tag [%d] %s", - *tag, (*tag>= 1; - } - } - return lzt; -} - -int -local_zones_answer(struct local_zones* zones, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, - struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, - size_t taglen, uint8_t* tagactions, size_t tagactionssize, - struct config_strlist** tag_datas, size_t tag_datas_size, - char** tagname, int num_tags, struct view* view) -{ - /* see if query is covered by a zone, - * if so: - try to match (exact) local data - * - look at zone type for negative response. */ - int labs = dname_count_labels(qinfo->qname); - struct local_data* ld = NULL; - struct local_zone* z = NULL; - enum localzone_type lzt = local_zone_transparent; - int r, tag = -1; - - if(view) { - lock_rw_rdlock(&view->lock); - if(view->local_zones && - (z = local_zones_lookup(view->local_zones, - qinfo->qname, qinfo->qname_len, labs, - qinfo->qclass, qinfo->qtype))) { - lock_rw_rdlock(&z->lock); - lzt = z->type; - } - if(lzt == local_zone_noview) { - lock_rw_unlock(&z->lock); - z = NULL; - } - if(z && (lzt == local_zone_transparent || - lzt == local_zone_typetransparent || - lzt == local_zone_inform || - lzt == local_zone_always_transparent || - lzt == local_zone_block_a) && - local_zone_does_not_cover(z, qinfo, labs)) { - lock_rw_unlock(&z->lock); - z = NULL; - } - if(view->local_zones && !z && !view->isfirst){ - lock_rw_unlock(&view->lock); - return 0; - } - if(z && verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(z->name, zname); - verbose(VERB_ALGO, "using localzone %s %s from view %s", - zname, local_zone_type2str(lzt), view->name); - } - lock_rw_unlock(&view->lock); - } - if(!z) { - /* try global local_zones tree */ - lock_rw_rdlock(&zones->lock); - if(!(z = local_zones_tags_lookup(zones, qinfo->qname, - qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype, - taglist, taglen, 0))) { - lock_rw_unlock(&zones->lock); - return 0; - } - lock_rw_rdlock(&z->lock); - lzt = lz_type(taglist, taglen, z->taglist, z->taglen, - tagactions, tagactionssize, z->type, repinfo, - z->override_tree, &tag, tagname, num_tags); - lock_rw_unlock(&zones->lock); - if(z && verbosity >= VERB_ALGO) { - char zname[255+1]; - dname_str(z->name, zname); - verbose(VERB_ALGO, "using localzone %s %s", zname, - local_zone_type2str(lzt)); - } - } - if((env->cfg->log_local_actions || - lzt == local_zone_inform || - lzt == local_zone_inform_deny || - lzt == local_zone_inform_redirect) - && repinfo) - lz_inform_print(z, qinfo, &repinfo->client_addr, - repinfo->client_addrlen); - - if(lzt != local_zone_always_refuse - && lzt != local_zone_always_transparent - && lzt != local_zone_block_a - && lzt != local_zone_always_nxdomain - && lzt != local_zone_always_nodata - && lzt != local_zone_always_deny - && local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs, - &ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) { - lock_rw_unlock(&z->lock); - /* We should tell the caller that encode is deferred if we found - * a local alias. */ - return !qinfo->local_alias; - } - r = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt); - lock_rw_unlock(&z->lock); - return r && !qinfo->local_alias; /* see above */ -} - -const char* local_zone_type2str(enum localzone_type t) -{ - switch(t) { - case local_zone_unset: return "unset"; - case local_zone_deny: return "deny"; - case local_zone_refuse: return "refuse"; - case local_zone_redirect: return "redirect"; - case local_zone_transparent: return "transparent"; - case local_zone_typetransparent: return "typetransparent"; - case local_zone_static: return "static"; - case local_zone_nodefault: return "nodefault"; - case local_zone_inform: return "inform"; - case local_zone_inform_deny: return "inform_deny"; - case local_zone_inform_redirect: return "inform_redirect"; - case local_zone_always_transparent: return "always_transparent"; - case local_zone_block_a: return "block_a"; - case local_zone_always_refuse: return "always_refuse"; - case local_zone_always_nxdomain: return "always_nxdomain"; - case local_zone_always_nodata: return "always_nodata"; - case local_zone_always_deny: return "always_deny"; - case local_zone_always_null: return "always_null"; - case local_zone_noview: return "noview"; - case local_zone_truncate: return "truncate"; - case local_zone_invalid: return "invalid"; - } - return "badtyped"; -} - -int local_zone_str2type(const char* type, enum localzone_type* t) -{ - if(strcmp(type, "deny") == 0) - *t = local_zone_deny; - else if(strcmp(type, "refuse") == 0) - *t = local_zone_refuse; - else if(strcmp(type, "static") == 0) - *t = local_zone_static; - else if(strcmp(type, "transparent") == 0) - *t = local_zone_transparent; - else if(strcmp(type, "typetransparent") == 0) - *t = local_zone_typetransparent; - else if(strcmp(type, "redirect") == 0) - *t = local_zone_redirect; - else if(strcmp(type, "inform") == 0) - *t = local_zone_inform; - else if(strcmp(type, "inform_deny") == 0) - *t = local_zone_inform_deny; - else if(strcmp(type, "inform_redirect") == 0) - *t = local_zone_inform_redirect; - else if(strcmp(type, "always_transparent") == 0) - *t = local_zone_always_transparent; - else if(strcmp(type, "block_a") == 0) - *t = local_zone_block_a; - else if(strcmp(type, "always_refuse") == 0) - *t = local_zone_always_refuse; - else if(strcmp(type, "always_nxdomain") == 0) - *t = local_zone_always_nxdomain; - else if(strcmp(type, "always_nodata") == 0) - *t = local_zone_always_nodata; - else if(strcmp(type, "always_deny") == 0) - *t = local_zone_always_deny; - else if(strcmp(type, "always_null") == 0) - *t = local_zone_always_null; - else if(strcmp(type, "noview") == 0) - *t = local_zone_noview; - else if(strcmp(type, "truncate") == 0) - *t = local_zone_truncate; - else if(strcmp(type, "nodefault") == 0) - *t = local_zone_nodefault; - else return 0; - return 1; -} - -/** iterate over the kiddies of the given name and set their parent ptr */ -static void -set_kiddo_parents(struct local_zone* z, struct local_zone* match, - struct local_zone* newp) -{ - /* both zones and z are locked already */ - /* in the sorted rbtree, the kiddies of z are located after z */ - /* z must be present in the tree */ - struct local_zone* p = z; - p = (struct local_zone*)rbtree_next(&p->node); - while(p!=(struct local_zone*)RBTREE_NULL && - p->dclass == z->dclass && dname_strict_subdomain(p->name, - p->namelabs, z->name, z->namelabs)) { - /* update parent ptr */ - /* only when matches with existing parent pointer, so that - * deeper child structures are not touched, i.e. - * update of x, and a.x, b.x, f.b.x, g.b.x, c.x, y - * gets to update a.x, b.x and c.x */ - lock_rw_wrlock(&p->lock); - if(p->parent == match) - p->parent = newp; - lock_rw_unlock(&p->lock); - p = (struct local_zone*)rbtree_next(&p->node); - } -} - -struct local_zone* local_zones_add_zone(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, - enum localzone_type tp) -{ - /* create */ - struct local_zone* z = local_zone_create(name, len, labs, tp, dclass); - if(!z) { - free(name); - return NULL; - } - lock_rw_wrlock(&z->lock); - - /* find the closest parent */ - z->parent = local_zones_find(zones, name, len, labs, dclass); - - /* insert into the tree */ - if(!rbtree_insert(&zones->ztree, &z->node)) { - /* duplicate entry! */ - lock_rw_unlock(&z->lock); - local_zone_delete(z); - log_err("internal: duplicate entry in local_zones_add_zone"); - return NULL; - } - - /* set parent pointers right */ - set_kiddo_parents(z, z->parent, z); - - lock_rw_unlock(&z->lock); - return z; -} - -void local_zones_del_zone(struct local_zones* zones, struct local_zone* z) -{ - /* fix up parents in tree */ - lock_rw_wrlock(&z->lock); - set_kiddo_parents(z, z, z->parent); - - /* remove from tree */ - (void)rbtree_delete(&zones->ztree, z); - - /* delete the zone */ - lock_rw_unlock(&z->lock); - local_zone_delete(z); -} - -int -local_zones_add_RR(struct local_zones* zones, const char* rr) -{ - uint8_t* rr_name; - uint16_t rr_class, rr_type; - size_t len; - int labs; - struct local_zone* z; - int r; - if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) { - return 0; - } - labs = dname_count_size_labels(rr_name, &len); - /* could first try readlock then get writelock if zone does not exist, - * but we do not add enough RRs (from multiple threads) to optimize */ - lock_rw_wrlock(&zones->lock); - z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type); - if(!z) { - z = local_zones_add_zone(zones, rr_name, len, labs, rr_class, - local_zone_transparent); - if(!z) { - lock_rw_unlock(&zones->lock); - return 0; - } - } else { - free(rr_name); - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - r = lz_enter_rr_into_zone(z, rr); - lock_rw_unlock(&z->lock); - return r; -} - -/** returns true if the node is terminal so no deeper domain names exist */ -static int -is_terminal(struct local_data* d) -{ - /* for empty nonterminals, the deeper domain names are sorted - * right after them, so simply check the next name in the tree - */ - struct local_data* n = (struct local_data*)rbtree_next(&d->node); - if(n == (struct local_data*)RBTREE_NULL) - return 1; /* last in tree, no deeper node */ - if(dname_strict_subdomain(n->name, n->namelabs, d->name, d->namelabs)) - return 0; /* there is a deeper node */ - return 1; -} - -/** delete empty terminals from tree when final data is deleted */ -static void -del_empty_term(struct local_zone* z, struct local_data* d, - uint8_t* name, size_t len, int labs) -{ - while(d && d->rrsets == NULL && is_terminal(d)) { - /* is this empty nonterminal? delete */ - /* note, no memory recycling in zone region */ - (void)rbtree_delete(&z->data, d); - - /* go up and to the next label */ - if(dname_is_root(name)) - return; - dname_remove_label(&name, &len); - labs--; - d = local_zone_find_data(z, name, len, labs); - } -} - -/** find and remove type from list in domain struct */ -static void -del_local_rrset(struct local_data* d, uint16_t dtype) -{ - struct local_rrset* prev=NULL, *p=d->rrsets; - while(p && ntohs(p->rrset->rk.type) != dtype) { - prev = p; - p = p->next; - } - if(!p) - return; /* rrset type not found */ - /* unlink it */ - if(prev) prev->next = p->next; - else d->rrsets = p->next; - /* no memory recycling for zone deletions ... */ -} - -void local_zones_del_data(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass) -{ - /* find zone */ - struct local_zone* z; - struct local_data* d; - - /* remove DS */ - lock_rw_rdlock(&zones->lock); - z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS); - if(z) { - lock_rw_wrlock(&z->lock); - d = local_zone_find_data(z, name, len, labs); - if(d) { - del_local_rrset(d, LDNS_RR_TYPE_DS); - del_empty_term(z, d, name, len, labs); - } - lock_rw_unlock(&z->lock); - } - lock_rw_unlock(&zones->lock); - - /* remove other types */ - lock_rw_rdlock(&zones->lock); - z = local_zones_lookup(zones, name, len, labs, dclass, 0); - if(!z) { - /* no such zone, we're done */ - lock_rw_unlock(&zones->lock); - return; - } - lock_rw_wrlock(&z->lock); - lock_rw_unlock(&zones->lock); - - /* find the domain */ - d = local_zone_find_data(z, name, len, labs); - if(d) { - /* no memory recycling for zone deletions ... */ - d->rrsets = NULL; - /* did we delete the soa record ? */ - if(query_dname_compare(d->name, z->name) == 0) { - z->soa = NULL; - z->soa_negative = NULL; - } - - /* cleanup the empty nonterminals for this name */ - del_empty_term(z, d, name, len, labs); - } - - lock_rw_unlock(&z->lock); -} diff --git a/crates/libunbound-sys/unbound/services/localzone.h b/crates/libunbound-sys/unbound/services/localzone.h deleted file mode 100644 index 4456893e..00000000 --- a/crates/libunbound-sys/unbound/services/localzone.h +++ /dev/null @@ -1,644 +0,0 @@ -/* - * services/localzone.h - local zones authority service. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable local zone authority service. - */ - -#ifndef SERVICES_LOCALZONE_H -#define SERVICES_LOCALZONE_H -#include "util/rbtree.h" -#include "util/locks.h" -#include "util/storage/dnstree.h" -#include "util/module.h" -#include "services/view.h" -#include "sldns/sbuffer.h" -struct packed_rrset_data; -struct ub_packed_rrset_key; -struct regional; -struct config_file; -struct edns_data; -struct query_info; -struct sldns_buffer; -struct comm_reply; -struct config_strlist; - -/** - * Local zone type - * This type determines processing for queries that did not match - * local-data directly. - */ -enum localzone_type { - /** unset type, used for unset tag_action elements */ - local_zone_unset = 0, - /** drop query */ - local_zone_deny, - /** answer with error */ - local_zone_refuse, - /** answer nxdomain or nodata */ - local_zone_static, - /** resolve normally */ - local_zone_transparent, - /** do not block types at localdata names */ - local_zone_typetransparent, - /** answer with data at zone apex */ - local_zone_redirect, - /** remove default AS112 blocking contents for zone - * nodefault is used in config not during service. */ - local_zone_nodefault, - /** log client address, but no block (transparent) */ - local_zone_inform, - /** log client address, and block (drop) */ - local_zone_inform_deny, - /** log client address, and direct */ - local_zone_inform_redirect, - /** resolve normally, even when there is local data */ - local_zone_always_transparent, - /** resolve normally, even when there is local data but return NODATA for A queries */ - local_zone_block_a, - /** answer with error, even when there is local data */ - local_zone_always_refuse, - /** answer with nxdomain, even when there is local data */ - local_zone_always_nxdomain, - /** answer with noerror/nodata, even when there is local data */ - local_zone_always_nodata, - /** drop query, even when there is local data */ - local_zone_always_deny, - /** answer with 0.0.0.0 or ::0 or noerror/nodata, even when there is - * local data */ - local_zone_always_null, - /** answer not from the view, but global or no-answer */ - local_zone_noview, - /** truncate the response; client should retry via tcp */ - local_zone_truncate, - /** Invalid type, cannot be used to generate answer */ - local_zone_invalid -}; - -/** - * Authoritative local zones storage, shared. - */ -struct local_zones { - /** lock on the localzone tree */ - lock_rw_type lock; - /** rbtree of struct local_zone */ - rbtree_type ztree; -}; - -/** - * Local zone. A locally served authoritative zone. - */ -struct local_zone { - /** rbtree node, key is name and class */ - rbnode_type node; - /** parent zone, if any. */ - struct local_zone* parent; - - /** zone name, in uncompressed wireformat */ - uint8_t* name; - /** length of zone name */ - size_t namelen; - /** number of labels in zone name */ - int namelabs; - /** the class of this zone. - * uses 'dclass' to not conflict with c++ keyword class. */ - uint16_t dclass; - - /** lock on the data in the structure - * For the node, parent, name, namelen, namelabs, dclass, you - * need to also hold the zones_tree lock to change them (or to - * delete this zone) */ - lock_rw_type lock; - - /** how to process zone */ - enum localzone_type type; - /** tag bitlist */ - uint8_t* taglist; - /** length of the taglist (in bytes) */ - size_t taglen; - /** netblock addr_tree with struct local_zone_override information - * or NULL if there are no override elements */ - struct rbtree_type* override_tree; - - /** in this region the zone's data is allocated. - * the struct local_zone itself is malloced. */ - struct regional* region; - /** local data for this zone - * rbtree of struct local_data */ - rbtree_type data; - /** if data contains zone apex SOA data, this is a ptr to it. */ - struct ub_packed_rrset_key* soa; - /** if data contains zone apex SOA data, this is a ptr to an - * artificial negative SOA rrset (TTL is the minimum of the TTL and the - * SOA.MINIMUM). */ - struct ub_packed_rrset_key* soa_negative; -}; - -/** - * Local data. One domain name, and the RRs to go with it. - */ -struct local_data { - /** rbtree node, key is name only */ - rbnode_type node; - /** domain name */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** number of labels in name */ - int namelabs; - /** the data rrsets, with different types, linked list. - * If this list is NULL, the node is an empty non-terminal. */ - struct local_rrset* rrsets; -}; - -/** - * A local data RRset - */ -struct local_rrset { - /** next in list */ - struct local_rrset* next; - /** RRset data item */ - struct ub_packed_rrset_key* rrset; -}; - -/** - * Local zone override information - */ -struct local_zone_override { - /** node in addrtree */ - struct addr_tree_node node; - /** override for local zone type */ - enum localzone_type type; -}; - -/** - * Create local zones storage - * @return new struct or NULL on error. - */ -struct local_zones* local_zones_create(void); - -/** - * Delete local zones storage - * @param zones: to delete. - */ -void local_zones_delete(struct local_zones* zones); - -/** - * Apply config settings; setup the local authoritative data. - * Takes care of locking. - * @param zones: is set up. - * @param cfg: config data. - * @return false on error. - */ -int local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg); - -/** - * Compare two local_zone entries in rbtree. Sort hierarchical but not - * canonical - * @param z1: zone 1 - * @param z2: zone 2 - * @return: -1, 0, +1 comparison value. - */ -int local_zone_cmp(const void* z1, const void* z2); - -/** - * Compare two local_data entries in rbtree. Sort canonical. - * @param d1: data 1 - * @param d2: data 2 - * @return: -1, 0, +1 comparison value. - */ -int local_data_cmp(const void* d1, const void* d2); - -/** - * Delete one zone - * @param z: to delete. - */ -void local_zone_delete(struct local_zone* z); - -/** - * Lookup zone that contains the given name, class and taglist. - * User must lock the tree or result zone. - * @param zones: the zones tree - * @param name: dname to lookup - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to lookup. - * @param dtype: type to lookup, if type DS a zone higher is used for zonecuts. - * @param taglist: taglist to lookup. - * @param taglen: length of taglist. - * @param ignoretags: lookup zone by name and class, regardless the - * local-zone's tags. - * @return closest local_zone or NULL if no covering zone is found. - */ -struct local_zone* local_zones_tags_lookup(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype, - uint8_t* taglist, size_t taglen, int ignoretags); - -/** - * Lookup zone that contains the given name, class. - * User must lock the tree or result zone. - * @param zones: the zones tree - * @param name: dname to lookup - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to lookup. - * @param dtype: type of the record, if type DS then a zone higher up is found - * pass 0 to just plain find a zone for a name. - * @return closest local_zone or NULL if no covering zone is found. - */ -struct local_zone* local_zones_lookup(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype); - -/** - * Debug helper. Print all zones - * Takes care of locking. - * @param zones: the zones tree - */ -void local_zones_print(struct local_zones* zones); - -/** - * Answer authoritatively for local zones. - * Takes care of locking. - * @param zones: the stored zones (shared, read only). - * @param env: the module environment. - * @param qinfo: query info (parsed). - * @param edns: edns info (parsed). - * @param buf: buffer with query ID and flags, also for reply. - * @param temp: temporary storage region. - * @param repinfo: source address for checks. may be NULL. - * @param taglist: taglist for checks. May be NULL. - * @param taglen: length of the taglist. - * @param tagactions: local zone actions for tags. May be NULL. - * @param tagactionssize: length of the tagactions. - * @param tag_datas: array per tag of strlist with rdata strings. or NULL. - * @param tag_datas_size: size of tag_datas array. - * @param tagname: array of tag name strings (for debug output). - * @param num_tags: number of items in tagname array. - * @param view: answer using this view. May be NULL. - * @return true if answer is in buffer. false if query is not answered - * by authority data. If the reply should be dropped altogether, the return - * value is true, but the buffer is cleared (empty). - * It can also return true if a non-exact alias answer is found. In this - * case qinfo->local_alias points to the corresponding alias RRset but the - * answer is NOT encoded in buffer. It's the caller's responsibility to - * complete the alias chain (if needed) and encode the final set of answer. - * Data pointed to by qinfo->local_alias is allocated in 'temp' or refers to - * configuration data. So the caller will need to make a deep copy of it - * if it needs to keep it beyond the lifetime of 'temp' or a dynamic update - * to local zone data. - */ -int local_zones_answer(struct local_zones* zones, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf, - struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, - size_t taglen, uint8_t* tagactions, size_t tagactionssize, - struct config_strlist** tag_datas, size_t tag_datas_size, - char** tagname, int num_tags, struct view* view); - -/** - * Answer using the local zone only (not local data used). - * @param z: zone for query. - * @param env: module environment. - * @param qinfo: query. - * @param edns: edns from query. - * @param repinfo: source address for checks. may be NULL. - * @param buf: buffer for answer. - * @param temp: temp region for encoding. - * @param ld: local data, if NULL, no such name exists in localdata. - * @param lz_type: type of the local zone. - * @return 1 if a reply is to be sent, 0 if not. - */ -int -local_zones_zone_answer(struct local_zone* z, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp, - struct local_data* ld, enum localzone_type lz_type); - -/** - * Parse the string into localzone type. - * - * @param str: string to parse - * @param t: local zone type returned here. - * @return 0 on parse error. - */ -int local_zone_str2type(const char* str, enum localzone_type* t); - -/** - * Print localzone type to a string. Pointer to a constant string. - * - * @param t: local zone type. - * @return constant string that describes type. - */ -const char* local_zone_type2str(enum localzone_type t); - -/** - * Find zone that with exactly given name, class. - * User must lock the tree or result zone. - * @param zones: the zones tree - * @param name: dname to lookup - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to lookup. - * @return the exact local_zone or NULL. - */ -struct local_zone* local_zones_find(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass); - -/** - * Find zone that with exactly or smaller name/class - * User must lock the tree or result zone. - * @param zones: the zones tree - * @param name: dname to lookup - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to lookup. - * @param exact: 1 on return is this is an exact match. - * @return the exact or smaller local_zone or NULL. - */ -struct local_zone* -local_zones_find_le(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, - int* exact); - -/** - * Add a new zone. Caller must hold the zones lock. - * Adjusts the other zones as well (parent pointers) after insertion. - * The zone must NOT exist (returns NULL and logs error). - * @param zones: the zones tree - * @param name: dname to add - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to add. - * @param tp: type. - * @return local_zone or NULL on error, caller must printout memory error. - */ -struct local_zone* local_zones_add_zone(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass, - enum localzone_type tp); - -/** - * Delete a zone. Caller must hold the zones lock. - * Adjusts the other zones as well (parent pointers) after insertion. - * @param zones: the zones tree - * @param zone: the zone to delete from tree. Also deletes zone from memory. - */ -void local_zones_del_zone(struct local_zones* zones, struct local_zone* zone); - -/** - * Add RR data into the localzone data. - * Looks up the zone, if no covering zone, a transparent zone with the - * name of the RR is created. - * @param zones: the zones tree. Not locked by caller. - * @param rr: string with on RR. - * @return false on failure. - */ -int local_zones_add_RR(struct local_zones* zones, const char* rr); - -/** - * Remove data from domain name in the tree. - * All types are removed. No effect if zone or name does not exist. - * @param zones: zones tree. - * @param name: dname to remove - * @param len: length of name. - * @param labs: labelcount of name. - * @param dclass: class to remove. - */ -void local_zones_del_data(struct local_zones* zones, - uint8_t* name, size_t len, int labs, uint16_t dclass); - - -/** - * Form wireformat from text format domain name. - * @param str: the domain name in text "www.example.com" - * @param res: resulting wireformat is stored here with malloc. - * @param len: length of resulting wireformat. - * @param labs: number of labels in resulting wireformat. - * @return false on error, syntax or memory. Also logged. - */ -int parse_dname(const char* str, uint8_t** res, size_t* len, int* labs); - -/** - * Find local data tag string match for the given type (in qinfo) in the list. - * If found, 'r' will be filled with corresponding rrset information. - * @param qinfo: contains name, type, and class for the data - * @param list: stores local tag data to be searched - * @param r: rrset key to be filled for matched data - * @param temp: region to allocate rrset in 'r' - * @return 1 if a match is found and rrset is built; otherwise 0 including - * errors. - */ -int local_data_find_tag_datas(const struct query_info* qinfo, - struct config_strlist* list, struct ub_packed_rrset_key* r, - struct regional* temp); - -/** - * See if two sets of tag lists (in the form of bitmap) have the same tag that - * has an action. If so, '*tag' will be set to the found tag index, and the - * corresponding action will be returned in the form of local zone type. - * Otherwise the passed type (lzt) will be returned as the default action. - * Pointers except tagactions must not be NULL. - * @param taglist: 1st list of tags - * @param taglen: size of taglist in bytes - * @param taglist2: 2nd list of tags - * @param taglen2: size of taglist2 in bytes - * @param tagactions: local data actions for tags. May be NULL. - * @param tagactionssize: length of the tagactions. - * @param lzt: default action (local zone type) if no tag action is found. - * @param tag: see above. - * @param tagname: array of tag name strings (for debug output). - * @param num_tags: number of items in tagname array. - * @return found tag action or the default action. - */ -enum localzone_type local_data_find_tag_action(const uint8_t* taglist, - size_t taglen, const uint8_t* taglist2, size_t taglen2, - const uint8_t* tagactions, size_t tagactionssize, - enum localzone_type lzt, int* tag, char* const* tagname, int num_tags); - -/** - * Enter defaults to local zone. - * @param zones: to add defaults to - * @param cfg: containing list of zones to exclude from default set. - * @return 1 on success; 0 otherwise. - */ -int local_zone_enter_defaults(struct local_zones* zones, - struct config_file* cfg); - -/** - * Parses resource record string into wire format, also returning its field values. - * @param str: input resource record - * @param nm: domain name field - * @param type: record type field - * @param dclass: record class field - * @param ttl: ttl field - * @param rr: buffer for the parsed rr in wire format - * @param len: buffer length - * @param rdata: rdata field - * @param rdata_len: rdata field length - * @return 1 on success; 0 otherwise. - */ -int rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type, - uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len, - uint8_t** rdata, size_t* rdata_len); - -/** - * Insert specified rdata into the specified resource record. - * @param region: allocator - * @param pd: data portion of the destination resource record - * @param rdata: source rdata - * @param rdata_len: source rdata length - * @param ttl: time to live - * @param rrstr: resource record in text form (for logging) - * @return 1 on success; 0 otherwise. - */ -int rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd, - uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr); - -/** - * Remove RR from rrset that is created using localzone's rrset_insert_rr. - * @param pd: the RRset containing the RR to remove - * @param index: index of RR to remove - * @return: 1 on success; 0 otherwise. - */ -int -local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index); - -/** - * Valid response ip actions for the IP-response-driven-action feature; - * defined here instead of in the respip module to enable sharing of enum - * values with the localzone_type enum. - * Note that these values except 'none' are the same as localzone types of - * the 'same semantics'. It's intentional as we use these values via - * access-control-tags, which can be shared for both response ip actions and - * local zones. - */ -enum respip_action { - /** no respip action */ - respip_none = local_zone_unset, - /** don't answer */ - respip_deny = local_zone_deny, - /** redirect as per provided data */ - respip_redirect = local_zone_redirect, - /** log query source and answer query */ - respip_inform = local_zone_inform, - /** log query source and don't answer query */ - respip_inform_deny = local_zone_inform_deny, - /** log query source and redirect */ - respip_inform_redirect = local_zone_inform_redirect, - /** resolve normally, even when there is response-ip data */ - respip_always_transparent = local_zone_always_transparent, - /** answer with 'refused' response */ - respip_always_refuse = local_zone_always_refuse, - /** answer with 'no such domain' response */ - respip_always_nxdomain = local_zone_always_nxdomain, - /** answer with nodata response */ - respip_always_nodata = local_zone_always_nodata, - /** answer with nodata response */ - respip_always_deny = local_zone_always_deny, - /** RPZ: truncate answer in order to force switch to tcp */ - respip_truncate = local_zone_truncate, - - /* The rest of the values are only possible as - * access-control-tag-action */ - - /** serves response data (if any), else, drops queries. */ - respip_refuse = local_zone_refuse, - /** serves response data, else, nodata answer. */ - respip_static = local_zone_static, - /** gives response data (if any), else nodata answer. */ - respip_transparent = local_zone_transparent, - /** gives response data (if any), else nodata answer. */ - respip_typetransparent = local_zone_typetransparent, - /** type invalid */ - respip_invalid = local_zone_invalid, -}; - -/** - * Get local data from local zone and encode answer. - * @param z: local zone to use - * @param env: module env - * @param qinfo: qinfo - * @param edns: edns data, for message encoding - * @param repinfo: reply info, for message encoding - * @param buf: commpoint buffer - * @param temp: scratchpad region - * @param labs: number of labels in qname - * @param ldp: where to store local data - * @param lz_type: type of local zone - * @param tag: matching tag index - * @param tag_datas: alc specific tag data list - * @param tag_datas_size: size of tag_datas - * @param tagname: list of names of tags, for logging purpose - * @param num_tags: number of tags - * @return 1 on success - */ -int -local_data_answer(struct local_zone* z, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, - struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, int labs, struct local_data** ldp, - enum localzone_type lz_type, int tag, struct config_strlist** tag_datas, - size_t tag_datas_size, char** tagname, int num_tags); - -/** - * Add RR to local zone. - * @param z: local zone to add RR to - * @param nm: dname of RR - * @param nmlen: length of nm - * @param nmlabs: number of labels of nm - * @param rrtype: RR type - * @param rrclass: RR class - * @param ttl: TTL of RR to add - * @param rdata: RDATA of RR to add - * @param rdata_len: length of rdata - * @param rrstr: RR in string format, for logging - * @return: 1 on success - */ -int -local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen, - int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl, - uint8_t* rdata, size_t rdata_len, const char* rrstr); - -/** - * Find a data node by exact name for a local zone - * @param z: local_zone containing data tree - * @param nm: name of local-data element to find - * @param nmlen: length of nm - * @param nmlabs: labs of nm - * @return local_data on exact match, NULL otherwise. - */ -struct local_data* -local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs); -#endif /* SERVICES_LOCALZONE_H */ diff --git a/crates/libunbound-sys/unbound/services/mesh.c b/crates/libunbound-sys/unbound/services/mesh.c deleted file mode 100644 index 52d14a2d..00000000 --- a/crates/libunbound-sys/unbound/services/mesh.c +++ /dev/null @@ -1,2233 +0,0 @@ -/* - * services/mesh.c - deal with mesh of query states and handle events for that. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist in dealing with a mesh of - * query states. This mesh is supposed to be thread-specific. - * It consists of query states (per qname, qtype, qclass) and connections - * between query states and the super and subquery states, and replies to - * send back to clients. - */ -#include "config.h" -#include "services/mesh.h" -#include "services/outbound_list.h" -#include "services/cache/dns.h" -#include "services/cache/rrset.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/data/msgencode.h" -#include "util/timehist.h" -#include "util/fptr_wlist.h" -#include "util/alloc.h" -#include "util/config_file.h" -#include "util/edns.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "services/localzone.h" -#include "util/data/dname.h" -#include "respip/respip.h" -#include "services/listen_dnsport.h" -#include "util/timeval_func.h" - -#ifdef CLIENT_SUBNET -#include "edns-subnet/subnetmod.h" -#include "edns-subnet/edns-subnet.h" -#endif - -/** - * Compare two response-ip client info entries for the purpose of mesh state - * compare. It returns 0 if ci_a and ci_b are considered equal; otherwise - * 1 or -1 (they mean 'ci_a is larger/smaller than ci_b', respectively, but - * in practice it should be only used to mean they are different). - * We cannot share the mesh state for two queries if different response-ip - * actions can apply in the end, even if those queries are otherwise identical. - * For this purpose we compare tag lists and tag action lists; they should be - * identical to share the same state. - * For tag data, we don't look into the data content, as it can be - * expensive; unless tag data are not defined for both or they point to the - * exact same data in memory (i.e., they come from the same ACL entry), we - * consider these data different. - * Likewise, if the client info is associated with views, we don't look into - * the views. They are considered different unless they are exactly the same - * even if the views only differ in the names. - */ -static int -client_info_compare(const struct respip_client_info* ci_a, - const struct respip_client_info* ci_b) -{ - int cmp; - - if(!ci_a && !ci_b) - return 0; - if(ci_a && !ci_b) - return -1; - if(!ci_a && ci_b) - return 1; - if(ci_a->taglen != ci_b->taglen) - return (ci_a->taglen < ci_b->taglen) ? -1 : 1; - if(ci_a->taglist && !ci_b->taglist) - return -1; - if(!ci_a->taglist && ci_b->taglist) - return 1; - if(ci_a->taglist && ci_b->taglist) { - cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen); - if(cmp != 0) - return cmp; - } - if(ci_a->tag_actions_size != ci_b->tag_actions_size) - return (ci_a->tag_actions_size < ci_b->tag_actions_size) ? - -1 : 1; - if(ci_a->tag_actions && !ci_b->tag_actions) - return -1; - if(!ci_a->tag_actions && ci_b->tag_actions) - return 1; - if(ci_a->tag_actions && ci_b->tag_actions) { - cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions, - ci_a->tag_actions_size); - if(cmp != 0) - return cmp; - } - if(ci_a->tag_datas != ci_b->tag_datas) - return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1; - if(ci_a->view != ci_b->view) - return ci_a->view < ci_b->view ? -1 : 1; - /* For the unbound daemon these should be non-NULL and identical, - * but we check that just in case. */ - if(ci_a->respip_set != ci_b->respip_set) - return ci_a->respip_set < ci_b->respip_set ? -1 : 1; - return 0; -} - -int -mesh_state_compare(const void* ap, const void* bp) -{ - struct mesh_state* a = (struct mesh_state*)ap; - struct mesh_state* b = (struct mesh_state*)bp; - int cmp; - - if(a->unique < b->unique) - return -1; - if(a->unique > b->unique) - return 1; - - if(a->s.is_priming && !b->s.is_priming) - return -1; - if(!a->s.is_priming && b->s.is_priming) - return 1; - - if(a->s.is_valrec && !b->s.is_valrec) - return -1; - if(!a->s.is_valrec && b->s.is_valrec) - return 1; - - if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD)) - return -1; - if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD)) - return 1; - - if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD)) - return -1; - if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD)) - return 1; - - cmp = query_info_compare(&a->s.qinfo, &b->s.qinfo); - if(cmp != 0) - return cmp; - return client_info_compare(a->s.client_info, b->s.client_info); -} - -int -mesh_state_ref_compare(const void* ap, const void* bp) -{ - struct mesh_state_ref* a = (struct mesh_state_ref*)ap; - struct mesh_state_ref* b = (struct mesh_state_ref*)bp; - return mesh_state_compare(a->s, b->s); -} - -struct mesh_area* -mesh_create(struct module_stack* stack, struct module_env* env) -{ - struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area)); - if(!mesh) { - log_err("mesh area alloc: out of memory"); - return NULL; - } - mesh->histogram = timehist_setup(); - mesh->qbuf_bak = sldns_buffer_new(env->cfg->msg_buffer_size); - if(!mesh->histogram || !mesh->qbuf_bak) { - free(mesh); - log_err("mesh area alloc: out of memory"); - return NULL; - } - mesh->mods = *stack; - mesh->env = env; - rbtree_init(&mesh->run, &mesh_state_compare); - rbtree_init(&mesh->all, &mesh_state_compare); - mesh->num_reply_addrs = 0; - mesh->num_reply_states = 0; - mesh->num_detached_states = 0; - mesh->num_forever_states = 0; - mesh->stats_jostled = 0; - mesh->stats_dropped = 0; - mesh->ans_expired = 0; - mesh->ans_cachedb = 0; - mesh->max_reply_states = env->cfg->num_queries_per_thread; - mesh->max_forever_states = (mesh->max_reply_states+1)/2; -#ifndef S_SPLINT_S - mesh->jostle_max.tv_sec = (time_t)(env->cfg->jostle_time / 1000); - mesh->jostle_max.tv_usec = (time_t)((env->cfg->jostle_time % 1000) - *1000); -#endif - return mesh; -} - -/** help mesh delete delete mesh states */ -static void -mesh_delete_helper(rbnode_type* n) -{ - struct mesh_state* mstate = (struct mesh_state*)n->key; - /* perform a full delete, not only 'cleanup' routine, - * because other callbacks expect a clean state in the mesh. - * For 're-entrant' calls */ - mesh_state_delete(&mstate->s); - /* but because these delete the items from the tree, postorder - * traversal and rbtree rebalancing do not work together */ -} - -void -mesh_delete(struct mesh_area* mesh) -{ - if(!mesh) - return; - /* free all query states */ - while(mesh->all.count) - mesh_delete_helper(mesh->all.root); - timehist_delete(mesh->histogram); - sldns_buffer_free(mesh->qbuf_bak); - free(mesh); -} - -void -mesh_delete_all(struct mesh_area* mesh) -{ - /* free all query states */ - while(mesh->all.count) - mesh_delete_helper(mesh->all.root); - mesh->stats_dropped += mesh->num_reply_addrs; - /* clear mesh area references */ - rbtree_init(&mesh->run, &mesh_state_compare); - rbtree_init(&mesh->all, &mesh_state_compare); - mesh->num_reply_addrs = 0; - mesh->num_reply_states = 0; - mesh->num_detached_states = 0; - mesh->num_forever_states = 0; - mesh->forever_first = NULL; - mesh->forever_last = NULL; - mesh->jostle_first = NULL; - mesh->jostle_last = NULL; -} - -int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf) -{ - struct mesh_state* m = mesh->jostle_first; - /* free space is available */ - if(mesh->num_reply_states < mesh->max_reply_states) - return 1; - /* try to kick out a jostle-list item */ - if(m && m->reply_list && m->list_select == mesh_jostle_list) { - /* how old is it? */ - struct timeval age; - timeval_subtract(&age, mesh->env->now_tv, - &m->reply_list->start_time); - if(timeval_smaller(&mesh->jostle_max, &age)) { - /* its a goner */ - log_nametypeclass(VERB_ALGO, "query jostled out to " - "make space for a new one", - m->s.qinfo.qname, m->s.qinfo.qtype, - m->s.qinfo.qclass); - /* backup the query */ - if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf); - /* notify supers */ - if(m->super_set.count > 0) { - verbose(VERB_ALGO, "notify supers of failure"); - m->s.return_msg = NULL; - m->s.return_rcode = LDNS_RCODE_SERVFAIL; - mesh_walk_supers(mesh, m); - } - mesh->stats_jostled ++; - mesh_state_delete(&m->s); - /* restore the query - note that the qinfo ptr to - * the querybuffer is then correct again. */ - if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak); - return 1; - } - } - /* no space for new item */ - return 0; -} - -struct dns_msg* -mesh_serve_expired_lookup(struct module_qstate* qstate, - struct query_info* lookup_qinfo) -{ - hashvalue_type h; - struct lruhash_entry* e; - struct dns_msg* msg; - struct reply_info* data; - struct msgreply_entry* key; - time_t timenow = *qstate->env->now; - int must_validate = (!(qstate->query_flags&BIT_CD) - || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate; - /* Lookup cache */ - h = query_info_hash(lookup_qinfo, qstate->query_flags); - e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0); - if(!e) return NULL; - - key = (struct msgreply_entry*)e->key; - data = (struct reply_info*)e->data; - msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow, - qstate->env->cfg->serve_expired, qstate->env->scratch); - if(!msg) - goto bail_out; - - /* Check CNAME chain (if any) - * This is part of tomsg above; no need to check now. */ - - /* Check security status of the cached answer. - * tomsg above has a subset of these checks, so we are leaving - * these as is. - * In case of bogus or revalidation we don't care to reply here. */ - if(must_validate && (msg->rep->security == sec_status_bogus || - msg->rep->security == sec_status_secure_sentinel_fail)) { - verbose(VERB_ALGO, "Serve expired: bogus answer found in cache"); - goto bail_out; - } else if(msg->rep->security == sec_status_unchecked && must_validate) { - verbose(VERB_ALGO, "Serve expired: unchecked entry needs " - "validation"); - goto bail_out; /* need to validate cache entry first */ - } else if(msg->rep->security == sec_status_secure && - !reply_all_rrsets_secure(msg->rep) && must_validate) { - verbose(VERB_ALGO, "Serve expired: secure entry" - " changed status"); - goto bail_out; /* rrset changed, re-verify */ - } - - lock_rw_unlock(&e->lock); - return msg; - -bail_out: - lock_rw_unlock(&e->lock); - return NULL; -} - - -/** Init the serve expired data structure */ -static int -mesh_serve_expired_init(struct mesh_state* mstate, int timeout) -{ - struct timeval t; - - /* Create serve_expired_data if not there yet */ - if(!mstate->s.serve_expired_data) { - mstate->s.serve_expired_data = (struct serve_expired_data*) - regional_alloc_zero( - mstate->s.region, sizeof(struct serve_expired_data)); - if(!mstate->s.serve_expired_data) - return 0; - } - - /* Don't overwrite the function if already set */ - mstate->s.serve_expired_data->get_cached_answer = - mstate->s.serve_expired_data->get_cached_answer? - mstate->s.serve_expired_data->get_cached_answer: - &mesh_serve_expired_lookup; - - /* In case this timer already popped, start it again */ - if(!mstate->s.serve_expired_data->timer) { - mstate->s.serve_expired_data->timer = comm_timer_create( - mstate->s.env->worker_base, mesh_serve_expired_callback, mstate); - if(!mstate->s.serve_expired_data->timer) - return 0; -#ifndef S_SPLINT_S - t.tv_sec = timeout/1000; - t.tv_usec = (timeout%1000)*1000; -#endif - comm_timer_set(mstate->s.serve_expired_data->timer, &t); - } - return 1; -} - -void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, - struct respip_client_info* cinfo, uint16_t qflags, - struct edns_data* edns, struct comm_reply* rep, uint16_t qid, - int rpz_passthru) -{ - struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list_in, mesh->env); - int was_detached = 0; - int was_noreply = 0; - int added = 0; - int timeout = mesh->env->cfg->serve_expired? - mesh->env->cfg->serve_expired_client_timeout:0; - struct sldns_buffer* r_buffer = rep->c->buffer; - if(rep->c->tcp_req_info) { - r_buffer = rep->c->tcp_req_info->spool_buffer; - } - if(!unique) - s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0); - /* does this create a new reply state? */ - if(!s || s->list_select == mesh_no_list) { - if(!mesh_make_new_space(mesh, rep->c->buffer)) { - verbose(VERB_ALGO, "Too many queries. dropping " - "incoming query."); - comm_point_drop_reply(rep); - mesh->stats_dropped++; - return; - } - /* for this new reply state, the reply address is free, - * so the limit of reply addresses does not stop reply states*/ - } else { - /* protect our memory usage from storing reply addresses */ - if(mesh->num_reply_addrs > mesh->max_reply_states*16) { - verbose(VERB_ALGO, "Too many requests queued. " - "dropping incoming query."); - comm_point_drop_reply(rep); - mesh->stats_dropped++; - return; - } - } - /* see if it already exists, if not, create one */ - if(!s) { -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - s = mesh_state_create(mesh->env, qinfo, cinfo, - qflags&(BIT_RD|BIT_CD), 0, 0); - if(!s) { - log_err("mesh_state_create: out of memory; SERVFAIL"); - if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, - LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(r_buffer, LDNS_RCODE_SERVFAIL, - qinfo, qid, qflags, edns); - comm_point_send_reply(rep); - return; - } - /* set detached (it is now) */ - mesh->num_detached_states++; - if(unique) - mesh_state_make_unique(s); - s->s.rpz_passthru = rpz_passthru; - /* copy the edns options we got from the front */ - if(edns->opt_list_in) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, - s->s.region); - if(!s->s.edns_opts_front_in) { - log_err("edns_opt_copy_region: out of memory; SERVFAIL"); - if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, - NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(r_buffer, LDNS_RCODE_SERVFAIL, - qinfo, qid, qflags, edns); - comm_point_send_reply(rep); - mesh_state_delete(&s->s); - return; - } - } - -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->all, &s->node); - log_assert(n != NULL); - added = 1; - } - if(!s->reply_list && !s->cb_list) { - was_noreply = 1; - if(s->super_set.count == 0) { - was_detached = 1; - } - } - /* add reply to s */ - if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) { - log_err("mesh_new_client: out of memory; SERVFAIL"); - goto servfail_mem; - } - if(rep->c->tcp_req_info) { - if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) { - log_err("mesh_new_client: out of memory add tcpreqinfo"); - goto servfail_mem; - } - } - if(rep->c->use_h2) { - http2_stream_add_meshstate(rep->c->h2_stream, mesh, s); - } - /* add serve expired timer if required and not already there */ - if(timeout && !mesh_serve_expired_init(s, timeout)) { - log_err("mesh_new_client: out of memory initializing serve expired"); - goto servfail_mem; - } - /* update statistics */ - if(was_detached) { - log_assert(mesh->num_detached_states > 0); - mesh->num_detached_states--; - } - if(was_noreply) { - mesh->num_reply_states ++; - } - mesh->num_reply_addrs++; - if(s->list_select == mesh_no_list) { - /* move to either the forever or the jostle_list */ - if(mesh->num_forever_states < mesh->max_forever_states) { - mesh->num_forever_states ++; - mesh_list_insert(s, &mesh->forever_first, - &mesh->forever_last); - s->list_select = mesh_forever_list; - } else { - mesh_list_insert(s, &mesh->jostle_first, - &mesh->jostle_last); - s->list_select = mesh_jostle_list; - } - } - if(added) - mesh_run(mesh, s, module_event_new, NULL); - return; - -servfail_mem: - if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s, - NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list_inplace_cb_out = NULL; - error_encode(r_buffer, LDNS_RCODE_SERVFAIL, - qinfo, qid, qflags, edns); - comm_point_send_reply(rep); - if(added) - mesh_state_delete(&s->s); - return; -} - -int -mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, struct edns_data* edns, sldns_buffer* buf, - uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru) -{ - struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list_in, mesh->env); - int timeout = mesh->env->cfg->serve_expired? - mesh->env->cfg->serve_expired_client_timeout:0; - int was_detached = 0; - int was_noreply = 0; - int added = 0; - if(!unique) - s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0); - - /* there are no limits on the number of callbacks */ - - /* see if it already exists, if not, create one */ - if(!s) { -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - s = mesh_state_create(mesh->env, qinfo, NULL, - qflags&(BIT_RD|BIT_CD), 0, 0); - if(!s) { - return 0; - } - /* set detached (it is now) */ - mesh->num_detached_states++; - if(unique) - mesh_state_make_unique(s); - s->s.rpz_passthru = rpz_passthru; - if(edns->opt_list_in) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, - s->s.region); - if(!s->s.edns_opts_front_in) { - mesh_state_delete(&s->s); - return 0; - } - } -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->all, &s->node); - log_assert(n != NULL); - added = 1; - } - if(!s->reply_list && !s->cb_list) { - was_noreply = 1; - if(s->super_set.count == 0) { - was_detached = 1; - } - } - /* add reply to s */ - if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) { - if(added) - mesh_state_delete(&s->s); - return 0; - } - /* add serve expired timer if not already there */ - if(timeout && !mesh_serve_expired_init(s, timeout)) { - if(added) - mesh_state_delete(&s->s); - return 0; - } - /* update statistics */ - if(was_detached) { - log_assert(mesh->num_detached_states > 0); - mesh->num_detached_states--; - } - if(was_noreply) { - mesh->num_reply_states ++; - } - mesh->num_reply_addrs++; - if(added) - mesh_run(mesh, s, module_event_new, NULL); - return 1; -} - -/* Internal backend routine of mesh_new_prefetch(). It takes one additional - * parameter, 'run', which controls whether to run the prefetch state - * immediately. When this function is called internally 'run' could be - * 0 (false), in which case the new state is only made runnable so it - * will not be run recursively on top of the current state. */ -static void mesh_schedule_prefetch(struct mesh_area* mesh, - struct query_info* qinfo, uint16_t qflags, time_t leeway, int run, - int rpz_passthru) -{ - struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo, - qflags&(BIT_RD|BIT_CD), 0, 0); -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - /* already exists, and for a different purpose perhaps. - * if mesh_no_list, keep it that way. */ - if(s) { - /* make it ignore the cache from now on */ - if(!s->s.blacklist) - sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); - if(s->s.prefetch_leeway < leeway) - s->s.prefetch_leeway = leeway; - return; - } - if(!mesh_make_new_space(mesh, NULL)) { - verbose(VERB_ALGO, "Too many queries. dropped prefetch."); - mesh->stats_dropped ++; - return; - } - - s = mesh_state_create(mesh->env, qinfo, NULL, - qflags&(BIT_RD|BIT_CD), 0, 0); - if(!s) { - log_err("prefetch mesh_state_create: out of memory"); - return; - } -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->all, &s->node); - log_assert(n != NULL); - /* set detached (it is now) */ - mesh->num_detached_states++; - /* make it ignore the cache */ - sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); - s->s.prefetch_leeway = leeway; - - if(s->list_select == mesh_no_list) { - /* move to either the forever or the jostle_list */ - if(mesh->num_forever_states < mesh->max_forever_states) { - mesh->num_forever_states ++; - mesh_list_insert(s, &mesh->forever_first, - &mesh->forever_last); - s->list_select = mesh_forever_list; - } else { - mesh_list_insert(s, &mesh->jostle_first, - &mesh->jostle_last); - s->list_select = mesh_jostle_list; - } - } - s->s.rpz_passthru = rpz_passthru; - - if(!run) { -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->run, &s->run_node); - log_assert(n != NULL); - return; - } - - mesh_run(mesh, s, module_event_new, NULL); -} - -#ifdef CLIENT_SUBNET -/* Same logic as mesh_schedule_prefetch but tailored to the subnet module logic - * like passing along the comm_reply info. This will be faked into an EDNS - * option for processing by the subnet module if the client has not already - * attached its own ECS data. */ -static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh, - struct query_info* qinfo, uint16_t qflags, time_t leeway, int run, - int rpz_passthru, struct sockaddr_storage* addr, struct edns_option* edns_list) -{ - struct mesh_state* s = NULL; - struct edns_option* opt = NULL; -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - if(!mesh_make_new_space(mesh, NULL)) { - verbose(VERB_ALGO, "Too many queries. dropped prefetch."); - mesh->stats_dropped ++; - return; - } - - s = mesh_state_create(mesh->env, qinfo, NULL, - qflags&(BIT_RD|BIT_CD), 0, 0); - if(!s) { - log_err("prefetch_subnet mesh_state_create: out of memory"); - return; - } - mesh_state_make_unique(s); - - opt = edns_opt_list_find(edns_list, mesh->env->cfg->client_subnet_opcode); - if(opt) { - /* Use the client's ECS data */ - if(!edns_opt_list_append(&s->s.edns_opts_front_in, opt->opt_code, - opt->opt_len, opt->opt_data, s->s.region)) { - log_err("prefetch_subnet edns_opt_list_append: out of memory"); - return; - } - } else { - /* Store the client's address. Later in the subnet module, - * it is decided whether to include an ECS option or not. - */ - s->s.client_addr = *addr; - } -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->all, &s->node); - log_assert(n != NULL); - /* set detached (it is now) */ - mesh->num_detached_states++; - /* make it ignore the cache */ - sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); - s->s.prefetch_leeway = leeway; - - if(s->list_select == mesh_no_list) { - /* move to either the forever or the jostle_list */ - if(mesh->num_forever_states < mesh->max_forever_states) { - mesh->num_forever_states ++; - mesh_list_insert(s, &mesh->forever_first, - &mesh->forever_last); - s->list_select = mesh_forever_list; - } else { - mesh_list_insert(s, &mesh->jostle_first, - &mesh->jostle_last); - s->list_select = mesh_jostle_list; - } - } - s->s.rpz_passthru = rpz_passthru; - - if(!run) { -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->run, &s->run_node); - log_assert(n != NULL); - return; - } - - mesh_run(mesh, s, module_event_new, NULL); -} -#endif /* CLIENT_SUBNET */ - -void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, time_t leeway, int rpz_passthru, - struct sockaddr_storage* addr, struct edns_option* opt_list) -{ - (void)addr; - (void)opt_list; -#ifdef CLIENT_SUBNET - if(addr) - mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1, - rpz_passthru, addr, opt_list); - else -#endif - mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1, - rpz_passthru); -} - -void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, - struct comm_reply* reply, int what) -{ - enum module_ev event = module_event_reply; - e->qstate->reply = reply; - if(what != NETEVENT_NOERROR) { - event = module_event_noreply; - if(what == NETEVENT_CAPSFAIL) - event = module_event_capsfail; - } - mesh_run(mesh, e->qstate->mesh_info, event, e); -} - -struct mesh_state* -mesh_state_create(struct module_env* env, struct query_info* qinfo, - struct respip_client_info* cinfo, uint16_t qflags, int prime, - int valrec) -{ - struct regional* region = alloc_reg_obtain(env->alloc); - struct mesh_state* mstate; - int i; - if(!region) - return NULL; - mstate = (struct mesh_state*)regional_alloc(region, - sizeof(struct mesh_state)); - if(!mstate) { - alloc_reg_release(env->alloc, region); - return NULL; - } - memset(mstate, 0, sizeof(*mstate)); - mstate->node = *RBTREE_NULL; - mstate->run_node = *RBTREE_NULL; - mstate->node.key = mstate; - mstate->run_node.key = mstate; - mstate->reply_list = NULL; - mstate->list_select = mesh_no_list; - mstate->replies_sent = 0; - rbtree_init(&mstate->super_set, &mesh_state_ref_compare); - rbtree_init(&mstate->sub_set, &mesh_state_ref_compare); - mstate->num_activated = 0; - mstate->unique = NULL; - /* init module qstate */ - mstate->s.qinfo.qtype = qinfo->qtype; - mstate->s.qinfo.qclass = qinfo->qclass; - mstate->s.qinfo.local_alias = NULL; - mstate->s.qinfo.qname_len = qinfo->qname_len; - mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname, - qinfo->qname_len); - if(!mstate->s.qinfo.qname) { - alloc_reg_release(env->alloc, region); - return NULL; - } - if(cinfo) { - mstate->s.client_info = regional_alloc_init(region, cinfo, - sizeof(*cinfo)); - if(!mstate->s.client_info) { - alloc_reg_release(env->alloc, region); - return NULL; - } - } - /* remove all weird bits from qflags */ - mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD)); - mstate->s.is_priming = prime; - mstate->s.is_valrec = valrec; - mstate->s.reply = NULL; - mstate->s.region = region; - mstate->s.curmod = 0; - mstate->s.return_msg = 0; - mstate->s.return_rcode = LDNS_RCODE_NOERROR; - mstate->s.env = env; - mstate->s.mesh_info = mstate; - mstate->s.prefetch_leeway = 0; - mstate->s.serve_expired_data = NULL; - mstate->s.no_cache_lookup = 0; - mstate->s.no_cache_store = 0; - mstate->s.need_refetch = 0; - mstate->s.was_ratelimited = 0; - mstate->s.qstarttime = *env->now; - - /* init modules */ - for(i=0; imesh->mods.num; i++) { - mstate->s.minfo[i] = NULL; - mstate->s.ext_state[i] = module_state_initial; - } - /* init edns option lists */ - mstate->s.edns_opts_front_in = NULL; - mstate->s.edns_opts_back_out = NULL; - mstate->s.edns_opts_back_in = NULL; - mstate->s.edns_opts_front_out = NULL; - - return mstate; -} - -void -mesh_state_make_unique(struct mesh_state* mstate) -{ - mstate->unique = mstate; -} - -void -mesh_state_cleanup(struct mesh_state* mstate) -{ - struct mesh_area* mesh; - int i; - if(!mstate) - return; - mesh = mstate->s.env->mesh; - /* Stop and delete the serve expired timer */ - if(mstate->s.serve_expired_data && mstate->s.serve_expired_data->timer) { - comm_timer_delete(mstate->s.serve_expired_data->timer); - mstate->s.serve_expired_data->timer = NULL; - } - /* drop unsent replies */ - if(!mstate->replies_sent) { - struct mesh_reply* rep = mstate->reply_list; - struct mesh_cb* cb; - /* in tcp_req_info, the mstates linked are removed, but - * the reply_list is now NULL, so the remove-from-empty-list - * takes no time and also it does not do the mesh accounting */ - mstate->reply_list = NULL; - for(; rep; rep=rep->next) { - comm_point_drop_reply(&rep->query_reply); - log_assert(mesh->num_reply_addrs > 0); - mesh->num_reply_addrs--; - } - while((cb = mstate->cb_list)!=NULL) { - mstate->cb_list = cb->next; - fptr_ok(fptr_whitelist_mesh_cb(cb->cb)); - (*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL, - sec_status_unchecked, NULL, 0); - log_assert(mesh->num_reply_addrs > 0); - mesh->num_reply_addrs--; - } - } - - /* de-init modules */ - for(i=0; imods.num; i++) { - fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear)); - (*mesh->mods.mod[i]->clear)(&mstate->s, i); - mstate->s.minfo[i] = NULL; - mstate->s.ext_state[i] = module_finished; - } - alloc_reg_release(mstate->s.env->alloc, mstate->s.region); -} - -void -mesh_state_delete(struct module_qstate* qstate) -{ - struct mesh_area* mesh; - struct mesh_state_ref* super, ref; - struct mesh_state* mstate; - if(!qstate) - return; - mstate = qstate->mesh_info; - mesh = mstate->s.env->mesh; - mesh_detach_subs(&mstate->s); - if(mstate->list_select == mesh_forever_list) { - mesh->num_forever_states --; - mesh_list_remove(mstate, &mesh->forever_first, - &mesh->forever_last); - } else if(mstate->list_select == mesh_jostle_list) { - mesh_list_remove(mstate, &mesh->jostle_first, - &mesh->jostle_last); - } - if(!mstate->reply_list && !mstate->cb_list - && mstate->super_set.count == 0) { - log_assert(mesh->num_detached_states > 0); - mesh->num_detached_states--; - } - if(mstate->reply_list || mstate->cb_list) { - log_assert(mesh->num_reply_states > 0); - mesh->num_reply_states--; - } - ref.node.key = &ref; - ref.s = mstate; - RBTREE_FOR(super, struct mesh_state_ref*, &mstate->super_set) { - (void)rbtree_delete(&super->s->sub_set, &ref); - } - (void)rbtree_delete(&mesh->run, mstate); - (void)rbtree_delete(&mesh->all, mstate); - mesh_state_cleanup(mstate); -} - -/** helper recursive rbtree find routine */ -static int -find_in_subsub(struct mesh_state* m, struct mesh_state* tofind, size_t *c) -{ - struct mesh_state_ref* r; - if((*c)++ > MESH_MAX_SUBSUB) - return 1; - RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) { - if(r->s == tofind || find_in_subsub(r->s, tofind, c)) - return 1; - } - return 0; -} - -/** find cycle for already looked up mesh_state */ -static int -mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m) -{ - struct mesh_state* cyc_m = qstate->mesh_info; - size_t counter = 0; - if(!dep_m) - return 0; - if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m, &counter)) { - if(counter > MESH_MAX_SUBSUB) - return 2; - return 1; - } - return 0; -} - -void mesh_detach_subs(struct module_qstate* qstate) -{ - struct mesh_area* mesh = qstate->env->mesh; - struct mesh_state_ref* ref, lookup; -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - lookup.node.key = &lookup; - lookup.s = qstate->mesh_info; - RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) { -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_delete(&ref->s->super_set, &lookup); - log_assert(n != NULL); /* must have been present */ - if(!ref->s->reply_list && !ref->s->cb_list - && ref->s->super_set.count == 0) { - mesh->num_detached_states++; - log_assert(mesh->num_detached_states + - mesh->num_reply_states <= mesh->all.count); - } - } - rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare); -} - -int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub) -{ - /* find it, if not, create it */ - struct mesh_area* mesh = qstate->env->mesh; - *sub = mesh_area_find(mesh, NULL, qinfo, qflags, - prime, valrec); - if(mesh_detect_cycle_found(qstate, *sub)) { - verbose(VERB_ALGO, "attach failed, cycle detected"); - return 0; - } - if(!*sub) { -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - /* create a new one */ - *sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime, - valrec); - if(!*sub) { - log_err("mesh_attach_sub: out of memory"); - return 0; - } -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->all, &(*sub)->node); - log_assert(n != NULL); - /* set detached (it is now) */ - mesh->num_detached_states++; - /* set new query state to run */ -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&mesh->run, &(*sub)->run_node); - log_assert(n != NULL); - *newq = &(*sub)->s; - } else - *newq = NULL; - return 1; -} - -int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq) -{ - struct mesh_area* mesh = qstate->env->mesh; - struct mesh_state* sub = NULL; - int was_detached; - if(!mesh_add_sub(qstate, qinfo, qflags, prime, valrec, newq, &sub)) - return 0; - was_detached = (sub->super_set.count == 0); - if(!mesh_state_attachment(qstate->mesh_info, sub)) - return 0; - /* if it was a duplicate attachment, the count was not zero before */ - if(!sub->reply_list && !sub->cb_list && was_detached && - sub->super_set.count == 1) { - /* it used to be detached, before this one got added */ - log_assert(mesh->num_detached_states > 0); - mesh->num_detached_states--; - } - /* *newq will be run when inited after the current module stops */ - return 1; -} - -int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub) -{ -#ifdef UNBOUND_DEBUG - struct rbnode_type* n; -#endif - struct mesh_state_ref* subref; /* points to sub, inserted in super */ - struct mesh_state_ref* superref; /* points to super, inserted in sub */ - if( !(subref = regional_alloc(super->s.region, - sizeof(struct mesh_state_ref))) || - !(superref = regional_alloc(sub->s.region, - sizeof(struct mesh_state_ref))) ) { - log_err("mesh_state_attachment: out of memory"); - return 0; - } - superref->node.key = superref; - superref->s = super; - subref->node.key = subref; - subref->s = sub; - if(!rbtree_insert(&sub->super_set, &superref->node)) { - /* this should not happen, iterator and validator do not - * attach subqueries that are identical. */ - /* already attached, we are done, nothing todo. - * since superref and subref already allocated in region, - * we cannot free them */ - return 1; - } -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(&super->sub_set, &subref->node); - log_assert(n != NULL); /* we checked above if statement, the reverse - administration should not fail now, unless they are out of sync */ - return 1; -} - -/** - * callback results to mesh cb entry - * @param m: mesh state to send it for. - * @param rcode: if not 0, error code. - * @param rep: reply to send (or NULL if rcode is set). - * @param r: callback entry - * @param start_time: the time to pass to callback functions, it is 0 or - * a value from one of the packets if the mesh state had packets. - */ -static void -mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, - struct mesh_cb* r, struct timeval* start_time) -{ - int secure; - char* reason = NULL; - int was_ratelimited = m->s.was_ratelimited; - /* bogus messages are not made into servfail, sec_status passed - * to the callback function */ - if(rep && rep->security == sec_status_secure) - secure = 1; - else secure = 0; - if(!rep && rcode == LDNS_RCODE_NOERROR) - rcode = LDNS_RCODE_SERVFAIL; - if(!rcode && rep && (rep->security == sec_status_bogus || - rep->security == sec_status_secure_sentinel_fail)) { - if(!(reason = errinf_to_str_bogus(&m->s))) - rcode = LDNS_RCODE_SERVFAIL; - } - /* send the reply */ - if(rcode) { - if(rcode == LDNS_RCODE_SERVFAIL) { - if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, - rep, rcode, &r->edns, NULL, m->s.region, start_time)) - r->edns.opt_list_inplace_cb_out = NULL; - } else { - if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, - &r->edns, NULL, m->s.region, start_time)) - r->edns.opt_list_inplace_cb_out = NULL; - } - fptr_ok(fptr_whitelist_mesh_cb(r->cb)); - (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL, - was_ratelimited); - } else { - size_t udp_size = r->edns.udp_size; - sldns_buffer_clear(r->buf); - r->edns.edns_version = EDNS_ADVERTISED_VERSION; - r->edns.udp_size = EDNS_ADVERTISED_SIZE; - r->edns.ext_rcode = 0; - r->edns.bits &= EDNS_DO; - - if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, - LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) || - !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, - r->qflags, r->buf, 0, 1, - m->s.env->scratch, udp_size, &r->edns, - (int)(r->edns.bits & EDNS_DO), secure)) - { - fptr_ok(fptr_whitelist_mesh_cb(r->cb)); - (*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf, - sec_status_unchecked, NULL, 0); - } else { - fptr_ok(fptr_whitelist_mesh_cb(r->cb)); - (*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf, - (rep?rep->security:sec_status_unchecked), - reason, was_ratelimited); - } - } - free(reason); - log_assert(m->s.env->mesh->num_reply_addrs > 0); - m->s.env->mesh->num_reply_addrs--; -} - -static inline int -mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m) -{ - struct respip_action_info const* respip_info = m->s.respip_action_info; - return respip_info == NULL - ? 0 - : (respip_info->rpz_used - && !respip_info->rpz_disabled - && respip_info->action == respip_truncate); -} - -static inline int -mesh_is_udp(struct mesh_reply const* r) -{ - return r->query_reply.c->type == comm_udp; -} - -static inline void -mesh_find_and_attach_ede_and_reason(struct mesh_state* m, - struct reply_info* rep, struct mesh_reply* r) -{ - /* OLD note: - * During validation the EDE code can be received via two - * code paths. One code path fills the reply_info EDE, and - * the other fills it in the errinf_strlist. These paths - * intersect at some points, but where is opaque due to - * the complexity of the validator. At the time of writing - * we make the choice to prefer the EDE from errinf_strlist - * but a compelling reason to do otherwise is just as valid - * NEW note: - * The compelling reason is that with caching support, the value - * in the reply_info is cached. - * The reason members of the reply_info struct should be - * updated as they are already cached. No reason to - * try and find the EDE information in errinf anymore. - */ - if(rep->reason_bogus != LDNS_EDE_NONE) { - edns_opt_list_append_ede(&r->edns.opt_list_out, - m->s.region, rep->reason_bogus, rep->reason_bogus_str); - } -} - -/** - * Send reply to mesh reply entry - * @param m: mesh state to send it for. - * @param rcode: if not 0, error code. - * @param rep: reply to send (or NULL if rcode is set). - * @param r: reply entry - * @param r_buffer: buffer to use for reply entry. - * @param prev: previous reply, already has its answer encoded in buffer. - * @param prev_buffer: buffer for previous reply. - */ -static void -mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, - struct mesh_reply* r, struct sldns_buffer* r_buffer, - struct mesh_reply* prev, struct sldns_buffer* prev_buffer) -{ - struct timeval end_time; - struct timeval duration; - int secure; - /* briefly set the replylist to null in case the - * meshsendreply calls tcpreqinfo sendreply that - * comm_point_drops because of size, and then the - * null stops the mesh state remove and thus - * reply_list modification and accounting */ - struct mesh_reply* rlist = m->reply_list; - - /* rpz: apply actions */ - rcode = mesh_is_udp(r) && mesh_is_rpz_respip_tcponly_action(m) - ? (rcode|BIT_TC) : rcode; - - /* examine security status */ - if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || - m->s.env->cfg->ignore_cd) && rep && - (rep->security <= sec_status_bogus || - rep->security == sec_status_secure_sentinel_fail)) { - rcode = LDNS_RCODE_SERVFAIL; - if(m->s.env->cfg->stat_extended) - m->s.env->mesh->ans_bogus++; - } - if(rep && rep->security == sec_status_secure) - secure = 1; - else secure = 0; - if(!rep && rcode == LDNS_RCODE_NOERROR) - rcode = LDNS_RCODE_SERVFAIL; - if(r->query_reply.c->use_h2) { - r->query_reply.c->h2_stream = r->h2_stream; - /* Mesh reply won't exist for long anymore. Make it impossible - * for HTTP/2 stream to refer to mesh state, in case - * connection gets cleanup before HTTP/2 stream close. */ - r->h2_stream->mesh_state = NULL; - } - /* send the reply */ - /* We don't reuse the encoded answer if: - * - either the previous or current response has a local alias. We could - * compare the alias records and still reuse the previous answer if they - * are the same, but that would be complicated and error prone for the - * relatively minor case. So we err on the side of safety. - * - there are registered callback functions for the given rcode, as these - * need to be called for each reply. */ - if(((rcode != LDNS_RCODE_SERVFAIL && - !m->s.env->inplace_cb_lists[inplace_cb_reply]) || - (rcode == LDNS_RCODE_SERVFAIL && - !m->s.env->inplace_cb_lists[inplace_cb_reply_servfail])) && - prev && prev_buffer && prev->qflags == r->qflags && - !prev->local_alias && !r->local_alias && - prev->edns.edns_present == r->edns.edns_present && - prev->edns.bits == r->edns.bits && - prev->edns.udp_size == r->edns.udp_size && - edns_opt_list_compare(prev->edns.opt_list_out, r->edns.opt_list_out) == 0 && - edns_opt_list_compare(prev->edns.opt_list_inplace_cb_out, r->edns.opt_list_inplace_cb_out) == 0 - ) { - /* if the previous reply is identical to this one, fix ID */ - if(prev_buffer != r_buffer) - sldns_buffer_copy(r_buffer, prev_buffer); - sldns_buffer_write_at(r_buffer, 0, &r->qid, sizeof(uint16_t)); - sldns_buffer_write_at(r_buffer, 12, r->qname, - m->s.qinfo.qname_len); - m->reply_list = NULL; - comm_point_send_reply(&r->query_reply); - m->reply_list = rlist; - } else if(rcode) { - m->s.qinfo.qname = r->qname; - m->s.qinfo.local_alias = r->local_alias; - if(rcode == LDNS_RCODE_SERVFAIL) { - if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, - rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list_inplace_cb_out = NULL; - } else { - if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, - &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list_inplace_cb_out = NULL; - } - /* Send along EDE EDNS0 option when SERVFAILing; usually - * DNSSEC validation failures */ - /* Since we are SERVFAILing here, CD bit and rep->security - * is already handled. */ - if(m->s.env->cfg->ede && rep) { - mesh_find_and_attach_ede_and_reason(m, rep, r); - } - error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, - r->qflags, &r->edns); - m->reply_list = NULL; - comm_point_send_reply(&r->query_reply); - m->reply_list = rlist; - } else { - size_t udp_size = r->edns.udp_size; - r->edns.edns_version = EDNS_ADVERTISED_VERSION; - r->edns.udp_size = EDNS_ADVERTISED_SIZE; - r->edns.ext_rcode = 0; - r->edns.bits &= EDNS_DO; - m->s.qinfo.qname = r->qname; - m->s.qinfo.local_alias = r->local_alias; - - /* Attach EDE without SERVFAIL if the validation failed. - * Need to explicitly check for rep->security otherwise failed - * validation paths may attach to a secure answer. */ - if(m->s.env->cfg->ede && rep && - (rep->security <= sec_status_bogus || - rep->security == sec_status_secure_sentinel_fail)) { - mesh_find_and_attach_ede_and_reason(m, rep, r); - } - - if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, - LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) || - !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, - r->qflags, r_buffer, 0, 1, m->s.env->scratch, - udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO), - secure)) - { - if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, - rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list_inplace_cb_out = NULL; - /* internal server error (probably malloc failure) so no - * EDE (RFC8914) needed */ - error_encode(r_buffer, LDNS_RCODE_SERVFAIL, - &m->s.qinfo, r->qid, r->qflags, &r->edns); - } - m->reply_list = NULL; - comm_point_send_reply(&r->query_reply); - m->reply_list = rlist; - } - /* account */ - log_assert(m->s.env->mesh->num_reply_addrs > 0); - m->s.env->mesh->num_reply_addrs--; - end_time = *m->s.env->now_tv; - timeval_subtract(&duration, &end_time, &r->start_time); - verbose(VERB_ALGO, "query took " ARG_LL "d.%6.6d sec", - (long long)duration.tv_sec, (int)duration.tv_usec); - m->s.env->mesh->replies_sent++; - timeval_add(&m->s.env->mesh->replies_sum_wait, &duration); - timehist_insert(m->s.env->mesh->histogram, &duration); - if(m->s.env->cfg->stat_extended) { - uint16_t rc = FLAGS_GET_RCODE(sldns_buffer_read_u16_at( - r_buffer, 2)); - if(secure) m->s.env->mesh->ans_secure++; - m->s.env->mesh->ans_rcode[ rc ] ++; - if(rc == 0 && LDNS_ANCOUNT(sldns_buffer_begin(r_buffer)) == 0) - m->s.env->mesh->ans_nodata++; - } - /* Log reply sent */ - if(m->s.env->cfg->log_replies) { - log_reply_info(NO_VERBOSE, &m->s.qinfo, - &r->query_reply.client_addr, - r->query_reply.client_addrlen, duration, 0, r_buffer); - } -} - -void mesh_query_done(struct mesh_state* mstate) -{ - struct mesh_reply* r; - struct mesh_reply* prev = NULL; - struct sldns_buffer* prev_buffer = NULL; - struct mesh_cb* c; - struct reply_info* rep = (mstate->s.return_msg? - mstate->s.return_msg->rep:NULL); - struct timeval tv = {0, 0}; - int i = 0; - /* No need for the serve expired timer anymore; we are going to reply. */ - if(mstate->s.serve_expired_data) { - comm_timer_delete(mstate->s.serve_expired_data->timer); - mstate->s.serve_expired_data->timer = NULL; - } - if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL || - (rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) { - /* we are SERVFAILing; check for expired answer here */ - mesh_serve_expired_callback(mstate); - if((mstate->reply_list || mstate->cb_list) - && mstate->s.env->cfg->log_servfail - && !mstate->s.env->cfg->val_log_squelch) { - char* err = errinf_to_str_servfail(&mstate->s); - if(err) - log_err("%s", err); - free(err); - } - } - for(r = mstate->reply_list; r; r = r->next) { - i++; - tv = r->start_time; - - /* if a response-ip address block has been stored the - * information should be logged for each client. */ - if(mstate->s.respip_action_info && - mstate->s.respip_action_info->addrinfo) { - respip_inform_print(mstate->s.respip_action_info, - r->qname, mstate->s.qinfo.qtype, - mstate->s.qinfo.qclass, r->local_alias, - &r->query_reply.client_addr, - r->query_reply.client_addrlen); - } - - /* if this query is determined to be dropped during the - * mesh processing, this is the point to take that action. */ - if(mstate->s.is_drop) { - /* briefly set the reply_list to NULL, so that the - * tcp req info cleanup routine that calls the mesh - * to deregister the meshstate for it is not done - * because the list is NULL and also accounting is not - * done there, but instead we do that here. */ - struct mesh_reply* reply_list = mstate->reply_list; - mstate->reply_list = NULL; - comm_point_drop_reply(&r->query_reply); - mstate->reply_list = reply_list; - } else { - struct sldns_buffer* r_buffer = r->query_reply.c->buffer; - if(r->query_reply.c->tcp_req_info) { - r_buffer = r->query_reply.c->tcp_req_info->spool_buffer; - prev_buffer = NULL; - } - mesh_send_reply(mstate, mstate->s.return_rcode, rep, - r, r_buffer, prev, prev_buffer); - if(r->query_reply.c->tcp_req_info) { - tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate); - r_buffer = NULL; - } - prev = r; - prev_buffer = r_buffer; - } - } - /* Account for each reply sent. */ - if(i > 0 && mstate->s.respip_action_info && - mstate->s.respip_action_info->addrinfo && - mstate->s.env->cfg->stat_extended && - mstate->s.respip_action_info->rpz_used) { - if(mstate->s.respip_action_info->rpz_disabled) - mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i; - if(mstate->s.respip_action_info->rpz_cname_override) - mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i; - else - mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action( - mstate->s.respip_action_info->action)] += i; - } - if(!mstate->s.is_drop && i > 0) { - if(mstate->s.env->cfg->stat_extended - && mstate->s.is_cachedb_answer) { - mstate->s.env->mesh->ans_cachedb += i; - } - } - - /* Mesh area accounting */ - if(mstate->reply_list) { - mstate->reply_list = NULL; - if(!mstate->reply_list && !mstate->cb_list) { - /* was a reply state, not anymore */ - log_assert(mstate->s.env->mesh->num_reply_states > 0); - mstate->s.env->mesh->num_reply_states--; - } - if(!mstate->reply_list && !mstate->cb_list && - mstate->super_set.count == 0) - mstate->s.env->mesh->num_detached_states++; - } - mstate->replies_sent = 1; - - while((c = mstate->cb_list) != NULL) { - /* take this cb off the list; so that the list can be - * changed, eg. by adds from the callback routine */ - if(!mstate->reply_list && mstate->cb_list && !c->next) { - /* was a reply state, not anymore */ - log_assert(mstate->s.env->mesh->num_reply_states > 0); - mstate->s.env->mesh->num_reply_states--; - } - mstate->cb_list = c->next; - if(!mstate->reply_list && !mstate->cb_list && - mstate->super_set.count == 0) - mstate->s.env->mesh->num_detached_states++; - mesh_do_callback(mstate, mstate->s.return_rcode, rep, c, &tv); - } -} - -void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate) -{ - struct mesh_state_ref* ref; - RBTREE_FOR(ref, struct mesh_state_ref*, &mstate->super_set) - { - /* make super runnable */ - (void)rbtree_insert(&mesh->run, &ref->s->run_node); - /* callback the function to inform super of result */ - fptr_ok(fptr_whitelist_mod_inform_super( - mesh->mods.mod[ref->s->s.curmod]->inform_super)); - (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s, - ref->s->s.curmod, &ref->s->s); - /* copy state that is always relevant to super */ - copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s); - } -} - -struct mesh_state* mesh_area_find(struct mesh_area* mesh, - struct respip_client_info* cinfo, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec) -{ - struct mesh_state key; - struct mesh_state* result; - - key.node.key = &key; - key.s.is_priming = prime; - key.s.is_valrec = valrec; - key.s.qinfo = *qinfo; - key.s.query_flags = qflags; - /* We are searching for a similar mesh state when we DO want to - * aggregate the state. Thus unique is set to NULL. (default when we - * desire aggregation).*/ - key.unique = NULL; - key.s.client_info = cinfo; - - result = (struct mesh_state*)rbtree_search(&mesh->all, &key); - return result; -} - -int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, - sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg, - uint16_t qid, uint16_t qflags) -{ - struct mesh_cb* r = regional_alloc(s->s.region, - sizeof(struct mesh_cb)); - if(!r) - return 0; - r->buf = buf; - log_assert(fptr_whitelist_mesh_cb(cb)); /* early failure ifmissing*/ - r->cb = cb; - r->cb_arg = cb_arg; - r->edns = *edns; - if(edns->opt_list_in && !(r->edns.opt_list_in = - edns_opt_copy_region(edns->opt_list_in, s->s.region))) - return 0; - if(edns->opt_list_out && !(r->edns.opt_list_out = - edns_opt_copy_region(edns->opt_list_out, s->s.region))) - return 0; - if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = - edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) - return 0; - r->qid = qid; - r->qflags = qflags; - r->next = s->cb_list; - s->cb_list = r; - return 1; - -} - -int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, - struct comm_reply* rep, uint16_t qid, uint16_t qflags, - const struct query_info* qinfo) -{ - struct mesh_reply* r = regional_alloc(s->s.region, - sizeof(struct mesh_reply)); - if(!r) - return 0; - r->query_reply = *rep; - r->edns = *edns; - if(edns->opt_list_in && !(r->edns.opt_list_in = - edns_opt_copy_region(edns->opt_list_in, s->s.region))) - return 0; - if(edns->opt_list_out && !(r->edns.opt_list_out = - edns_opt_copy_region(edns->opt_list_out, s->s.region))) - return 0; - if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = - edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) - return 0; - r->qid = qid; - r->qflags = qflags; - r->start_time = *s->s.env->now_tv; - r->next = s->reply_list; - r->qname = regional_alloc_init(s->s.region, qinfo->qname, - s->s.qinfo.qname_len); - if(!r->qname) - return 0; - if(rep->c->use_h2) - r->h2_stream = rep->c->h2_stream; - - /* Data related to local alias stored in 'qinfo' (if any) is ephemeral - * and can be different for different original queries (even if the - * replaced query name is the same). So we need to make a deep copy - * and store the copy for each reply info. */ - if(qinfo->local_alias) { - struct packed_rrset_data* d; - struct packed_rrset_data* dsrc; - r->local_alias = regional_alloc_zero(s->s.region, - sizeof(*qinfo->local_alias)); - if(!r->local_alias) - return 0; - r->local_alias->rrset = regional_alloc_init(s->s.region, - qinfo->local_alias->rrset, - sizeof(*qinfo->local_alias->rrset)); - if(!r->local_alias->rrset) - return 0; - dsrc = qinfo->local_alias->rrset->entry.data; - - /* In the current implementation, a local alias must be - * a single CNAME RR (see worker_handle_request()). */ - log_assert(!qinfo->local_alias->next && dsrc->count == 1 && - qinfo->local_alias->rrset->rk.type == - htons(LDNS_RR_TYPE_CNAME)); - /* we should make a local copy for the owner name of - * the RRset */ - r->local_alias->rrset->rk.dname_len = - qinfo->local_alias->rrset->rk.dname_len; - r->local_alias->rrset->rk.dname = regional_alloc_init( - s->s.region, qinfo->local_alias->rrset->rk.dname, - qinfo->local_alias->rrset->rk.dname_len); - if(!r->local_alias->rrset->rk.dname) - return 0; - - /* the rrset is not packed, like in the cache, but it is - * individually allocated with an allocator from localzone. */ - d = regional_alloc_zero(s->s.region, sizeof(*d)); - if(!d) - return 0; - r->local_alias->rrset->entry.data = d; - if(!rrset_insert_rr(s->s.region, d, dsrc->rr_data[0], - dsrc->rr_len[0], dsrc->rr_ttl[0], "CNAME local alias")) - return 0; - } else - r->local_alias = NULL; - - s->reply_list = r; - return 1; -} - -/* Extract the query info and flags from 'mstate' into '*qinfop' and '*qflags'. - * Since this is only used for internal refetch of otherwise-expired answer, - * we simply ignore the rare failure mode when memory allocation fails. */ -static void -mesh_copy_qinfo(struct mesh_state* mstate, struct query_info** qinfop, - uint16_t* qflags) -{ - struct regional* region = mstate->s.env->scratch; - struct query_info* qinfo; - - qinfo = regional_alloc_init(region, &mstate->s.qinfo, sizeof(*qinfo)); - if(!qinfo) - return; - qinfo->qname = regional_alloc_init(region, qinfo->qname, - qinfo->qname_len); - if(!qinfo->qname) - return; - *qinfop = qinfo; - *qflags = mstate->s.query_flags; -} - -/** - * Continue processing the mesh state at another module. - * Handles module to modules transfer of control. - * Handles module finished. - * @param mesh: the mesh area. - * @param mstate: currently active mesh state. - * Deleted if finished, calls _done and _supers to - * send replies to clients and inform other mesh states. - * This in turn may create additional runnable mesh states. - * @param s: state at which the current module exited. - * @param ev: the event sent to the module. - * returned is the event to send to the next module. - * @return true if continue processing at the new module. - * false if not continued processing is needed. - */ -static int -mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, - enum module_ext_state s, enum module_ev* ev) -{ - mstate->num_activated++; - if(mstate->num_activated > MESH_MAX_ACTIVATION) { - /* module is looping. Stop it. */ - log_err("internal error: looping module (%s) stopped", - mesh->mods.mod[mstate->s.curmod]->name); - log_query_info(NO_VERBOSE, "pass error for qstate", - &mstate->s.qinfo); - s = module_error; - } - if(s == module_wait_module || s == module_restart_next) { - /* start next module */ - mstate->s.curmod++; - if(mesh->mods.num == mstate->s.curmod) { - log_err("Cannot pass to next module; at last module"); - log_query_info(VERB_QUERY, "pass error for qstate", - &mstate->s.qinfo); - mstate->s.curmod--; - return mesh_continue(mesh, mstate, module_error, ev); - } - if(s == module_restart_next) { - int curmod = mstate->s.curmod; - for(; mstate->s.curmod < mesh->mods.num; - mstate->s.curmod++) { - fptr_ok(fptr_whitelist_mod_clear( - mesh->mods.mod[mstate->s.curmod]->clear)); - (*mesh->mods.mod[mstate->s.curmod]->clear) - (&mstate->s, mstate->s.curmod); - mstate->s.minfo[mstate->s.curmod] = NULL; - } - mstate->s.curmod = curmod; - } - *ev = module_event_pass; - return 1; - } - if(s == module_wait_subquery && mstate->sub_set.count == 0) { - log_err("module cannot wait for subquery, subquery list empty"); - log_query_info(VERB_QUERY, "pass error for qstate", - &mstate->s.qinfo); - s = module_error; - } - if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) { - /* error is bad, handle pass back up below */ - mstate->s.return_rcode = LDNS_RCODE_SERVFAIL; - } - if(s == module_error) { - mesh_query_done(mstate); - mesh_walk_supers(mesh, mstate); - mesh_state_delete(&mstate->s); - return 0; - } - if(s == module_finished) { - if(mstate->s.curmod == 0) { - struct query_info* qinfo = NULL; - struct edns_option* opt_list = NULL; - struct sockaddr_storage addr; - uint16_t qflags; - int rpz_p = 0; - -#ifdef CLIENT_SUBNET - struct edns_option* ecs; - if(mstate->s.need_refetch && mstate->reply_list && - modstack_find(&mesh->mods, "subnetcache") != -1 && - mstate->s.env->unique_mesh) { - addr = mstate->reply_list->query_reply.client_addr; - } else -#endif - memset(&addr, 0, sizeof(addr)); - - mesh_query_done(mstate); - mesh_walk_supers(mesh, mstate); - - /* If the answer to the query needs to be refetched - * from an external DNS server, we'll need to schedule - * a prefetch after removing the current state, so - * we need to make a copy of the query info here. */ - if(mstate->s.need_refetch) { - mesh_copy_qinfo(mstate, &qinfo, &qflags); -#ifdef CLIENT_SUBNET - /* Make also a copy of the ecs option if any */ - if((ecs = edns_opt_list_find( - mstate->s.edns_opts_front_in, - mstate->s.env->cfg->client_subnet_opcode)) != NULL) { - (void)edns_opt_list_append(&opt_list, - ecs->opt_code, ecs->opt_len, - ecs->opt_data, - mstate->s.env->scratch); - } -#endif - rpz_p = mstate->s.rpz_passthru; - } - - if(qinfo) { - mesh_state_delete(&mstate->s); - mesh_new_prefetch(mesh, qinfo, qflags, 0, - rpz_p, - addr.ss_family!=AF_UNSPEC?&addr:NULL, - opt_list); - } else { - mesh_state_delete(&mstate->s); - } - return 0; - } - /* pass along the locus of control */ - mstate->s.curmod --; - *ev = module_event_moddone; - return 1; - } - return 0; -} - -void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, - enum module_ev ev, struct outbound_entry* e) -{ - enum module_ext_state s; - verbose(VERB_ALGO, "mesh_run: start"); - while(mstate) { - /* run the module */ - fptr_ok(fptr_whitelist_mod_operate( - mesh->mods.mod[mstate->s.curmod]->operate)); - (*mesh->mods.mod[mstate->s.curmod]->operate) - (&mstate->s, ev, mstate->s.curmod, e); - - /* examine results */ - mstate->s.reply = NULL; - regional_free_all(mstate->s.env->scratch); - s = mstate->s.ext_state[mstate->s.curmod]; - verbose(VERB_ALGO, "mesh_run: %s module exit state is %s", - mesh->mods.mod[mstate->s.curmod]->name, strextstate(s)); - e = NULL; - if(mesh_continue(mesh, mstate, s, &ev)) - continue; - - /* run more modules */ - ev = module_event_pass; - if(mesh->run.count > 0) { - /* pop random element off the runnable tree */ - mstate = (struct mesh_state*)mesh->run.root->key; - (void)rbtree_delete(&mesh->run, mstate); - } else mstate = NULL; - } - if(verbosity >= VERB_ALGO) { - mesh_stats(mesh, "mesh_run: end"); - mesh_log_list(mesh); - } -} - -void -mesh_log_list(struct mesh_area* mesh) -{ - char buf[30]; - struct mesh_state* m; - int num = 0; - RBTREE_FOR(m, struct mesh_state*, &mesh->all) { - snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s", - num++, (m->s.is_priming)?"p":"", /* prime */ - (m->s.is_valrec)?"v":"", /* prime */ - (m->s.query_flags&BIT_RD)?"RD":"", - (m->s.query_flags&BIT_CD)?"CD":"", - (m->super_set.count==0)?"d":"", /* detached */ - (m->sub_set.count!=0)?"c":"", /* children */ - m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/ - (m->cb_list)?"cb":"" /* callbacks */ - ); - log_query_info(VERB_ALGO, buf, &m->s.qinfo); - } -} - -void -mesh_stats(struct mesh_area* mesh, const char* str) -{ - verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, " - "%u detached), %u waiting replies, %u recursion replies " - "sent, %d replies dropped, %d states jostled out", - str, (unsigned)mesh->all.count, - (unsigned)mesh->num_reply_states, - (unsigned)mesh->num_detached_states, - (unsigned)mesh->num_reply_addrs, - (unsigned)mesh->replies_sent, - (unsigned)mesh->stats_dropped, - (unsigned)mesh->stats_jostled); - if(mesh->replies_sent > 0) { - struct timeval avg; - timeval_divide(&avg, &mesh->replies_sum_wait, - mesh->replies_sent); - log_info("average recursion processing time " - ARG_LL "d.%6.6d sec", - (long long)avg.tv_sec, (int)avg.tv_usec); - log_info("histogram of recursion processing times"); - timehist_log(mesh->histogram, "recursions"); - } -} - -void -mesh_stats_clear(struct mesh_area* mesh) -{ - if(!mesh) - return; - mesh->replies_sent = 0; - mesh->replies_sum_wait.tv_sec = 0; - mesh->replies_sum_wait.tv_usec = 0; - mesh->stats_jostled = 0; - mesh->stats_dropped = 0; - timehist_clear(mesh->histogram); - mesh->ans_secure = 0; - mesh->ans_bogus = 0; - mesh->ans_expired = 0; - mesh->ans_cachedb = 0; - memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM); - memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM); - mesh->ans_nodata = 0; -} - -size_t -mesh_get_mem(struct mesh_area* mesh) -{ - struct mesh_state* m; - size_t s = sizeof(*mesh) + sizeof(struct timehist) + - sizeof(struct th_buck)*mesh->histogram->num + - sizeof(sldns_buffer) + sldns_buffer_capacity(mesh->qbuf_bak); - RBTREE_FOR(m, struct mesh_state*, &mesh->all) { - /* all, including m itself allocated in qstate region */ - s += regional_get_mem(m->s.region); - } - return s; -} - -int -mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t flags, int prime, int valrec) -{ - struct mesh_area* mesh = qstate->env->mesh; - struct mesh_state* dep_m = NULL; - dep_m = mesh_area_find(mesh, NULL, qinfo, flags, prime, valrec); - return mesh_detect_cycle_found(qstate, dep_m); -} - -void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, - struct mesh_state** lp) -{ - /* insert as last element */ - m->prev = *lp; - m->next = NULL; - if(*lp) - (*lp)->next = m; - else *fp = m; - *lp = m; -} - -void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, - struct mesh_state** lp) -{ - if(m->next) - m->next->prev = m->prev; - else *lp = m->prev; - if(m->prev) - m->prev->next = m->next; - else *fp = m->next; -} - -void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp) -{ - struct mesh_reply* n, *prev = NULL; - n = m->reply_list; - /* when in mesh_cleanup, it sets the reply_list to NULL, so that - * there is no accounting twice */ - if(!n) return; /* nothing to remove, also no accounting needed */ - while(n) { - if(n->query_reply.c == cp) { - /* unlink it */ - if(prev) prev->next = n->next; - else m->reply_list = n->next; - /* delete it, but allocated in m region */ - log_assert(mesh->num_reply_addrs > 0); - mesh->num_reply_addrs--; - - /* prev = prev; */ - n = n->next; - continue; - } - prev = n; - n = n->next; - } - /* it was not detached (because it had a reply list), could be now */ - if(!m->reply_list && !m->cb_list - && m->super_set.count == 0) { - mesh->num_detached_states++; - } - /* if not replies any more in mstate, it is no longer a reply_state */ - if(!m->reply_list && !m->cb_list) { - log_assert(mesh->num_reply_states > 0); - mesh->num_reply_states--; - } -} - - -static int -apply_respip_action(struct module_qstate* qstate, - const struct query_info* qinfo, struct respip_client_info* cinfo, - struct respip_action_info* actinfo, struct reply_info* rep, - struct ub_packed_rrset_key** alias_rrset, - struct reply_info** encode_repp, struct auth_zones* az) -{ - if(qinfo->qtype != LDNS_RR_TYPE_A && - qinfo->qtype != LDNS_RR_TYPE_AAAA && - qinfo->qtype != LDNS_RR_TYPE_ANY) - return 1; - - if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo, - alias_rrset, 0, qstate->region, az, NULL)) - return 0; - - /* xxx_deny actions mean dropping the reply, unless the original reply - * was redirected to response-ip data. */ - if((actinfo->action == respip_deny || - actinfo->action == respip_inform_deny) && - *encode_repp == rep) - *encode_repp = NULL; - - return 1; -} - -void -mesh_serve_expired_callback(void* arg) -{ - struct mesh_state* mstate = (struct mesh_state*) arg; - struct module_qstate* qstate = &mstate->s; - struct mesh_reply* r; - struct mesh_area* mesh = qstate->env->mesh; - struct dns_msg* msg; - struct mesh_cb* c; - struct mesh_reply* prev = NULL; - struct sldns_buffer* prev_buffer = NULL; - struct sldns_buffer* r_buffer = NULL; - struct reply_info* partial_rep = NULL; - struct ub_packed_rrset_key* alias_rrset = NULL; - struct reply_info* encode_rep = NULL; - struct respip_action_info actinfo; - struct query_info* lookup_qinfo = &qstate->qinfo; - struct query_info qinfo_tmp; - struct timeval tv = {0, 0}; - int must_validate = (!(qstate->query_flags&BIT_CD) - || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate; - int i = 0; - if(!qstate->serve_expired_data) return; - verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data"); - comm_timer_delete(qstate->serve_expired_data->timer); - qstate->serve_expired_data->timer = NULL; - /* If is_drop or no_cache_lookup (modules that handle their own cache e.g., - * subnetmod) ignore stale data from the main cache. */ - if(qstate->no_cache_lookup || qstate->is_drop) { - verbose(VERB_ALGO, - "Serve expired: Not allowed to look into cache for stale"); - return; - } - /* The following while is used instead of the `goto lookup_cache` - * like in the worker. */ - while(1) { - fptr_ok(fptr_whitelist_serve_expired_lookup( - qstate->serve_expired_data->get_cached_answer)); - msg = (*qstate->serve_expired_data->get_cached_answer)(qstate, - lookup_qinfo); - if(!msg) - return; - /* Reset these in case we pass a second time from here. */ - encode_rep = msg->rep; - memset(&actinfo, 0, sizeof(actinfo)); - actinfo.action = respip_none; - alias_rrset = NULL; - if((mesh->use_response_ip || mesh->use_rpz) && - !partial_rep && !apply_respip_action(qstate, &qstate->qinfo, - qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep, - qstate->env->auth_zones)) { - return; - } else if(partial_rep && - !respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep, - qstate->client_info, must_validate, &encode_rep, qstate->region, - qstate->env->auth_zones)) { - return; - } - if(!encode_rep || alias_rrset) { - if(!encode_rep) { - /* Needs drop */ - return; - } else { - /* A partial CNAME chain is found. */ - partial_rep = encode_rep; - } - } - /* We've found a partial reply ending with an - * alias. Replace the lookup qinfo for the - * alias target and lookup the cache again to - * (possibly) complete the reply. As we're - * passing the "base" reply, there will be no - * more alias chasing. */ - if(partial_rep) { - memset(&qinfo_tmp, 0, sizeof(qinfo_tmp)); - get_cname_target(alias_rrset, &qinfo_tmp.qname, - &qinfo_tmp.qname_len); - if(!qinfo_tmp.qname) { - log_err("Serve expired: unexpected: invalid answer alias"); - return; - } - qinfo_tmp.qtype = qstate->qinfo.qtype; - qinfo_tmp.qclass = qstate->qinfo.qclass; - lookup_qinfo = &qinfo_tmp; - continue; - } - break; - } - - if(verbosity >= VERB_ALGO) - log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep); - - for(r = mstate->reply_list; r; r = r->next) { - i++; - tv = r->start_time; - - /* If address info is returned, it means the action should be an - * 'inform' variant and the information should be logged. */ - if(actinfo.addrinfo) { - respip_inform_print(&actinfo, r->qname, - qstate->qinfo.qtype, qstate->qinfo.qclass, - r->local_alias, &r->query_reply.client_addr, - r->query_reply.client_addrlen); - } - - /* Add EDE Stale Answer (RCF8914). Ignore global ede as this is - * warning instead of an error */ - if (r->edns.edns_present && qstate->env->cfg->ede_serve_expired && - qstate->env->cfg->ede) { - edns_opt_list_append_ede(&r->edns.opt_list_out, - mstate->s.region, LDNS_EDE_STALE_ANSWER, NULL); - } - - r_buffer = r->query_reply.c->buffer; - if(r->query_reply.c->tcp_req_info) - r_buffer = r->query_reply.c->tcp_req_info->spool_buffer; - mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep, - r, r_buffer, prev, prev_buffer); - if(r->query_reply.c->tcp_req_info) - tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate); - prev = r; - prev_buffer = r_buffer; - } - /* Account for each reply sent. */ - if(i > 0) { - mesh->ans_expired += i; - if(actinfo.addrinfo && qstate->env->cfg->stat_extended && - actinfo.rpz_used) { - if(actinfo.rpz_disabled) - qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i; - if(actinfo.rpz_cname_override) - qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i; - else - qstate->env->mesh->rpz_action[ - respip_action_to_rpz_action(actinfo.action)] += i; - } - } - - /* Mesh area accounting */ - if(mstate->reply_list) { - mstate->reply_list = NULL; - if(!mstate->reply_list && !mstate->cb_list) { - log_assert(mesh->num_reply_states > 0); - mesh->num_reply_states--; - if(mstate->super_set.count == 0) { - mesh->num_detached_states++; - } - } - } - - while((c = mstate->cb_list) != NULL) { - /* take this cb off the list; so that the list can be - * changed, eg. by adds from the callback routine */ - if(!mstate->reply_list && mstate->cb_list && !c->next) { - /* was a reply state, not anymore */ - log_assert(qstate->env->mesh->num_reply_states > 0); - qstate->env->mesh->num_reply_states--; - } - mstate->cb_list = c->next; - if(!mstate->reply_list && !mstate->cb_list && - mstate->super_set.count == 0) - qstate->env->mesh->num_detached_states++; - mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c, &tv); - } -} - -int mesh_jostle_exceeded(struct mesh_area* mesh) -{ - if(mesh->all.count < mesh->max_reply_states) - return 0; - return 1; -} diff --git a/crates/libunbound-sys/unbound/services/mesh.h b/crates/libunbound-sys/unbound/services/mesh.h deleted file mode 100644 index d926cfc9..00000000 --- a/crates/libunbound-sys/unbound/services/mesh.h +++ /dev/null @@ -1,693 +0,0 @@ -/* - * services/mesh.h - deal with mesh of query states and handle events for that. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to assist in dealing with a mesh of - * query states. This mesh is supposed to be thread-specific. - * It consists of query states (per qname, qtype, qclass) and connections - * between query states and the super and subquery states, and replies to - * send back to clients. - */ - -#ifndef SERVICES_MESH_H -#define SERVICES_MESH_H - -#include "util/rbtree.h" -#include "util/netevent.h" -#include "util/data/msgparse.h" -#include "util/module.h" -#include "services/modstack.h" -#include "services/rpz.h" -#include "libunbound/unbound.h" -struct sldns_buffer; -struct mesh_state; -struct mesh_reply; -struct mesh_cb; -struct query_info; -struct reply_info; -struct outbound_entry; -struct timehist; -struct respip_client_info; - -/** - * Maximum number of mesh state activations. Any more is likely an - * infinite loop in the module. It is then terminated. - */ -#define MESH_MAX_ACTIVATION 10000 - -/** - * Max number of references-to-references-to-references.. search size. - * Any more is treated like 'too large', and the creation of a new - * dependency is failed (so that no loops can be created). - */ -#define MESH_MAX_SUBSUB 1024 - -/** - * Mesh of query states - */ -struct mesh_area { - /** active module stack */ - struct module_stack mods; - /** environment for new states */ - struct module_env* env; - - /** set of runnable queries (mesh_state.run_node) */ - rbtree_type run; - /** rbtree of all current queries (mesh_state.node)*/ - rbtree_type all; - - /** count of the total number of mesh_reply entries */ - size_t num_reply_addrs; - /** count of the number of mesh_states that have mesh_replies - * Because a state can send results to multiple reply addresses, - * this number must be equal or lower than num_reply_addrs. */ - size_t num_reply_states; - /** number of mesh_states that have no mesh_replies, and also - * an empty set of super-states, thus are 'toplevel' or detached - * internal opportunistic queries */ - size_t num_detached_states; - /** number of reply states in the forever list */ - size_t num_forever_states; - - /** max total number of reply states to have */ - size_t max_reply_states; - /** max forever number of reply states to have */ - size_t max_forever_states; - - /** stats, cumulative number of reply states jostled out */ - size_t stats_jostled; - /** stats, cumulative number of incoming client msgs dropped */ - size_t stats_dropped; - /** stats, number of expired replies sent */ - size_t ans_expired; - /** stats, number of cached replies from cachedb */ - size_t ans_cachedb; - /** number of replies sent */ - size_t replies_sent; - /** sum of waiting times for the replies */ - struct timeval replies_sum_wait; - /** histogram of time values */ - struct timehist* histogram; - /** (extended stats) secure replies */ - size_t ans_secure; - /** (extended stats) bogus replies */ - size_t ans_bogus; - /** (extended stats) rcodes in replies */ - size_t ans_rcode[UB_STATS_RCODE_NUM]; - /** (extended stats) rcode nodata in replies */ - size_t ans_nodata; - /** (extended stats) type of applied RPZ action */ - size_t rpz_action[UB_STATS_RPZ_ACTION_NUM]; - - /** backup of query if other operations recurse and need the - * network buffers */ - struct sldns_buffer* qbuf_bak; - - /** double linked list of the run-to-completion query states. - * These are query states with a reply */ - struct mesh_state* forever_first; - /** last entry in run forever list */ - struct mesh_state* forever_last; - - /** double linked list of the query states that can be jostled out - * by new queries if too old. These are query states with a reply */ - struct mesh_state* jostle_first; - /** last entry in jostle list - this is the entry that is newest */ - struct mesh_state* jostle_last; - /** timeout for jostling. if age is lower, it does not get jostled. */ - struct timeval jostle_max; - - /** If we need to use response ip (value passed from daemon)*/ - int use_response_ip; - /** If we need to use RPZ (value passed from daemon) */ - int use_rpz; -}; - -/** - * A mesh query state - * Unique per qname, qtype, qclass (from the qstate). - * And RD / CD flag; in case a client turns it off. - * And priming queries are different from ordinary queries (because of hints). - * - * The entire structure is allocated in a region, this region is the qstate - * region. All parts (rbtree nodes etc) are also allocated in the region. - */ -struct mesh_state { - /** node in mesh_area all tree, key is this struct. Must be first. */ - rbnode_type node; - /** node in mesh_area runnable tree, key is this struct */ - rbnode_type run_node; - /** the query state. Note that the qinfo and query_flags - * may not change. */ - struct module_qstate s; - /** the list of replies to clients for the results */ - struct mesh_reply* reply_list; - /** the list of callbacks for the results */ - struct mesh_cb* cb_list; - /** set of superstates (that want this state's result) - * contains struct mesh_state_ref* */ - rbtree_type super_set; - /** set of substates (that this state needs to continue) - * contains struct mesh_state_ref* */ - rbtree_type sub_set; - /** number of activations for the mesh state */ - size_t num_activated; - - /** previous in linked list for reply states */ - struct mesh_state* prev; - /** next in linked list for reply states */ - struct mesh_state* next; - /** if this state is in the forever list, jostle list, or neither */ - enum mesh_list_select { mesh_no_list, mesh_forever_list, - mesh_jostle_list } list_select; - /** pointer to this state for uniqueness or NULL */ - struct mesh_state* unique; - - /** true if replies have been sent out (at end for alignment) */ - uint8_t replies_sent; -}; - -/** - * Rbtree reference to a mesh_state. - * Used in super_set and sub_set. - */ -struct mesh_state_ref { - /** node in rbtree for set, key is this structure */ - rbnode_type node; - /** the mesh state */ - struct mesh_state* s; -}; - -/** - * Reply to a client - */ -struct mesh_reply { - /** next in reply list */ - struct mesh_reply* next; - /** the query reply destination, packet buffer and where to send. */ - struct comm_reply query_reply; - /** edns data from query */ - struct edns_data edns; - /** the time when request was entered */ - struct timeval start_time; - /** id of query, in network byteorder. */ - uint16_t qid; - /** flags of query, for reply flags */ - uint16_t qflags; - /** qname from this query. len same as mesh qinfo. */ - uint8_t* qname; - /** same as that in query_info. */ - struct local_rrset* local_alias; - /** send query to this http2 stream, if set */ - struct http2_stream* h2_stream; -}; - -/** - * Mesh result callback func. - * called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus, - * was_ratelimited); - */ -typedef void (*mesh_cb_func_type)(void* cb_arg, int rcode, struct sldns_buffer*, - enum sec_status, char* why_bogus, int was_ratelimited); - -/** - * Callback to result routine - */ -struct mesh_cb { - /** next in list */ - struct mesh_cb* next; - /** edns data from query */ - struct edns_data edns; - /** id of query, in network byteorder. */ - uint16_t qid; - /** flags of query, for reply flags */ - uint16_t qflags; - /** buffer for reply */ - struct sldns_buffer* buf; - /** callback routine for results. if rcode != 0 buf has message. - * called as cb(cb_arg, rcode, buf, sec_state, why_bogus, was_ratelimited); - */ - mesh_cb_func_type cb; - /** user arg for callback */ - void* cb_arg; -}; - -/* ------------------- Functions for worker -------------------- */ - -/** - * Allocate mesh, to empty. - * @param stack: module stack to activate, copied (as readonly reference). - * @param env: environment for new queries. - * @return mesh: the new mesh or NULL on error. - */ -struct mesh_area* mesh_create(struct module_stack* stack, - struct module_env* env); - -/** - * Delete mesh, and all query states and replies in it. - * @param mesh: the mesh to delete. - */ -void mesh_delete(struct mesh_area* mesh); - -/** - * New query incoming from clients. Create new query state if needed, and - * add mesh_reply to it. Returns error to client on malloc failures. - * Will run the mesh area queries to process if a new query state is created. - * - * @param mesh: the mesh. - * @param qinfo: query from client. - * @param cinfo: additional information associated with the query client. - * 'cinfo' itself is ephemeral but data pointed to by its members - * can be assumed to be valid and unchanged until the query processing is - * completed. - * @param qflags: flags from client query. - * @param edns: edns data from client query. - * @param rep: where to reply to. - * @param qid: query id to reply with. - * @param rpz_passthru: if true, the rpz passthru was previously found and - * further rpz processing is stopped. - */ -void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, - struct respip_client_info* cinfo, uint16_t qflags, - struct edns_data* edns, struct comm_reply* rep, uint16_t qid, - int rpz_passthru); - -/** - * New query with callback. Create new query state if needed, and - * add mesh_cb to it. - * Will run the mesh area queries to process if a new query state is created. - * - * @param mesh: the mesh. - * @param qinfo: query from client. - * @param qflags: flags from client query. - * @param edns: edns data from client query. - * @param buf: buffer for reply contents. - * @param qid: query id to reply with. - * @param cb: callback function. - * @param cb_arg: callback user arg. - * @param rpz_passthru: if true, the rpz passthru was previously found and - * further rpz processing is stopped. - * @return 0 on error. - */ -int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf, - uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru); - -/** - * New prefetch message. Create new query state if needed. - * Will run the mesh area queries to process if a new query state is created. - * - * @param mesh: the mesh. - * @param qinfo: query from client. - * @param qflags: flags from client query. - * @param leeway: TTL leeway what to expire earlier for this update. - * @param rpz_passthru: if true, the rpz passthru was previously found and - * further rpz processing is stopped. - * @param addr: sockaddr_storage for the client; to be used with subnet. - * @param opt_list: edns opt_list from the client; to be used when subnet is - * enabled. - */ -void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, time_t leeway, int rpz_passthru, - struct sockaddr_storage* addr, struct edns_option* opt_list); - -/** - * Handle new event from the wire. A serviced query has returned. - * The query state will be made runnable, and the mesh_area will process - * query states until processing is complete. - * - * @param mesh: the query mesh. - * @param e: outbound entry, with query state to run and reply pointer. - * @param reply: the comm point reply info. - * @param what: NETEVENT_* error code (if not 0, what is wrong, TIMEOUT). - */ -void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, - struct comm_reply* reply, int what); - -/* ------------------- Functions for module environment --------------- */ - -/** - * Detach-subqueries. - * Remove all sub-query references from this query state. - * Keeps super-references of those sub-queries correct. - * Updates stat items in mesh_area structure. - * @param qstate: used to find mesh state. - */ -void mesh_detach_subs(struct module_qstate* qstate); - -/** - * Attach subquery. - * Creates it if it does not exist already. - * Keeps sub and super references correct. - * Performs a cycle detection - for double check - and fails if there is one. - * Also fails if the sub-sub-references become too large. - * Updates stat items in mesh_area structure. - * Pass if it is priming query or not. - * return: - * o if error (malloc) happened. - * o need to initialise the new state (module init; it is a new state). - * so that the next run of the query with this module is successful. - * o no init needed, attachment successful. - * - * @param qstate: the state to find mesh state, and that wants to receive - * the results from the new subquery. - * @param qinfo: what to query for (copied). - * @param qflags: what flags to use (RD / CD flag or not). - * @param prime: if it is a (stub) priming query. - * @param valrec: if it is a validation recursion query (lookup of key, DS). - * @param newq: If the new subquery needs initialisation, it is returned, - * otherwise NULL is returned. - * @return: false on error, true if success (and init may be needed). - */ -int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq); - -/** - * Add detached query. - * Creates it if it does not exist already. - * Does not make super/sub references. - * Performs a cycle detection - for double check - and fails if there is one. - * Updates stat items in mesh_area structure. - * Pass if it is priming query or not. - * return: - * o if error (malloc) happened. - * o need to initialise the new state (module init; it is a new state). - * so that the next run of the query with this module is successful. - * o no init needed, attachment successful. - * o added subquery, created if it did not exist already. - * - * @param qstate: the state to find mesh state, and that wants to receive - * the results from the new subquery. - * @param qinfo: what to query for (copied). - * @param qflags: what flags to use (RD / CD flag or not). - * @param prime: if it is a (stub) priming query. - * @param valrec: if it is a validation recursion query (lookup of key, DS). - * @param newq: If the new subquery needs initialisation, it is returned, - * otherwise NULL is returned. - * @param sub: The added mesh state, created if it did not exist already. - * @return: false on error, true if success (and init may be needed). - */ -int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub); - -/** - * Query state is done, send messages to reply entries. - * Encode messages using reply entry values and the querystate (with original - * qinfo), using given reply_info. - * Pass errcode != 0 if an error reply is needed. - * If no reply entries, nothing is done. - * Must be called before a module can module_finished or return module_error. - * The module must handle the super query states itself as well. - * - * @param mstate: mesh state that is done. return_rcode and return_msg - * are used for replies. - * return_rcode: if not 0 (NOERROR) an error is sent back (and - * return_msg is ignored). - * return_msg: reply to encode and send back to clients. - */ -void mesh_query_done(struct mesh_state* mstate); - -/** - * Call inform_super for the super query states that are interested in the - * results from this query state. These can then be changed for error - * or results. - * Called when a module is module_finished or returns module_error. - * The super query states become runnable with event module_event_pass, - * it calls the current module for the super with the inform_super event. - * - * @param mesh: mesh area to add newly runnable modules to. - * @param mstate: the state that has results, used to find mesh state. - */ -void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate); - -/** - * Delete mesh state, cleanup and also rbtrees and so on. - * Will detach from all super/subnodes. - * @param qstate: to remove. - */ -void mesh_state_delete(struct module_qstate* qstate); - -/* ------------------- Functions for mesh -------------------- */ - -/** - * Create and initialize a new mesh state and its query state - * Does not put the mesh state into rbtrees and so on. - * @param env: module environment to set. - * @param qinfo: query info that the mesh is for. - * @param cinfo: control info for the query client (can be NULL). - * @param qflags: flags for query (RD / CD flag). - * @param prime: if true, it is a priming query, set is_priming on mesh state. - * @param valrec: if true, it is a validation recursion query, and sets - * is_valrec on the mesh state. - * @return: new mesh state or NULL on allocation error. - */ -struct mesh_state* mesh_state_create(struct module_env* env, - struct query_info* qinfo, struct respip_client_info* cinfo, - uint16_t qflags, int prime, int valrec); - -/** - * Make a mesh state unique. - * A unique mesh state uses it's unique member to point to itself. - * @param mstate: mesh state to check. - */ -void mesh_state_make_unique(struct mesh_state* mstate); - -/** - * Cleanup a mesh state and its query state. Does not do rbtree or - * reference cleanup. - * @param mstate: mesh state to cleanup. Its pointer may no longer be used - * afterwards. Cleanup rbtrees before calling this function. - */ -void mesh_state_cleanup(struct mesh_state* mstate); - -/** - * Delete all mesh states from the mesh. - * @param mesh: the mesh area to clear - */ -void mesh_delete_all(struct mesh_area* mesh); - -/** - * Find a mesh state in the mesh area. Pass relevant flags. - * - * @param mesh: the mesh area to look in. - * @param cinfo: if non-NULL client specific info that may affect IP-based - * actions that apply to the query result. - * @param qinfo: what query - * @param qflags: if RD / CD bit is set or not. - * @param prime: if it is a priming query. - * @param valrec: if it is a validation-recursion query. - * @return: mesh state or NULL if not found. - */ -struct mesh_state* mesh_area_find(struct mesh_area* mesh, - struct respip_client_info* cinfo, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec); - -/** - * Setup attachment super/sub relation between super and sub mesh state. - * The relation must not be present when calling the function. - * Does not update stat items in mesh_area. - * @param super: super state. - * @param sub: sub state. - * @return: 0 on alloc error. - */ -int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub); - -/** - * Create new reply structure and attach it to a mesh state. - * Does not update stat items in mesh area. - * @param s: the mesh state. - * @param edns: edns data for reply (bufsize). - * @param rep: comm point reply info. - * @param qid: ID of reply. - * @param qflags: original query flags. - * @param qinfo: original query info. - * @return: 0 on alloc error. - */ -int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, - struct comm_reply* rep, uint16_t qid, uint16_t qflags, - const struct query_info* qinfo); - -/** - * Create new callback structure and attach it to a mesh state. - * Does not update stat items in mesh area. - * @param s: the mesh state. - * @param edns: edns data for reply (bufsize). - * @param buf: buffer for reply - * @param cb: callback to call with results. - * @param cb_arg: callback user arg. - * @param qid: ID of reply. - * @param qflags: original query flags. - * @return: 0 on alloc error. - */ -int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, - struct sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg, - uint16_t qid, uint16_t qflags); - -/** - * Run the mesh. Run all runnable mesh states. Which can create new - * runnable mesh states. Until completion. Automatically called by - * mesh_report_reply and mesh_new_client as needed. - * @param mesh: mesh area. - * @param mstate: first mesh state to run. - * @param ev: event the mstate. Others get event_pass. - * @param e: if a reply, its outbound entry. - */ -void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, - enum module_ev ev, struct outbound_entry* e); - -/** - * Print some stats about the mesh to the log. - * @param mesh: the mesh to print it for. - * @param str: descriptive string to go with it. - */ -void mesh_stats(struct mesh_area* mesh, const char* str); - -/** - * Clear the stats that the mesh keeps (number of queries serviced) - * @param mesh: the mesh - */ -void mesh_stats_clear(struct mesh_area* mesh); - -/** - * Print all the states in the mesh to the log. - * @param mesh: the mesh to print all states of. - */ -void mesh_log_list(struct mesh_area* mesh); - -/** - * Calculate memory size in use by mesh and all queries inside it. - * @param mesh: the mesh to examine. - * @return size in bytes. - */ -size_t mesh_get_mem(struct mesh_area* mesh); - -/** - * Find cycle; see if the given mesh is in the targets sub, or sub-sub, ... - * trees. - * If the sub-sub structure is too large, it returns 'a cycle'=2. - * @param qstate: given mesh querystate. - * @param qinfo: query info for dependency. - * @param flags: query flags of dependency. - * @param prime: if dependency is a priming query or not. - * @param valrec: if it is a validation recursion query (lookup of key, DS). - * @return true if the name,type,class exists and the given qstate mesh exists - * as a dependency of that name. Thus if qstate becomes dependent on - * name,type,class then a cycle is created, this is return value 1. - * Too large to search is value 2 (also true). - */ -int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t flags, int prime, int valrec); - -/** compare two mesh_states */ -int mesh_state_compare(const void* ap, const void* bp); - -/** compare two mesh references */ -int mesh_state_ref_compare(const void* ap, const void* bp); - -/** - * Make space for another recursion state for a reply in the mesh - * @param mesh: mesh area - * @param qbuf: query buffer to save if recursion is invoked to make space. - * This buffer is necessary, because the following sequence in calls - * can result in an overwrite of the incoming query: - * delete_other_mesh_query - iter_clean - serviced_delete - waiting - * udp query is sent - on error callback - callback sends SERVFAIL reply - * over the same network channel, and shared UDP buffer is overwritten. - * You can pass NULL if there is no buffer that must be backed up. - * @return false if no space is available. - */ -int mesh_make_new_space(struct mesh_area* mesh, struct sldns_buffer* qbuf); - -/** - * Insert mesh state into a double linked list. Inserted at end. - * @param m: mesh state. - * @param fp: pointer to the first-elem-pointer of the list. - * @param lp: pointer to the last-elem-pointer of the list. - */ -void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, - struct mesh_state** lp); - -/** - * Remove mesh state from a double linked list. Remove from any position. - * @param m: mesh state. - * @param fp: pointer to the first-elem-pointer of the list. - * @param lp: pointer to the last-elem-pointer of the list. - */ -void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, - struct mesh_state** lp); - -/** - * Remove mesh reply entry from the reply entry list. Searches for - * the comm_point pointer. - * @param mesh: to update the counters. - * @param m: the mesh state. - * @param cp: the comm_point to remove from the list. - */ -void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, - struct comm_point* cp); - -/** Callback for when the serve expired client timer has run out. Tries to - * find an expired answer in the cache and reply that to the client. - * @param arg: the argument passed to the callback. - */ -void mesh_serve_expired_callback(void* arg); - -/** - * Try to get a (expired) cached answer. - * This needs to behave like the worker's answer_from_cache() in order to have - * the same behavior as when replying from cache. - * @param qstate: the module qstate. - * @param lookup_qinfo: the query info to look for in the cache. - * @return dns_msg if a cached answer was found, otherwise NULL. - */ -struct dns_msg* -mesh_serve_expired_lookup(struct module_qstate* qstate, - struct query_info* lookup_qinfo); - -/** - * See if the mesh has space for more queries. You can allocate queries - * anyway, but this checks for the allocated space. - * @param mesh: mesh area. - * @return true if the query list is full. - * It checks the number of all queries, not just number of reply states, - * that have a client address. So that spawned queries count too, - * that were created by the iterator, or other modules. - */ -int mesh_jostle_exceeded(struct mesh_area* mesh); - -#endif /* SERVICES_MESH_H */ diff --git a/crates/libunbound-sys/unbound/services/modstack.c b/crates/libunbound-sys/unbound/services/modstack.c deleted file mode 100644 index a90d7178..00000000 --- a/crates/libunbound-sys/unbound/services/modstack.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * services/modstack.c - stack of modules - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to help maintain a stack of modules. - */ -#include "config.h" -#include -#include "services/modstack.h" -#include "util/module.h" -#include "util/fptr_wlist.h" -#include "dns64/dns64.h" -#include "iterator/iterator.h" -#include "validator/validator.h" -#include "respip/respip.h" - -#ifdef WITH_PYTHONMODULE -#include "pythonmod/pythonmod.h" -#endif -#ifdef WITH_DYNLIBMODULE -#include "dynlibmod/dynlibmod.h" -#endif -#ifdef USE_CACHEDB -#include "cachedb/cachedb.h" -#endif -#ifdef USE_IPSECMOD -#include "ipsecmod/ipsecmod.h" -#endif -#ifdef CLIENT_SUBNET -#include "edns-subnet/subnetmod.h" -#endif -#ifdef USE_IPSET -#include "ipset/ipset.h" -#endif - -/** count number of modules (words) in the string */ -static int -count_modules(const char* s) -{ - int num = 0; - if(!s) - return 0; - while(*s) { - /* skip whitespace */ - while(*s && isspace((unsigned char)*s)) - s++; - if(*s && !isspace((unsigned char)*s)) { - /* skip identifier */ - num++; - while(*s && !isspace((unsigned char)*s)) - s++; - } - } - return num; -} - -void -modstack_init(struct module_stack* stack) -{ - stack->num = 0; - stack->mod = NULL; -} - -int -modstack_config(struct module_stack* stack, const char* module_conf) -{ - int i; - verbose(VERB_QUERY, "module config: \"%s\"", module_conf); - stack->num = count_modules(module_conf); - if(stack->num == 0) { - log_err("error: no modules specified"); - return 0; - } - if(stack->num > MAX_MODULE) { - log_err("error: too many modules (%d max %d)", - stack->num, MAX_MODULE); - return 0; - } - stack->mod = (struct module_func_block**)calloc((size_t) - stack->num, sizeof(struct module_func_block*)); - if(!stack->mod) { - log_err("out of memory"); - return 0; - } - for(i=0; inum; i++) { - stack->mod[i] = module_factory(&module_conf); - if(!stack->mod[i]) { - char md[256]; - char * s = md; - snprintf(md, sizeof(md), "%s", module_conf); - /* Leading spaces are present on errors. */ - while (*s && isspace((unsigned char)*s)) - s++; - if(strchr(s, ' ')) *(strchr(s, ' ')) = 0; - if(strchr(s, '\t')) *(strchr(s, '\t')) = 0; - log_err("Unknown value in module-config, module: '%s'." - " This module is not present (not compiled in)," - " See the list of linked modules with unbound -V", s); - return 0; - } - } - return 1; -} - -/** The list of module names */ -const char** -module_list_avail(void) -{ - /* these are the modules available */ - static const char* names[] = { - "dns64", -#ifdef WITH_PYTHONMODULE - "python", -#endif -#ifdef WITH_DYNLIBMODULE - "dynlib", -#endif -#ifdef USE_CACHEDB - "cachedb", -#endif -#ifdef USE_IPSECMOD - "ipsecmod", -#endif -#ifdef CLIENT_SUBNET - "subnetcache", -#endif -#ifdef USE_IPSET - "ipset", -#endif - "respip", - "validator", - "iterator", - NULL}; - return names; -} - -/** func block get function type */ -typedef struct module_func_block* (*fbgetfunctype)(void); - -/** The list of module func blocks */ -static fbgetfunctype* -module_funcs_avail(void) -{ - static struct module_func_block* (*fb[])(void) = { - &dns64_get_funcblock, -#ifdef WITH_PYTHONMODULE - &pythonmod_get_funcblock, -#endif -#ifdef WITH_DYNLIBMODULE - &dynlibmod_get_funcblock, -#endif -#ifdef USE_CACHEDB - &cachedb_get_funcblock, -#endif -#ifdef USE_IPSECMOD - &ipsecmod_get_funcblock, -#endif -#ifdef CLIENT_SUBNET - &subnetmod_get_funcblock, -#endif -#ifdef USE_IPSET - &ipset_get_funcblock, -#endif - &respip_get_funcblock, - &val_get_funcblock, - &iter_get_funcblock, - NULL}; - return fb; -} - -struct -module_func_block* module_factory(const char** str) -{ - int i = 0; - const char* s = *str; - const char** names = module_list_avail(); - fbgetfunctype* fb = module_funcs_avail(); - while(*s && isspace((unsigned char)*s)) - s++; - while(names[i]) { - if(strncmp(names[i], s, strlen(names[i])) == 0) { - s += strlen(names[i]); - *str = s; - return (*fb[i])(); - } - i++; - } - return NULL; -} - -int -modstack_setup(struct module_stack* stack, const char* module_conf, - struct module_env* env) -{ - int i; - if(stack->num != 0) - modstack_desetup(stack, env); - /* fixed setup of the modules */ - if(!modstack_config(stack, module_conf)) { - return 0; - } - env->need_to_validate = 0; /* set by module init below */ - for(i=0; inum; i++) { - verbose(VERB_OPS, "init module %d: %s", - i, stack->mod[i]->name); - fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); - if(!(*stack->mod[i]->init)(env, i)) { - log_err("module init for module %s failed", - stack->mod[i]->name); - return 0; - } - } - return 1; -} - -void -modstack_desetup(struct module_stack* stack, struct module_env* env) -{ - int i; - for(i=0; inum; i++) { - fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); - (*stack->mod[i]->deinit)(env, i); - } - stack->num = 0; - free(stack->mod); - stack->mod = NULL; -} - -int -modstack_find(struct module_stack* stack, const char* name) -{ - int i; - for(i=0; inum; i++) { - if(strcmp(stack->mod[i]->name, name) == 0) - return i; - } - return -1; -} - -size_t -mod_get_mem(struct module_env* env, const char* name) -{ - int m = modstack_find(&env->mesh->mods, name); - if(m != -1) { - fptr_ok(fptr_whitelist_mod_get_mem(env->mesh-> - mods.mod[m]->get_mem)); - return (*env->mesh->mods.mod[m]->get_mem)(env, m); - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/services/modstack.h b/crates/libunbound-sys/unbound/services/modstack.h deleted file mode 100644 index 3ff01b54..00000000 --- a/crates/libunbound-sys/unbound/services/modstack.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * services/modstack.h - stack of modules - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to help maintain a stack of modules. - */ - -#ifndef SERVICES_MODSTACK_H -#define SERVICES_MODSTACK_H -struct module_func_block; -struct module_env; - -/** - * Stack of modules. - */ -struct module_stack { - /** the number of modules */ - int num; - /** the module callbacks, array of num_modules length (ref only) */ - struct module_func_block** mod; -}; - -/** - * Init a stack of modules - * @param stack: initialised as empty. - */ -void modstack_init(struct module_stack* stack); - -/** - * Read config file module settings and set up the modfunc block - * @param stack: the stack of modules (empty before call). - * @param module_conf: string what modules to insert. - * @return false on error - */ -int modstack_config(struct module_stack* stack, const char* module_conf); - -/** - * Get funcblock for module name - * @param str: string with module name. Advanced to next value on success. - * The string is assumed whitespace separated list of module names. - * @return funcblock or NULL on error. - */ -struct module_func_block* module_factory(const char** str); - -/** - * Get list of modules available. - * @return list of modules available. Static strings, ends with NULL. - */ -const char** module_list_avail(void); - -/** - * Setup modules. Assigns ids and calls module_init. - * @param stack: if not empty beforehand, it will be desetup()ed. - * It is then modstack_configged(). - * @param module_conf: string what modules to insert. - * @param env: module environment which is inited by the modules. - * environment should have a superalloc, cfg, - * env.need_to_validate is set by the modules. - * @return on false a module init failed. - */ -int modstack_setup(struct module_stack* stack, const char* module_conf, - struct module_env* env); - -/** - * Desetup the modules, deinit, delete. - * @param stack: made empty. - * @param env: module env for module deinit() calls. - */ -void modstack_desetup(struct module_stack* stack, struct module_env* env); - -/** - * Find index of module by name. - * @param stack: to look in - * @param name: the name to look for - * @return -1 on failure, otherwise index number. - */ -int modstack_find(struct module_stack* stack, const char* name); - -/** fetch memory for a module by name, returns 0 if module not there */ -size_t mod_get_mem(struct module_env* env, const char* name); - -#endif /* SERVICES_MODSTACK_H */ diff --git a/crates/libunbound-sys/unbound/services/outbound_list.c b/crates/libunbound-sys/unbound/services/outbound_list.c deleted file mode 100644 index ad73380b..00000000 --- a/crates/libunbound-sys/unbound/services/outbound_list.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * services/outbound_list.c - keep list of outbound serviced queries. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to help a module keep track of the - * queries it has outstanding to authoritative servers. - */ -#include "config.h" -#include -#include "services/outbound_list.h" -#include "services/outside_network.h" - -void -outbound_list_init(struct outbound_list* list) -{ - list->first = NULL; -} - -void -outbound_list_clear(struct outbound_list* list) -{ - struct outbound_entry *p, *np; - p = list->first; - while(p) { - np = p->next; - outnet_serviced_query_stop(p->qsent, p); - /* in region, no free needed */ - p = np; - } - outbound_list_init(list); -} - -void -outbound_list_insert(struct outbound_list* list, struct outbound_entry* e) -{ - if(list->first) - list->first->prev = e; - e->next = list->first; - e->prev = NULL; - list->first = e; -} - -void -outbound_list_remove(struct outbound_list* list, struct outbound_entry* e) -{ - if(!e) - return; - outnet_serviced_query_stop(e->qsent, e); - if(e->next) - e->next->prev = e->prev; - if(e->prev) - e->prev->next = e->next; - else list->first = e->next; - /* in region, no free needed */ -} diff --git a/crates/libunbound-sys/unbound/services/outbound_list.h b/crates/libunbound-sys/unbound/services/outbound_list.h deleted file mode 100644 index 73c137d5..00000000 --- a/crates/libunbound-sys/unbound/services/outbound_list.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * services/outbound_list.h - keep list of outbound serviced queries. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to help a module keep track of the - * queries it has outstanding to authoritative servers. - */ -#ifndef SERVICES_OUTBOUND_LIST_H -#define SERVICES_OUTBOUND_LIST_H -struct outbound_entry; -struct serviced_query; -struct module_qstate; - -/** - * The outbound list. This structure is part of the module specific query - * state. - */ -struct outbound_list { - /** The linked list of outbound query entries. */ - struct outbound_entry* first; -}; - -/** - * Outbound list entry. A serviced query sent by a module processing the - * query from the qstate. Double linked list to aid removal. - */ -struct outbound_entry { - /** next in list */ - struct outbound_entry* next; - /** prev in list */ - struct outbound_entry* prev; - /** The query that was sent out */ - struct serviced_query* qsent; - /** the module query state that sent it */ - struct module_qstate* qstate; -}; - -/** - * Init the user allocated outbound list structure - * @param list: the list structure. - */ -void outbound_list_init(struct outbound_list* list); - -/** - * Clear the user owner outbound list structure. - * Deletes serviced queries. - * @param list: the list structure. It is cleared, but the list struct itself - * is callers responsibility to delete. - */ -void outbound_list_clear(struct outbound_list* list); - -/** - * Insert new entry into the list. Caller must allocate the entry with malloc. - * qstate and qsent are set by caller. - * @param list: the list to add to. - * @param e: entry to add, it is only half initialised at call start, fully - * initialised at call end. - */ -void outbound_list_insert(struct outbound_list* list, - struct outbound_entry* e); - -/** - * Remove an entry from the list, and deletes it. - * Deletes serviced query in the entry. - * @param list: the list to remove from. - * @param e: the entry to remove. - */ -void outbound_list_remove(struct outbound_list* list, - struct outbound_entry* e); - -#endif /* SERVICES_OUTBOUND_LIST_H */ diff --git a/crates/libunbound-sys/unbound/services/outside_network.c b/crates/libunbound-sys/unbound/services/outside_network.c deleted file mode 100644 index 2a219cbc..00000000 --- a/crates/libunbound-sys/unbound/services/outside_network.c +++ /dev/null @@ -1,3923 +0,0 @@ -/* - * services/outside_network.c - implement sending of queries and wait answer. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has functions to send queries to authoritative servers and - * wait for the pending answer events. - */ -#include "config.h" -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#include -#include "services/outside_network.h" -#include "services/listen_dnsport.h" -#include "services/cache/infra.h" -#include "iterator/iterator.h" -#include "util/data/msgparse.h" -#include "util/data/msgreply.h" -#include "util/data/msgencode.h" -#include "util/data/dname.h" -#include "util/netevent.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/random.h" -#include "util/fptr_wlist.h" -#include "util/edns.h" -#include "sldns/sbuffer.h" -#include "dnstap/dnstap.h" -#ifdef HAVE_OPENSSL_SSL_H -#include -#endif -#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST -#include -#endif - -#ifdef HAVE_NETDB_H -#include -#endif -#include - -/** number of times to retry making a random ID that is unique. */ -#define MAX_ID_RETRY 1000 -/** number of times to retry finding interface, port that can be opened. */ -#define MAX_PORT_RETRY 10000 -/** number of retries on outgoing UDP queries */ -#define OUTBOUND_UDP_RETRY 1 - -/** initiate TCP transaction for serviced query */ -static void serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff); -/** with a fd available, randomize and send UDP */ -static int randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, - int timeout); - -/** select a DNS ID for a TCP stream */ -static uint16_t tcp_select_id(struct outside_network* outnet, - struct reuse_tcp* reuse); - -/** Perform serviced query UDP sending operation */ -static int serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff); - -/** Send serviced query over TCP return false on initial failure */ -static int serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff); - -/** call the callbacks for a serviced query */ -static void serviced_callbacks(struct serviced_query* sq, int error, - struct comm_point* c, struct comm_reply* rep); - -int -pending_cmp(const void* key1, const void* key2) -{ - struct pending *p1 = (struct pending*)key1; - struct pending *p2 = (struct pending*)key2; - if(p1->id < p2->id) - return -1; - if(p1->id > p2->id) - return 1; - log_assert(p1->id == p2->id); - return sockaddr_cmp(&p1->addr, p1->addrlen, &p2->addr, p2->addrlen); -} - -int -serviced_cmp(const void* key1, const void* key2) -{ - struct serviced_query* q1 = (struct serviced_query*)key1; - struct serviced_query* q2 = (struct serviced_query*)key2; - int r; - if(q1->qbuflen < q2->qbuflen) - return -1; - if(q1->qbuflen > q2->qbuflen) - return 1; - log_assert(q1->qbuflen == q2->qbuflen); - log_assert(q1->qbuflen >= 15 /* 10 header, root, type, class */); - /* alternate casing of qname is still the same query */ - if((r = memcmp(q1->qbuf, q2->qbuf, 10)) != 0) - return r; - if((r = memcmp(q1->qbuf+q1->qbuflen-4, q2->qbuf+q2->qbuflen-4, 4)) != 0) - return r; - if(q1->dnssec != q2->dnssec) { - if(q1->dnssec < q2->dnssec) - return -1; - return 1; - } - if((r = query_dname_compare(q1->qbuf+10, q2->qbuf+10)) != 0) - return r; - if((r = edns_opt_list_compare(q1->opt_list, q2->opt_list)) != 0) - return r; - return sockaddr_cmp(&q1->addr, q1->addrlen, &q2->addr, q2->addrlen); -} - -/** compare if the reuse element has the same address, port and same ssl-is - * used-for-it characteristic */ -static int -reuse_cmp_addrportssl(const void* key1, const void* key2) -{ - struct reuse_tcp* r1 = (struct reuse_tcp*)key1; - struct reuse_tcp* r2 = (struct reuse_tcp*)key2; - int r; - /* compare address and port */ - r = sockaddr_cmp(&r1->addr, r1->addrlen, &r2->addr, r2->addrlen); - if(r != 0) - return r; - - /* compare if SSL-enabled */ - if(r1->is_ssl && !r2->is_ssl) - return 1; - if(!r1->is_ssl && r2->is_ssl) - return -1; - return 0; -} - -int -reuse_cmp(const void* key1, const void* key2) -{ - int r; - r = reuse_cmp_addrportssl(key1, key2); - if(r != 0) - return r; - - /* compare ptr value */ - if(key1 < key2) return -1; - if(key1 > key2) return 1; - return 0; -} - -int reuse_id_cmp(const void* key1, const void* key2) -{ - struct waiting_tcp* w1 = (struct waiting_tcp*)key1; - struct waiting_tcp* w2 = (struct waiting_tcp*)key2; - if(w1->id < w2->id) - return -1; - if(w1->id > w2->id) - return 1; - return 0; -} - -/** delete waiting_tcp entry. Does not unlink from waiting list. - * @param w: to delete. - */ -static void -waiting_tcp_delete(struct waiting_tcp* w) -{ - if(!w) return; - if(w->timer) - comm_timer_delete(w->timer); - free(w); -} - -/** - * Pick random outgoing-interface of that family, and bind it. - * port set to 0 so OS picks a port number for us. - * if it is the ANY address, do not bind. - * @param pend: pending tcp structure, for storing the local address choice. - * @param w: tcp structure with destination address. - * @param s: socket fd. - * @return false on error, socket closed. - */ -static int -pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s) -{ - struct port_if* pi = NULL; - int num; - pend->pi = NULL; -#ifdef INET6 - if(addr_is_ip6(&w->addr, w->addrlen)) - num = w->outnet->num_ip6; - else -#endif - num = w->outnet->num_ip4; - if(num == 0) { - log_err("no TCP outgoing interfaces of family"); - log_addr(VERB_OPS, "for addr", &w->addr, w->addrlen); - sock_close(s); - return 0; - } -#ifdef INET6 - if(addr_is_ip6(&w->addr, w->addrlen)) - pi = &w->outnet->ip6_ifs[ub_random_max(w->outnet->rnd, num)]; - else -#endif - pi = &w->outnet->ip4_ifs[ub_random_max(w->outnet->rnd, num)]; - log_assert(pi); - pend->pi = pi; - if(addr_is_any(&pi->addr, pi->addrlen)) { - /* binding to the ANY interface is for listening sockets */ - return 1; - } - /* set port to 0 */ - if(addr_is_ip6(&pi->addr, pi->addrlen)) - ((struct sockaddr_in6*)&pi->addr)->sin6_port = 0; - else ((struct sockaddr_in*)&pi->addr)->sin_port = 0; - if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) { -#ifndef USE_WINSOCK -#ifdef EADDRNOTAVAIL - if(!(verbosity < 4 && errno == EADDRNOTAVAIL)) -#endif -#else /* USE_WINSOCK */ - if(!(verbosity < 4 && WSAGetLastError() == WSAEADDRNOTAVAIL)) -#endif - log_err("outgoing tcp: bind: %s", sock_strerror(errno)); - sock_close(s); - return 0; - } - log_addr(VERB_ALGO, "tcp bound to src", &pi->addr, pi->addrlen); - return 1; -} - -/** get TCP file descriptor for address, returns -1 on failure, - * tcp_mss is 0 or maxseg size to set for TCP packets. */ -int -outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp) -{ - int s; - int af; - char* err; -#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) - int on = 1; -#endif -#ifdef INET6 - if(addr_is_ip6(addr, addrlen)){ - s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); - af = AF_INET6; - } else { -#else - { -#endif - af = AF_INET; - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - } - if(s == -1) { - log_err_addr("outgoing tcp: socket", sock_strerror(errno), - addr, addrlen); - return -1; - } - -#ifdef SO_REUSEADDR - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - verbose(VERB_ALGO, "outgoing tcp:" - " setsockopt(.. SO_REUSEADDR ..) failed"); - } -#endif - - err = set_ip_dscp(s, af, dscp); - if(err != NULL) { - verbose(VERB_ALGO, "outgoing tcp:" - "error setting IP DiffServ codepoint on socket"); - } - - if(tcp_mss > 0) { -#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG) - if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, - (void*)&tcp_mss, (socklen_t)sizeof(tcp_mss)) < 0) { - verbose(VERB_ALGO, "outgoing tcp:" - " setsockopt(.. TCP_MAXSEG ..) failed"); - } -#else - verbose(VERB_ALGO, "outgoing tcp:" - " setsockopt(TCP_MAXSEG) unsupported"); -#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */ - } -#ifdef IP_BIND_ADDRESS_NO_PORT - if(setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (void*)&on, - (socklen_t)sizeof(on)) < 0) { - verbose(VERB_ALGO, "outgoing tcp:" - " setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed"); - } -#endif /* IP_BIND_ADDRESS_NO_PORT */ - return s; -} - -/** connect tcp connection to addr, 0 on failure */ -int -outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen) -{ - if(connect(s, (struct sockaddr*)addr, addrlen) == -1) { -#ifndef USE_WINSOCK -#ifdef EINPROGRESS - if(errno != EINPROGRESS) { -#endif - if(tcp_connect_errno_needs_log( - (struct sockaddr*)addr, addrlen)) - log_err_addr("outgoing tcp: connect", - strerror(errno), addr, addrlen); - close(s); - return 0; -#ifdef EINPROGRESS - } -#endif -#else /* USE_WINSOCK */ - if(WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEWOULDBLOCK) { - closesocket(s); - return 0; - } -#endif - } - return 1; -} - -/** log reuse item addr and ptr with message */ -static void -log_reuse_tcp(enum verbosity_value v, const char* msg, struct reuse_tcp* reuse) -{ - uint16_t port; - char addrbuf[128]; - if(verbosity < v) return; - if(!reuse || !reuse->pending || !reuse->pending->c) - return; - addr_to_str(&reuse->addr, reuse->addrlen, addrbuf, sizeof(addrbuf)); - port = ntohs(((struct sockaddr_in*)&reuse->addr)->sin_port); - verbose(v, "%s %s#%u fd %d", msg, addrbuf, (unsigned)port, - reuse->pending->c->fd); -} - -/** pop the first element from the writewait list */ -struct waiting_tcp* -reuse_write_wait_pop(struct reuse_tcp* reuse) -{ - struct waiting_tcp* w = reuse->write_wait_first; - if(!w) - return NULL; - log_assert(w->write_wait_queued); - log_assert(!w->write_wait_prev); - reuse->write_wait_first = w->write_wait_next; - if(w->write_wait_next) - w->write_wait_next->write_wait_prev = NULL; - else reuse->write_wait_last = NULL; - w->write_wait_queued = 0; - w->write_wait_next = NULL; - w->write_wait_prev = NULL; - return w; -} - -/** remove the element from the writewait list */ -void -reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w) -{ - log_assert(w); - log_assert(w->write_wait_queued); - if(!w) - return; - if(!w->write_wait_queued) - return; - if(w->write_wait_prev) - w->write_wait_prev->write_wait_next = w->write_wait_next; - else reuse->write_wait_first = w->write_wait_next; - log_assert(!w->write_wait_prev || - w->write_wait_prev->write_wait_next != w->write_wait_prev); - if(w->write_wait_next) - w->write_wait_next->write_wait_prev = w->write_wait_prev; - else reuse->write_wait_last = w->write_wait_prev; - log_assert(!w->write_wait_next - || w->write_wait_next->write_wait_prev != w->write_wait_next); - w->write_wait_queued = 0; - w->write_wait_next = NULL; - w->write_wait_prev = NULL; -} - -/** push the element after the last on the writewait list */ -void -reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w) -{ - if(!w) return; - log_assert(!w->write_wait_queued); - if(reuse->write_wait_last) { - reuse->write_wait_last->write_wait_next = w; - log_assert(reuse->write_wait_last->write_wait_next != - reuse->write_wait_last); - w->write_wait_prev = reuse->write_wait_last; - } else { - reuse->write_wait_first = w; - w->write_wait_prev = NULL; - } - w->write_wait_next = NULL; - reuse->write_wait_last = w; - w->write_wait_queued = 1; -} - -/** insert element in tree by id */ -void -reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w) -{ -#ifdef UNBOUND_DEBUG - rbnode_type* added; -#endif - log_assert(w->id_node.key == NULL); - w->id_node.key = w; -#ifdef UNBOUND_DEBUG - added = -#else - (void) -#endif - rbtree_insert(&reuse->tree_by_id, &w->id_node); - log_assert(added); /* should have been added */ -} - -/** find element in tree by id */ -struct waiting_tcp* -reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id) -{ - struct waiting_tcp key_w; - rbnode_type* n; - memset(&key_w, 0, sizeof(key_w)); - key_w.id_node.key = &key_w; - key_w.id = id; - n = rbtree_search(&reuse->tree_by_id, &key_w); - if(!n) return NULL; - return (struct waiting_tcp*)n->key; -} - -/** return ID value of rbnode in tree_by_id */ -static uint16_t -tree_by_id_get_id(rbnode_type* node) -{ - struct waiting_tcp* w = (struct waiting_tcp*)node->key; - return w->id; -} - -/** insert into reuse tcp tree and LRU, false on failure (duplicate) */ -int -reuse_tcp_insert(struct outside_network* outnet, struct pending_tcp* pend_tcp) -{ - log_reuse_tcp(VERB_CLIENT, "reuse_tcp_insert", &pend_tcp->reuse); - if(pend_tcp->reuse.item_on_lru_list) { - if(!pend_tcp->reuse.node.key) - log_err("internal error: reuse_tcp_insert: " - "in lru list without key"); - return 1; - } - pend_tcp->reuse.node.key = &pend_tcp->reuse; - pend_tcp->reuse.pending = pend_tcp; - if(!rbtree_insert(&outnet->tcp_reuse, &pend_tcp->reuse.node)) { - /* We are not in the LRU list but we are already in the - * tcp_reuse tree, strange. - * Continue to add ourselves to the LRU list. */ - log_err("internal error: reuse_tcp_insert: in lru list but " - "not in the tree"); - } - /* insert into LRU, first is newest */ - pend_tcp->reuse.lru_prev = NULL; - if(outnet->tcp_reuse_first) { - pend_tcp->reuse.lru_next = outnet->tcp_reuse_first; - log_assert(pend_tcp->reuse.lru_next != &pend_tcp->reuse); - outnet->tcp_reuse_first->lru_prev = &pend_tcp->reuse; - log_assert(outnet->tcp_reuse_first->lru_prev != - outnet->tcp_reuse_first); - } else { - pend_tcp->reuse.lru_next = NULL; - outnet->tcp_reuse_last = &pend_tcp->reuse; - } - outnet->tcp_reuse_first = &pend_tcp->reuse; - pend_tcp->reuse.item_on_lru_list = 1; - log_assert((!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); - log_assert(outnet->tcp_reuse_first != outnet->tcp_reuse_first->lru_next && - outnet->tcp_reuse_first != outnet->tcp_reuse_first->lru_prev); - log_assert(outnet->tcp_reuse_last != outnet->tcp_reuse_last->lru_next && - outnet->tcp_reuse_last != outnet->tcp_reuse_last->lru_prev); - return 1; -} - -/** find reuse tcp stream to destination for query, or NULL if none */ -static struct reuse_tcp* -reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr, - socklen_t addrlen, int use_ssl) -{ - struct waiting_tcp key_w; - struct pending_tcp key_p; - struct comm_point c; - rbnode_type* result = NULL, *prev; - verbose(VERB_CLIENT, "reuse_tcp_find"); - memset(&key_w, 0, sizeof(key_w)); - memset(&key_p, 0, sizeof(key_p)); - memset(&c, 0, sizeof(c)); - key_p.query = &key_w; - key_p.c = &c; - key_p.reuse.pending = &key_p; - key_p.reuse.node.key = &key_p.reuse; - if(use_ssl) - key_p.reuse.is_ssl = 1; - if(addrlen > (socklen_t)sizeof(key_p.reuse.addr)) - return NULL; - memmove(&key_p.reuse.addr, addr, addrlen); - key_p.reuse.addrlen = addrlen; - - verbose(VERB_CLIENT, "reuse_tcp_find: num reuse streams %u", - (unsigned)outnet->tcp_reuse.count); - if(outnet->tcp_reuse.root == NULL || - outnet->tcp_reuse.root == RBTREE_NULL) - return NULL; - if(rbtree_find_less_equal(&outnet->tcp_reuse, &key_p.reuse, - &result)) { - /* exact match */ - /* but the key is on stack, and ptr is compared, impossible */ - log_assert(&key_p.reuse != (struct reuse_tcp*)result); - log_assert(&key_p != ((struct reuse_tcp*)result)->pending); - } - /* not found, return null */ - - /* It is possible that we search for something before the first element - * in the tree. Replace a null pointer with the first element. - */ - if (!result) { - verbose(VERB_CLIENT, "reuse_tcp_find: taking first"); - result = rbtree_first(&outnet->tcp_reuse); - } - - if(!result || result == RBTREE_NULL) - return NULL; - - /* It is possible that we got the previous address, but that the - * address we are looking for is in the tree. If the address we got - * is less than the address we are looking, then take the next entry. - */ - if (reuse_cmp_addrportssl(result->key, &key_p.reuse) < 0) { - verbose(VERB_CLIENT, "reuse_tcp_find: key too low"); - result = rbtree_next(result); - } - - verbose(VERB_CLIENT, "reuse_tcp_find check inexact match"); - /* inexact match, find one of possibly several connections to the - * same destination address, with the correct port, ssl, and - * also less than max number of open queries, or else, fail to open - * a new one */ - /* rewind to start of sequence of same address,port,ssl */ - prev = rbtree_previous(result); - while(prev && prev != RBTREE_NULL && - reuse_cmp_addrportssl(prev->key, &key_p.reuse) == 0) { - result = prev; - prev = rbtree_previous(result); - } - - /* loop to find first one that has correct characteristics */ - while(result && result != RBTREE_NULL && - reuse_cmp_addrportssl(result->key, &key_p.reuse) == 0) { - if(((struct reuse_tcp*)result)->tree_by_id.count < - outnet->max_reuse_tcp_queries) { - /* same address, port, ssl-yes-or-no, and has - * space for another query */ - return (struct reuse_tcp*)result; - } - result = rbtree_next(result); - } - return NULL; -} - -/** use the buffer to setup writing the query */ -static void -outnet_tcp_take_query_setup(int s, struct pending_tcp* pend, - struct waiting_tcp* w) -{ - struct timeval tv; - verbose(VERB_CLIENT, "outnet_tcp_take_query_setup: setup packet to write " - "len %d timeout %d msec", - (int)w->pkt_len, w->timeout); - pend->c->tcp_write_pkt = w->pkt; - pend->c->tcp_write_pkt_len = w->pkt_len; - pend->c->tcp_write_and_read = 1; - pend->c->tcp_write_byte_count = 0; - pend->c->tcp_is_reading = 0; - comm_point_start_listening(pend->c, s, -1); - /* set timer on the waiting_tcp entry, this is the write timeout - * for the written packet. The timer on pend->c is the timer - * for when there is no written packet and we have readtimeouts */ -#ifndef S_SPLINT_S - tv.tv_sec = w->timeout/1000; - tv.tv_usec = (w->timeout%1000)*1000; -#endif - /* if the waiting_tcp was previously waiting for a buffer in the - * outside_network.tcpwaitlist, then the timer is reset now that - * we start writing it */ - comm_timer_set(w->timer, &tv); -} - -/** use next free buffer to service a tcp query */ -static int -outnet_tcp_take_into_use(struct waiting_tcp* w) -{ - struct pending_tcp* pend = w->outnet->tcp_free; - int s; - log_assert(pend); - log_assert(w->pkt); - log_assert(w->pkt_len > 0); - log_assert(w->addrlen > 0); - pend->c->tcp_do_toggle_rw = 0; - pend->c->tcp_do_close = 0; - - /* Consistency check, if we have ssl_upstream but no sslctx, then - * log an error and return failure. - */ - if (w->ssl_upstream && !w->outnet->sslctx) { - log_err("SSL upstream requested but no SSL context"); - return 0; - } - - /* open socket */ - s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp); - - if(s == -1) - return 0; - - if(!pick_outgoing_tcp(pend, w, s)) - return 0; - - fd_set_nonblock(s); -#ifdef USE_OSX_MSG_FASTOPEN - /* API for fast open is different here. We use a connectx() function and - then writes can happen as normal even using SSL.*/ - /* connectx requires that the len be set in the sockaddr struct*/ - struct sockaddr_in *addr_in = (struct sockaddr_in *)&w->addr; - addr_in->sin_len = w->addrlen; - sa_endpoints_t endpoints; - endpoints.sae_srcif = 0; - endpoints.sae_srcaddr = NULL; - endpoints.sae_srcaddrlen = 0; - endpoints.sae_dstaddr = (struct sockaddr *)&w->addr; - endpoints.sae_dstaddrlen = w->addrlen; - if (connectx(s, &endpoints, SAE_ASSOCID_ANY, - CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE, - NULL, 0, NULL, NULL) == -1) { - /* if fails, failover to connect for OSX 10.10 */ -#ifdef EINPROGRESS - if(errno != EINPROGRESS) { -#else - if(1) { -#endif - if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) { -#else /* USE_OSX_MSG_FASTOPEN*/ -#ifdef USE_MSG_FASTOPEN - pend->c->tcp_do_fastopen = 1; - /* Only do TFO for TCP in which case no connect() is required here. - Don't combine client TFO with SSL, since OpenSSL can't - currently support doing a handshake on fd that already isn't connected*/ - if (w->outnet->sslctx && w->ssl_upstream) { - if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) { -#else /* USE_MSG_FASTOPEN*/ - if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) { -#endif /* USE_MSG_FASTOPEN*/ -#endif /* USE_OSX_MSG_FASTOPEN*/ -#ifndef USE_WINSOCK -#ifdef EINPROGRESS - if(errno != EINPROGRESS) { -#else - if(1) { -#endif - if(tcp_connect_errno_needs_log( - (struct sockaddr*)&w->addr, w->addrlen)) - log_err_addr("outgoing tcp: connect", - strerror(errno), &w->addr, w->addrlen); - close(s); -#else /* USE_WINSOCK */ - if(WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEWOULDBLOCK) { - closesocket(s); -#endif - return 0; - } - } -#ifdef USE_MSG_FASTOPEN - } -#endif /* USE_MSG_FASTOPEN */ -#ifdef USE_OSX_MSG_FASTOPEN - } - } -#endif /* USE_OSX_MSG_FASTOPEN */ - if(w->outnet->sslctx && w->ssl_upstream) { - pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s); - if(!pend->c->ssl) { - pend->c->fd = s; - comm_point_close(pend->c); - return 0; - } - verbose(VERB_ALGO, "the query is using TLS encryption, for %s", - (w->tls_auth_name?w->tls_auth_name:"an unauthenticated connection")); -#ifdef USE_WINSOCK - comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl); -#endif - pend->c->ssl_shake_state = comm_ssl_shake_write; - if(!set_auth_name_on_ssl(pend->c->ssl, w->tls_auth_name, - w->outnet->tls_use_sni)) { - pend->c->fd = s; -#ifdef HAVE_SSL - SSL_free(pend->c->ssl); -#endif - pend->c->ssl = NULL; - comm_point_close(pend->c); - return 0; - } - } - w->next_waiting = (void*)pend; - w->outnet->num_tcp_outgoing++; - w->outnet->tcp_free = pend->next_free; - pend->next_free = NULL; - pend->query = w; - pend->reuse.outnet = w->outnet; - pend->c->repinfo.remote_addrlen = w->addrlen; - pend->c->tcp_more_read_again = &pend->reuse.cp_more_read_again; - pend->c->tcp_more_write_again = &pend->reuse.cp_more_write_again; - pend->reuse.cp_more_read_again = 0; - pend->reuse.cp_more_write_again = 0; - memcpy(&pend->c->repinfo.remote_addr, &w->addr, w->addrlen); - pend->reuse.pending = pend; - - /* Remove from tree in case the is_ssl will be different and causes the - * identity of the reuse_tcp to change; could result in nodes not being - * deleted from the tree (because the new identity does not match the - * previous node) but their ->key would be changed to NULL. */ - if(pend->reuse.node.key) - reuse_tcp_remove_tree_list(w->outnet, &pend->reuse); - - if(pend->c->ssl) - pend->reuse.is_ssl = 1; - else pend->reuse.is_ssl = 0; - /* insert in reuse by address tree if not already inserted there */ - (void)reuse_tcp_insert(w->outnet, pend); - reuse_tree_by_id_insert(&pend->reuse, w); - outnet_tcp_take_query_setup(s, pend, w); - return 1; -} - -/** Touch the lru of a reuse_tcp element, it is in use. - * This moves it to the front of the list, where it is not likely to - * be closed. Items at the back of the list are closed to make space. */ -void -reuse_tcp_lru_touch(struct outside_network* outnet, struct reuse_tcp* reuse) -{ - if(!reuse->item_on_lru_list) { - log_err("internal error: we need to touch the lru_list but item not in list"); - return; /* not on the list, no lru to modify */ - } - log_assert(reuse->lru_prev || - (!reuse->lru_prev && outnet->tcp_reuse_first == reuse)); - if(!reuse->lru_prev) - return; /* already first in the list */ - /* remove at current position */ - /* since it is not first, there is a previous element */ - reuse->lru_prev->lru_next = reuse->lru_next; - log_assert(reuse->lru_prev->lru_next != reuse->lru_prev); - if(reuse->lru_next) - reuse->lru_next->lru_prev = reuse->lru_prev; - else outnet->tcp_reuse_last = reuse->lru_prev; - log_assert(!reuse->lru_next || reuse->lru_next->lru_prev != reuse->lru_next); - log_assert(outnet->tcp_reuse_last != outnet->tcp_reuse_last->lru_next && - outnet->tcp_reuse_last != outnet->tcp_reuse_last->lru_prev); - /* insert at the front */ - reuse->lru_prev = NULL; - reuse->lru_next = outnet->tcp_reuse_first; - if(outnet->tcp_reuse_first) { - outnet->tcp_reuse_first->lru_prev = reuse; - } - log_assert(reuse->lru_next != reuse); - /* since it is not first, it is not the only element and - * lru_next is thus not NULL and thus reuse is now not the last in - * the list, so outnet->tcp_reuse_last does not need to be modified */ - outnet->tcp_reuse_first = reuse; - log_assert(outnet->tcp_reuse_first != outnet->tcp_reuse_first->lru_next && - outnet->tcp_reuse_first != outnet->tcp_reuse_first->lru_prev); - log_assert((!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); -} - -/** Snip the last reuse_tcp element off of the LRU list */ -struct reuse_tcp* -reuse_tcp_lru_snip(struct outside_network* outnet) -{ - struct reuse_tcp* reuse = outnet->tcp_reuse_last; - if(!reuse) return NULL; - /* snip off of LRU */ - log_assert(reuse->lru_next == NULL); - if(reuse->lru_prev) { - outnet->tcp_reuse_last = reuse->lru_prev; - reuse->lru_prev->lru_next = NULL; - } else { - outnet->tcp_reuse_last = NULL; - outnet->tcp_reuse_first = NULL; - } - log_assert((!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); - reuse->item_on_lru_list = 0; - reuse->lru_next = NULL; - reuse->lru_prev = NULL; - return reuse; -} - -/** remove waiting tcp from the outnet waiting list */ -void -outnet_waiting_tcp_list_remove(struct outside_network* outnet, struct waiting_tcp* w) -{ - struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL; - w->on_tcp_waiting_list = 0; - while(p) { - if(p == w) { - /* remove w */ - if(prev) - prev->next_waiting = w->next_waiting; - else outnet->tcp_wait_first = w->next_waiting; - if(outnet->tcp_wait_last == w) - outnet->tcp_wait_last = prev; - w->next_waiting = NULL; - return; - } - prev = p; - p = p->next_waiting; - } - /* outnet_waiting_tcp_list_remove is currently called only with items - * that are already in the waiting list. */ - log_assert(0); -} - -/** pop the first waiting tcp from the outnet waiting list */ -struct waiting_tcp* -outnet_waiting_tcp_list_pop(struct outside_network* outnet) -{ - struct waiting_tcp* w = outnet->tcp_wait_first; - if(!outnet->tcp_wait_first) return NULL; - log_assert(w->on_tcp_waiting_list); - outnet->tcp_wait_first = w->next_waiting; - if(outnet->tcp_wait_last == w) - outnet->tcp_wait_last = NULL; - w->on_tcp_waiting_list = 0; - w->next_waiting = NULL; - return w; -} - -/** add waiting_tcp element to the outnet tcp waiting list */ -void -outnet_waiting_tcp_list_add(struct outside_network* outnet, - struct waiting_tcp* w, int set_timer) -{ - struct timeval tv; - log_assert(!w->on_tcp_waiting_list); - if(w->on_tcp_waiting_list) - return; - w->next_waiting = NULL; - if(outnet->tcp_wait_last) - outnet->tcp_wait_last->next_waiting = w; - else outnet->tcp_wait_first = w; - outnet->tcp_wait_last = w; - w->on_tcp_waiting_list = 1; - if(set_timer) { -#ifndef S_SPLINT_S - tv.tv_sec = w->timeout/1000; - tv.tv_usec = (w->timeout%1000)*1000; -#endif - comm_timer_set(w->timer, &tv); - } -} - -/** add waiting_tcp element as first to the outnet tcp waiting list */ -void -outnet_waiting_tcp_list_add_first(struct outside_network* outnet, - struct waiting_tcp* w, int reset_timer) -{ - struct timeval tv; - log_assert(!w->on_tcp_waiting_list); - if(w->on_tcp_waiting_list) - return; - w->next_waiting = outnet->tcp_wait_first; - log_assert(w->next_waiting != w); - if(!outnet->tcp_wait_last) - outnet->tcp_wait_last = w; - outnet->tcp_wait_first = w; - w->on_tcp_waiting_list = 1; - if(reset_timer) { -#ifndef S_SPLINT_S - tv.tv_sec = w->timeout/1000; - tv.tv_usec = (w->timeout%1000)*1000; -#endif - comm_timer_set(w->timer, &tv); - } - log_assert( - (!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); -} - -/** call callback on waiting_tcp, if not NULL */ -static void -waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error, - struct comm_reply* reply_info) -{ - if(w && w->cb) { - fptr_ok(fptr_whitelist_pending_tcp(w->cb)); - (void)(*w->cb)(c, w->cb_arg, error, reply_info); - } -} - -/** see if buffers can be used to service TCP queries */ -static void -use_free_buffer(struct outside_network* outnet) -{ - struct waiting_tcp* w; - while(outnet->tcp_wait_first && !outnet->want_to_quit) { -#ifdef USE_DNSTAP - struct pending_tcp* pend_tcp = NULL; -#endif - struct reuse_tcp* reuse = NULL; - w = outnet_waiting_tcp_list_pop(outnet); - log_assert( - (!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); - reuse = reuse_tcp_find(outnet, &w->addr, w->addrlen, - w->ssl_upstream); - /* re-select an ID when moving to a new TCP buffer */ - w->id = tcp_select_id(outnet, reuse); - LDNS_ID_SET(w->pkt, w->id); - if(reuse) { - log_reuse_tcp(VERB_CLIENT, "use free buffer for waiting tcp: " - "found reuse", reuse); -#ifdef USE_DNSTAP - pend_tcp = reuse->pending; -#endif - reuse_tcp_lru_touch(outnet, reuse); - comm_timer_disable(w->timer); - w->next_waiting = (void*)reuse->pending; - reuse_tree_by_id_insert(reuse, w); - if(reuse->pending->query) { - /* on the write wait list */ - reuse_write_wait_push_back(reuse, w); - } else { - /* write straight away */ - /* stop the timer on read of the fd */ - comm_point_stop_listening(reuse->pending->c); - reuse->pending->query = w; - outnet_tcp_take_query_setup( - reuse->pending->c->fd, reuse->pending, - w); - } - } else if(outnet->tcp_free) { - struct pending_tcp* pend = w->outnet->tcp_free; - rbtree_init(&pend->reuse.tree_by_id, reuse_id_cmp); - pend->reuse.pending = pend; - memcpy(&pend->reuse.addr, &w->addr, w->addrlen); - pend->reuse.addrlen = w->addrlen; - if(!outnet_tcp_take_into_use(w)) { - waiting_tcp_callback(w, NULL, NETEVENT_CLOSED, - NULL); - waiting_tcp_delete(w); -#ifdef USE_DNSTAP - w = NULL; -#endif - } -#ifdef USE_DNSTAP - pend_tcp = pend; -#endif - } else { - /* no reuse and no free buffer, put back at the start */ - outnet_waiting_tcp_list_add_first(outnet, w, 0); - break; - } -#ifdef USE_DNSTAP - if(outnet->dtenv && pend_tcp && w && w->sq && - (outnet->dtenv->log_resolver_query_messages || - outnet->dtenv->log_forwarder_query_messages)) { - sldns_buffer tmp; - sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len); - dt_msg_send_outside_query(outnet->dtenv, &w->sq->addr, - &pend_tcp->pi->addr, comm_tcp, w->sq->zone, - w->sq->zonelen, &tmp); - } -#endif - } -} - -/** delete element from tree by id */ -static void -reuse_tree_by_id_delete(struct reuse_tcp* reuse, struct waiting_tcp* w) -{ -#ifdef UNBOUND_DEBUG - rbnode_type* rem; -#endif - log_assert(w->id_node.key != NULL); -#ifdef UNBOUND_DEBUG - rem = -#else - (void) -#endif - rbtree_delete(&reuse->tree_by_id, w); - log_assert(rem); /* should have been there */ - w->id_node.key = NULL; -} - -/** move writewait list to go for another connection. */ -static void -reuse_move_writewait_away(struct outside_network* outnet, - struct pending_tcp* pend) -{ - /* the writewait list has not been written yet, so if the - * stream was closed, they have not actually been failed, only - * the queries written. Other queries can get written to another - * stream. For upstreams that do not support multiple queries - * and answers, the stream can get closed, and then the queries - * can get written on a new socket */ - struct waiting_tcp* w; - if(pend->query && pend->query->error_count == 0 && - pend->c->tcp_write_pkt == pend->query->pkt && - pend->c->tcp_write_pkt_len == pend->query->pkt_len) { - /* since the current query is not written, it can also - * move to a free buffer */ - if(verbosity >= VERB_CLIENT && pend->query->pkt_len > 12+2+2 && - LDNS_QDCOUNT(pend->query->pkt) > 0 && - dname_valid(pend->query->pkt+12, pend->query->pkt_len-12)) { - char buf[LDNS_MAX_DOMAINLEN+1]; - dname_str(pend->query->pkt+12, buf); - verbose(VERB_CLIENT, "reuse_move_writewait_away current %s %d bytes were written", - buf, (int)pend->c->tcp_write_byte_count); - } - pend->c->tcp_write_pkt = NULL; - pend->c->tcp_write_pkt_len = 0; - pend->c->tcp_write_and_read = 0; - pend->reuse.cp_more_read_again = 0; - pend->reuse.cp_more_write_again = 0; - pend->c->tcp_is_reading = 1; - w = pend->query; - pend->query = NULL; - /* increase error count, so that if the next socket fails too - * the server selection is run again with this query failed - * and it can select a different server (if possible), or - * fail the query */ - w->error_count ++; - reuse_tree_by_id_delete(&pend->reuse, w); - outnet_waiting_tcp_list_add(outnet, w, 1); - } - while((w = reuse_write_wait_pop(&pend->reuse)) != NULL) { - if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 && - LDNS_QDCOUNT(w->pkt) > 0 && - dname_valid(w->pkt+12, w->pkt_len-12)) { - char buf[LDNS_MAX_DOMAINLEN+1]; - dname_str(w->pkt+12, buf); - verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf); - } - reuse_tree_by_id_delete(&pend->reuse, w); - outnet_waiting_tcp_list_add(outnet, w, 1); - } -} - -/** remove reused element from tree and lru list */ -void -reuse_tcp_remove_tree_list(struct outside_network* outnet, - struct reuse_tcp* reuse) -{ - verbose(VERB_CLIENT, "reuse_tcp_remove_tree_list"); - if(reuse->node.key) { - /* delete it from reuse tree */ - if(!rbtree_delete(&outnet->tcp_reuse, reuse)) { - /* should not be possible, it should be there */ - char buf[256]; - addr_to_str(&reuse->addr, reuse->addrlen, buf, - sizeof(buf)); - log_err("reuse tcp delete: node not present, internal error, %s ssl %d lru %d", buf, reuse->is_ssl, reuse->item_on_lru_list); - } - reuse->node.key = NULL; - /* defend against loops on broken tree by zeroing the - * rbnode structure */ - memset(&reuse->node, 0, sizeof(reuse->node)); - } - /* delete from reuse list */ - if(reuse->item_on_lru_list) { - if(reuse->lru_prev) { - /* assert that members of the lru list are waiting - * and thus have a pending pointer to the struct */ - log_assert(reuse->lru_prev->pending); - reuse->lru_prev->lru_next = reuse->lru_next; - log_assert(reuse->lru_prev->lru_next != reuse->lru_prev); - } else { - log_assert(!reuse->lru_next || reuse->lru_next->pending); - outnet->tcp_reuse_first = reuse->lru_next; - log_assert(!outnet->tcp_reuse_first || - (outnet->tcp_reuse_first != - outnet->tcp_reuse_first->lru_next && - outnet->tcp_reuse_first != - outnet->tcp_reuse_first->lru_prev)); - } - if(reuse->lru_next) { - /* assert that members of the lru list are waiting - * and thus have a pending pointer to the struct */ - log_assert(reuse->lru_next->pending); - reuse->lru_next->lru_prev = reuse->lru_prev; - log_assert(reuse->lru_next->lru_prev != reuse->lru_next); - } else { - log_assert(!reuse->lru_prev || reuse->lru_prev->pending); - outnet->tcp_reuse_last = reuse->lru_prev; - log_assert(!outnet->tcp_reuse_last || - (outnet->tcp_reuse_last != - outnet->tcp_reuse_last->lru_next && - outnet->tcp_reuse_last != - outnet->tcp_reuse_last->lru_prev)); - } - log_assert((!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) || - (outnet->tcp_reuse_first && outnet->tcp_reuse_last)); - reuse->item_on_lru_list = 0; - reuse->lru_next = NULL; - reuse->lru_prev = NULL; - } - reuse->pending = NULL; -} - -/** helper function that deletes an element from the tree of readwait - * elements in tcp reuse structure */ -static void reuse_del_readwait_elem(rbnode_type* node, void* ATTR_UNUSED(arg)) -{ - struct waiting_tcp* w = (struct waiting_tcp*)node->key; - waiting_tcp_delete(w); -} - -/** delete readwait waiting_tcp elements, deletes the elements in the list */ -void reuse_del_readwait(rbtree_type* tree_by_id) -{ - if(tree_by_id->root == NULL || - tree_by_id->root == RBTREE_NULL) - return; - traverse_postorder(tree_by_id, &reuse_del_readwait_elem, NULL); - rbtree_init(tree_by_id, reuse_id_cmp); -} - -/** decommission a tcp buffer, closes commpoint and frees waiting_tcp entry */ -static void -decommission_pending_tcp(struct outside_network* outnet, - struct pending_tcp* pend) -{ - verbose(VERB_CLIENT, "decommission_pending_tcp"); - /* A certain code path can lead here twice for the same pending_tcp - * creating a loop in the free pending_tcp list. */ - if(outnet->tcp_free != pend) { - pend->next_free = outnet->tcp_free; - outnet->tcp_free = pend; - } - if(pend->reuse.node.key) { - /* needs unlink from the reuse tree to get deleted */ - reuse_tcp_remove_tree_list(outnet, &pend->reuse); - } - /* free SSL structure after remove from outnet tcp reuse tree, - * because the c->ssl null or not is used for sorting in the tree */ - if(pend->c->ssl) { -#ifdef HAVE_SSL - SSL_shutdown(pend->c->ssl); - SSL_free(pend->c->ssl); - pend->c->ssl = NULL; -#endif - } - comm_point_close(pend->c); - pend->reuse.cp_more_read_again = 0; - pend->reuse.cp_more_write_again = 0; - /* unlink the query and writewait list, it is part of the tree - * nodes and is deleted */ - pend->query = NULL; - pend->reuse.write_wait_first = NULL; - pend->reuse.write_wait_last = NULL; - reuse_del_readwait(&pend->reuse.tree_by_id); -} - -/** perform failure callbacks for waiting queries in reuse read rbtree */ -static void reuse_cb_readwait_for_failure(rbtree_type* tree_by_id, int err) -{ - rbnode_type* node; - if(tree_by_id->root == NULL || - tree_by_id->root == RBTREE_NULL) - return; - node = rbtree_first(tree_by_id); - while(node && node != RBTREE_NULL) { - struct waiting_tcp* w = (struct waiting_tcp*)node->key; - waiting_tcp_callback(w, NULL, err, NULL); - node = rbtree_next(node); - } -} - -/** mark the entry for being in the cb_and_decommission stage */ -static void mark_for_cb_and_decommission(rbnode_type* node, - void* ATTR_UNUSED(arg)) -{ - struct waiting_tcp* w = (struct waiting_tcp*)node->key; - /* Mark the waiting_tcp to signal later code (serviced_delete) that - * this item is part of the backed up tree_by_id and will be deleted - * later. */ - w->in_cb_and_decommission = 1; - /* Mark the serviced_query for deletion so that later code through - * callbacks (iter_clear .. outnet_serviced_query_stop) won't - * prematurely delete it. */ - if(w->cb) - ((struct serviced_query*)w->cb_arg)->to_be_deleted = 1; -} - -/** perform callbacks for failure and also decommission pending tcp. - * the callbacks remove references in sq->pending to the waiting_tcp - * members of the tree_by_id in the pending tcp. The pending_tcp is - * removed before the callbacks, so that the callbacks do not modify - * the pending_tcp due to its reference in the outside_network reuse tree */ -static void reuse_cb_and_decommission(struct outside_network* outnet, - struct pending_tcp* pend, int error) -{ - rbtree_type store; - store = pend->reuse.tree_by_id; - pend->query = NULL; - rbtree_init(&pend->reuse.tree_by_id, reuse_id_cmp); - pend->reuse.write_wait_first = NULL; - pend->reuse.write_wait_last = NULL; - decommission_pending_tcp(outnet, pend); - if(store.root != NULL && store.root != RBTREE_NULL) { - traverse_postorder(&store, &mark_for_cb_and_decommission, NULL); - } - reuse_cb_readwait_for_failure(&store, error); - reuse_del_readwait(&store); -} - -/** set timeout on tcp fd and setup read event to catch incoming dns msgs */ -static void -reuse_tcp_setup_timeout(struct pending_tcp* pend_tcp, int tcp_reuse_timeout) -{ - log_reuse_tcp(VERB_CLIENT, "reuse_tcp_setup_timeout", &pend_tcp->reuse); - comm_point_start_listening(pend_tcp->c, -1, tcp_reuse_timeout); -} - -/** set timeout on tcp fd and setup read event to catch incoming dns msgs */ -static void -reuse_tcp_setup_read_and_timeout(struct pending_tcp* pend_tcp, int tcp_reuse_timeout) -{ - log_reuse_tcp(VERB_CLIENT, "reuse_tcp_setup_readtimeout", &pend_tcp->reuse); - sldns_buffer_clear(pend_tcp->c->buffer); - pend_tcp->c->tcp_is_reading = 1; - pend_tcp->c->tcp_byte_count = 0; - comm_point_stop_listening(pend_tcp->c); - comm_point_start_listening(pend_tcp->c, -1, tcp_reuse_timeout); -} - -int -outnet_tcp_cb(struct comm_point* c, void* arg, int error, - struct comm_reply *reply_info) -{ - struct pending_tcp* pend = (struct pending_tcp*)arg; - struct outside_network* outnet = pend->reuse.outnet; - struct waiting_tcp* w = NULL; - log_assert(pend->reuse.item_on_lru_list && pend->reuse.node.key); - verbose(VERB_ALGO, "outnettcp cb"); - if(error == NETEVENT_TIMEOUT) { - if(pend->c->tcp_write_and_read) { - verbose(VERB_QUERY, "outnettcp got tcp timeout " - "for read, ignored because write underway"); - /* if we are writing, ignore readtimer, wait for write timer - * or write is done */ - return 0; - } else { - verbose(VERB_QUERY, "outnettcp got tcp timeout %s", - (pend->reuse.tree_by_id.count?"for reading pkt": - "for keepalive for reuse")); - } - /* must be timeout for reading or keepalive reuse, - * close it. */ - reuse_tcp_remove_tree_list(outnet, &pend->reuse); - } else if(error == NETEVENT_PKT_WRITTEN) { - /* the packet we want to write has been written. */ - verbose(VERB_ALGO, "outnet tcp pkt was written event"); - log_assert(c == pend->c); - log_assert(pend->query->pkt == pend->c->tcp_write_pkt); - log_assert(pend->query->pkt_len == pend->c->tcp_write_pkt_len); - pend->c->tcp_write_pkt = NULL; - pend->c->tcp_write_pkt_len = 0; - /* the pend.query is already in tree_by_id */ - log_assert(pend->query->id_node.key); - pend->query = NULL; - /* setup to write next packet or setup read timeout */ - if(pend->reuse.write_wait_first) { - verbose(VERB_ALGO, "outnet tcp setup next pkt"); - /* we can write it straight away perhaps, set flag - * because this callback called after a tcp write - * succeeded and likely more buffer space is available - * and we can write some more. */ - pend->reuse.cp_more_write_again = 1; - pend->query = reuse_write_wait_pop(&pend->reuse); - comm_point_stop_listening(pend->c); - outnet_tcp_take_query_setup(pend->c->fd, pend, - pend->query); - } else { - verbose(VERB_ALGO, "outnet tcp writes done, wait"); - pend->c->tcp_write_and_read = 0; - pend->reuse.cp_more_read_again = 0; - pend->reuse.cp_more_write_again = 0; - pend->c->tcp_is_reading = 1; - comm_point_stop_listening(pend->c); - reuse_tcp_setup_timeout(pend, outnet->tcp_reuse_timeout); - } - return 0; - } else if(error != NETEVENT_NOERROR) { - verbose(VERB_QUERY, "outnettcp got tcp error %d", error); - reuse_move_writewait_away(outnet, pend); - /* pass error below and exit */ - } else { - /* check ID */ - if(sldns_buffer_limit(c->buffer) < sizeof(uint16_t)) { - log_addr(VERB_QUERY, - "outnettcp: bad ID in reply, too short, from:", - &pend->reuse.addr, pend->reuse.addrlen); - error = NETEVENT_CLOSED; - } else { - uint16_t id = LDNS_ID_WIRE(sldns_buffer_begin( - c->buffer)); - /* find the query the reply is for */ - w = reuse_tcp_by_id_find(&pend->reuse, id); - /* Make sure that the reply we got is at least for a - * sent query with the same ID; the waiting_tcp that - * gets a reply is assumed to not be waiting to be - * sent. */ - if(w && (w->on_tcp_waiting_list || w->write_wait_queued)) - w = NULL; - } - } - if(error == NETEVENT_NOERROR && !w) { - /* no struct waiting found in tree, no reply to call */ - log_addr(VERB_QUERY, "outnettcp: bad ID in reply, from:", - &pend->reuse.addr, pend->reuse.addrlen); - error = NETEVENT_CLOSED; - } - if(error == NETEVENT_NOERROR) { - /* add to reuse tree so it can be reused, if not a failure. - * This is possible if the state machine wants to make a tcp - * query again to the same destination. */ - if(outnet->tcp_reuse.count < outnet->tcp_reuse_max) { - (void)reuse_tcp_insert(outnet, pend); - } - } - if(w) { - log_assert(!w->on_tcp_waiting_list); - log_assert(!w->write_wait_queued); - reuse_tree_by_id_delete(&pend->reuse, w); - verbose(VERB_CLIENT, "outnet tcp callback query err %d buflen %d", - error, (int)sldns_buffer_limit(c->buffer)); - waiting_tcp_callback(w, c, error, reply_info); - waiting_tcp_delete(w); - } - verbose(VERB_CLIENT, "outnet_tcp_cb reuse after cb"); - if(error == NETEVENT_NOERROR && pend->reuse.node.key) { - verbose(VERB_CLIENT, "outnet_tcp_cb reuse after cb: keep it"); - /* it is in the reuse_tcp tree, with other queries, or - * on the empty list. do not decommission it */ - /* if there are more outstanding queries, we could try to - * read again, to see if it is on the input, - * because this callback called after a successful read - * and there could be more bytes to read on the input */ - if(pend->reuse.tree_by_id.count != 0) - pend->reuse.cp_more_read_again = 1; - reuse_tcp_setup_read_and_timeout(pend, outnet->tcp_reuse_timeout); - return 0; - } - verbose(VERB_CLIENT, "outnet_tcp_cb reuse after cb: decommission it"); - /* no queries on it, no space to keep it. or timeout or closed due - * to error. Close it */ - reuse_cb_and_decommission(outnet, pend, (error==NETEVENT_TIMEOUT? - NETEVENT_TIMEOUT:NETEVENT_CLOSED)); - use_free_buffer(outnet); - return 0; -} - -/** lower use count on pc, see if it can be closed */ -static void -portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc) -{ - struct port_if* pif; - pc->num_outstanding--; - if(pc->num_outstanding > 0) { - return; - } - /* close it and replace in unused list */ - verbose(VERB_ALGO, "close of port %d", pc->number); - comm_point_close(pc->cp); - pif = pc->pif; - log_assert(pif->inuse > 0); -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - pif->avail_ports[pif->avail_total - pif->inuse] = pc->number; -#endif - pif->inuse--; - pif->out[pc->index] = pif->out[pif->inuse]; - pif->out[pc->index]->index = pc->index; - pc->next = outnet->unused_fds; - outnet->unused_fds = pc; -} - -/** try to send waiting UDP queries */ -static void -outnet_send_wait_udp(struct outside_network* outnet) -{ - struct pending* pend; - /* process waiting queries */ - while(outnet->udp_wait_first && outnet->unused_fds - && !outnet->want_to_quit) { - pend = outnet->udp_wait_first; - outnet->udp_wait_first = pend->next_waiting; - if(!pend->next_waiting) outnet->udp_wait_last = NULL; - sldns_buffer_clear(outnet->udp_buff); - sldns_buffer_write(outnet->udp_buff, pend->pkt, pend->pkt_len); - sldns_buffer_flip(outnet->udp_buff); - free(pend->pkt); /* freeing now makes get_mem correct */ - pend->pkt = NULL; - pend->pkt_len = 0; - log_assert(!pend->sq->busy); - pend->sq->busy = 1; - if(!randomize_and_send_udp(pend, outnet->udp_buff, - pend->timeout)) { - /* callback error on pending */ - if(pend->cb) { - fptr_ok(fptr_whitelist_pending_udp(pend->cb)); - (void)(*pend->cb)(outnet->unused_fds->cp, pend->cb_arg, - NETEVENT_CLOSED, NULL); - } - pending_delete(outnet, pend); - } else { - pend->sq->busy = 0; - } - } -} - -int -outnet_udp_cb(struct comm_point* c, void* arg, int error, - struct comm_reply *reply_info) -{ - struct outside_network* outnet = (struct outside_network*)arg; - struct pending key; - struct pending* p; - verbose(VERB_ALGO, "answer cb"); - - if(error != NETEVENT_NOERROR) { - verbose(VERB_QUERY, "outnetudp got udp error %d", error); - return 0; - } - if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { - verbose(VERB_QUERY, "outnetudp udp too short"); - return 0; - } - log_assert(reply_info); - - /* setup lookup key */ - key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer)); - memcpy(&key.addr, &reply_info->remote_addr, reply_info->remote_addrlen); - key.addrlen = reply_info->remote_addrlen; - verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id); - log_addr(VERB_ALGO, "Incoming reply addr =", - &reply_info->remote_addr, reply_info->remote_addrlen); - - /* find it, see if this thing is a valid query response */ - verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count); - p = (struct pending*)rbtree_search(outnet->pending, &key); - if(!p) { - verbose(VERB_QUERY, "received unwanted or unsolicited udp reply dropped."); - log_buf(VERB_ALGO, "dropped message", c->buffer); - outnet->unwanted_replies++; - if(outnet->unwanted_threshold && ++outnet->unwanted_total - >= outnet->unwanted_threshold) { - log_warn("unwanted reply total reached threshold (%u)" - " you may be under attack." - " defensive action: clearing the cache", - (unsigned)outnet->unwanted_threshold); - fptr_ok(fptr_whitelist_alloc_cleanup( - outnet->unwanted_action)); - (*outnet->unwanted_action)(outnet->unwanted_param); - outnet->unwanted_total = 0; - } - return 0; - } - - verbose(VERB_ALGO, "received udp reply."); - log_buf(VERB_ALGO, "udp message", c->buffer); - if(p->pc->cp != c) { - verbose(VERB_QUERY, "received reply id,addr on wrong port. " - "dropped."); - outnet->unwanted_replies++; - if(outnet->unwanted_threshold && ++outnet->unwanted_total - >= outnet->unwanted_threshold) { - log_warn("unwanted reply total reached threshold (%u)" - " you may be under attack." - " defensive action: clearing the cache", - (unsigned)outnet->unwanted_threshold); - fptr_ok(fptr_whitelist_alloc_cleanup( - outnet->unwanted_action)); - (*outnet->unwanted_action)(outnet->unwanted_param); - outnet->unwanted_total = 0; - } - return 0; - } - comm_timer_disable(p->timer); - verbose(VERB_ALGO, "outnet handle udp reply"); - /* delete from tree first in case callback creates a retry */ - (void)rbtree_delete(outnet->pending, p->node.key); - if(p->cb) { - fptr_ok(fptr_whitelist_pending_udp(p->cb)); - (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_NOERROR, reply_info); - } - portcomm_loweruse(outnet, p->pc); - pending_delete(NULL, p); - outnet_send_wait_udp(outnet); - return 0; -} - -/** calculate number of ip4 and ip6 interfaces*/ -static void -calc_num46(char** ifs, int num_ifs, int do_ip4, int do_ip6, - int* num_ip4, int* num_ip6) -{ - int i; - *num_ip4 = 0; - *num_ip6 = 0; - if(num_ifs <= 0) { - if(do_ip4) - *num_ip4 = 1; - if(do_ip6) - *num_ip6 = 1; - return; - } - for(i=0; ioutnet; - verbose(VERB_ALGO, "timeout udp with delay"); - portcomm_loweruse(outnet, p->pc); - pending_delete(outnet, p); - outnet_send_wait_udp(outnet); -} - -void -pending_udp_timer_cb(void *arg) -{ - struct pending* p = (struct pending*)arg; - struct outside_network* outnet = p->outnet; - /* it timed out */ - verbose(VERB_ALGO, "timeout udp"); - if(p->cb) { - fptr_ok(fptr_whitelist_pending_udp(p->cb)); - (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_TIMEOUT, NULL); - } - /* if delayclose, keep port open for a longer time. - * But if the udpwaitlist exists, then we are struggling to - * keep up with demand for sockets, so do not wait, but service - * the customer (customer service more important than portICMPs) */ - if(outnet->delayclose && !outnet->udp_wait_first) { - p->cb = NULL; - p->timer->callback = &pending_udp_timer_delay_cb; - comm_timer_set(p->timer, &outnet->delay_tv); - return; - } - portcomm_loweruse(outnet, p->pc); - pending_delete(outnet, p); - outnet_send_wait_udp(outnet); -} - -/** create pending_tcp buffers */ -static int -create_pending_tcp(struct outside_network* outnet, size_t bufsize) -{ - size_t i; - if(outnet->num_tcp == 0) - return 1; /* no tcp needed, nothing to do */ - if(!(outnet->tcp_conns = (struct pending_tcp **)calloc( - outnet->num_tcp, sizeof(struct pending_tcp*)))) - return 0; - for(i=0; inum_tcp; i++) { - if(!(outnet->tcp_conns[i] = (struct pending_tcp*)calloc(1, - sizeof(struct pending_tcp)))) - return 0; - outnet->tcp_conns[i]->next_free = outnet->tcp_free; - outnet->tcp_free = outnet->tcp_conns[i]; - outnet->tcp_conns[i]->c = comm_point_create_tcp_out( - outnet->base, bufsize, outnet_tcp_cb, - outnet->tcp_conns[i]); - if(!outnet->tcp_conns[i]->c) - return 0; - } - return 1; -} - -/** setup an outgoing interface, ready address */ -static int setup_if(struct port_if* pif, const char* addrstr, - int* avail, int numavail, size_t numfd) -{ -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - pif->avail_total = numavail; - pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int)); - if(!pif->avail_ports) - return 0; -#endif - if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) && - !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT, - &pif->addr, &pif->addrlen, &pif->pfxlen)) - return 0; - pif->maxout = (int)numfd; - pif->inuse = 0; - pif->out = (struct port_comm**)calloc(numfd, - sizeof(struct port_comm*)); - if(!pif->out) - return 0; - return 1; -} - -struct outside_network* -outside_network_create(struct comm_base *base, size_t bufsize, - size_t num_ports, char** ifs, int num_ifs, int do_ip4, - int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra, - struct ub_randstate* rnd, int use_caps_for_id, int* availports, - int numavailports, size_t unwanted_threshold, int tcp_mss, - void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv, - int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout, - int tcp_auth_query_timeout) -{ - struct outside_network* outnet = (struct outside_network*) - calloc(1, sizeof(struct outside_network)); - size_t k; - if(!outnet) { - log_err("malloc failed"); - return NULL; - } - comm_base_timept(base, &outnet->now_secs, &outnet->now_tv); - outnet->base = base; - outnet->num_tcp = num_tcp; - outnet->max_reuse_tcp_queries = max_reuse_tcp_queries; - outnet->tcp_reuse_timeout= tcp_reuse_timeout; - outnet->tcp_auth_query_timeout = tcp_auth_query_timeout; - outnet->num_tcp_outgoing = 0; - outnet->num_udp_outgoing = 0; - outnet->infra = infra; - outnet->rnd = rnd; - outnet->sslctx = sslctx; - outnet->tls_use_sni = tls_use_sni; -#ifdef USE_DNSTAP - outnet->dtenv = dtenv; -#else - (void)dtenv; -#endif - outnet->svcd_overhead = 0; - outnet->want_to_quit = 0; - outnet->unwanted_threshold = unwanted_threshold; - outnet->unwanted_action = unwanted_action; - outnet->unwanted_param = unwanted_param; - outnet->use_caps_for_id = use_caps_for_id; - outnet->do_udp = do_udp; - outnet->tcp_mss = tcp_mss; - outnet->ip_dscp = dscp; -#ifndef S_SPLINT_S - if(delayclose) { - outnet->delayclose = 1; - outnet->delay_tv.tv_sec = delayclose/1000; - outnet->delay_tv.tv_usec = (delayclose%1000)*1000; - } -#endif - if(udp_connect) { - outnet->udp_connect = 1; - } - if(numavailports == 0 || num_ports == 0) { - log_err("no outgoing ports available"); - outside_network_delete(outnet); - return NULL; - } -#ifndef INET6 - do_ip6 = 0; -#endif - calc_num46(ifs, num_ifs, do_ip4, do_ip6, - &outnet->num_ip4, &outnet->num_ip6); - if(outnet->num_ip4 != 0) { - if(!(outnet->ip4_ifs = (struct port_if*)calloc( - (size_t)outnet->num_ip4, sizeof(struct port_if)))) { - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - } - if(outnet->num_ip6 != 0) { - if(!(outnet->ip6_ifs = (struct port_if*)calloc( - (size_t)outnet->num_ip6, sizeof(struct port_if)))) { - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - } - if( !(outnet->udp_buff = sldns_buffer_new(bufsize)) || - !(outnet->pending = rbtree_create(pending_cmp)) || - !(outnet->serviced = rbtree_create(serviced_cmp)) || - !create_pending_tcp(outnet, bufsize)) { - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - rbtree_init(&outnet->tcp_reuse, reuse_cmp); - outnet->tcp_reuse_max = num_tcp; - - /* allocate commpoints */ - for(k=0; kcp = comm_point_create_udp(outnet->base, -1, - outnet->udp_buff, 0, outnet_udp_cb, outnet, NULL); - if(!pc->cp) { - log_err("malloc failed"); - free(pc); - outside_network_delete(outnet); - return NULL; - } - pc->next = outnet->unused_fds; - outnet->unused_fds = pc; - } - - /* allocate interfaces */ - if(num_ifs == 0) { - if(do_ip4 && !setup_if(&outnet->ip4_ifs[0], "0.0.0.0", - availports, numavailports, num_ports)) { - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - if(do_ip6 && !setup_if(&outnet->ip6_ifs[0], "::", - availports, numavailports, num_ports)) { - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - } else { - size_t done_4 = 0, done_6 = 0; - int i; - for(i=0; iip6_ifs[done_6], ifs[i], - availports, numavailports, num_ports)){ - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - done_6++; - } - if(!str_is_ip6(ifs[i]) && do_ip4) { - if(!setup_if(&outnet->ip4_ifs[done_4], ifs[i], - availports, numavailports, num_ports)){ - log_err("malloc failed"); - outside_network_delete(outnet); - return NULL; - } - done_4++; - } - } - } - return outnet; -} - -/** helper pending delete */ -static void -pending_node_del(rbnode_type* node, void* arg) -{ - struct pending* pend = (struct pending*)node; - struct outside_network* outnet = (struct outside_network*)arg; - pending_delete(outnet, pend); -} - -/** helper serviced delete */ -static void -serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg)) -{ - struct serviced_query* sq = (struct serviced_query*)node; - alloc_reg_release(sq->alloc, sq->region); - if(sq->timer) - comm_timer_delete(sq->timer); - free(sq); -} - -void -outside_network_quit_prepare(struct outside_network* outnet) -{ - if(!outnet) - return; - /* prevent queued items from being sent */ - outnet->want_to_quit = 1; -} - -void -outside_network_delete(struct outside_network* outnet) -{ - if(!outnet) - return; - outnet->want_to_quit = 1; - /* check every element, since we can be called on malloc error */ - if(outnet->pending) { - /* free pending elements, but do no unlink from tree. */ - traverse_postorder(outnet->pending, pending_node_del, NULL); - free(outnet->pending); - } - if(outnet->serviced) { - traverse_postorder(outnet->serviced, serviced_node_del, NULL); - free(outnet->serviced); - } - if(outnet->udp_buff) - sldns_buffer_free(outnet->udp_buff); - if(outnet->unused_fds) { - struct port_comm* p = outnet->unused_fds, *np; - while(p) { - np = p->next; - comm_point_delete(p->cp); - free(p); - p = np; - } - outnet->unused_fds = NULL; - } - if(outnet->ip4_ifs) { - int i, k; - for(i=0; inum_ip4; i++) { - for(k=0; kip4_ifs[i].inuse; k++) { - struct port_comm* pc = outnet->ip4_ifs[i]. - out[k]; - comm_point_delete(pc->cp); - free(pc); - } -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - free(outnet->ip4_ifs[i].avail_ports); -#endif - free(outnet->ip4_ifs[i].out); - } - free(outnet->ip4_ifs); - } - if(outnet->ip6_ifs) { - int i, k; - for(i=0; inum_ip6; i++) { - for(k=0; kip6_ifs[i].inuse; k++) { - struct port_comm* pc = outnet->ip6_ifs[i]. - out[k]; - comm_point_delete(pc->cp); - free(pc); - } -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - free(outnet->ip6_ifs[i].avail_ports); -#endif - free(outnet->ip6_ifs[i].out); - } - free(outnet->ip6_ifs); - } - if(outnet->tcp_conns) { - size_t i; - for(i=0; inum_tcp; i++) - if(outnet->tcp_conns[i]) { - struct pending_tcp* pend; - pend = outnet->tcp_conns[i]; - if(pend->reuse.item_on_lru_list) { - /* delete waiting_tcp elements that - * the tcp conn is working on */ - decommission_pending_tcp(outnet, pend); - } - comm_point_delete(outnet->tcp_conns[i]->c); - free(outnet->tcp_conns[i]); - outnet->tcp_conns[i] = NULL; - } - free(outnet->tcp_conns); - outnet->tcp_conns = NULL; - } - if(outnet->tcp_wait_first) { - struct waiting_tcp* p = outnet->tcp_wait_first, *np; - while(p) { - np = p->next_waiting; - waiting_tcp_delete(p); - p = np; - } - } - /* was allocated in struct pending that was deleted above */ - rbtree_init(&outnet->tcp_reuse, reuse_cmp); - outnet->tcp_reuse_first = NULL; - outnet->tcp_reuse_last = NULL; - if(outnet->udp_wait_first) { - struct pending* p = outnet->udp_wait_first, *np; - while(p) { - np = p->next_waiting; - pending_delete(NULL, p); - p = np; - } - } - free(outnet); -} - -void -pending_delete(struct outside_network* outnet, struct pending* p) -{ - if(!p) - return; - if(outnet && outnet->udp_wait_first && - (p->next_waiting || p == outnet->udp_wait_last) ) { - /* delete from waiting list, if it is in the waiting list */ - struct pending* prev = NULL, *x = outnet->udp_wait_first; - while(x && x != p) { - prev = x; - x = x->next_waiting; - } - if(x) { - log_assert(x == p); - if(prev) - prev->next_waiting = p->next_waiting; - else outnet->udp_wait_first = p->next_waiting; - if(outnet->udp_wait_last == p) - outnet->udp_wait_last = prev; - } - } - if(outnet) { - (void)rbtree_delete(outnet->pending, p->node.key); - } - if(p->timer) - comm_timer_delete(p->timer); - free(p->pkt); - free(p); -} - -static void -sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd) -{ - int i, last; - if(!(pfxlen > 0 && pfxlen < 128)) - return; - for(i = 0; i < (128 - pfxlen) / 8; i++) { - sa->sin6_addr.s6_addr[15-i] = (uint8_t)ub_random_max(rnd, 256); - } - last = pfxlen & 7; - if(last != 0) { - sa->sin6_addr.s6_addr[15-i] |= - ((0xFF >> last) & ub_random_max(rnd, 256)); - } -} - -/** - * Try to open a UDP socket for outgoing communication. - * Sets sockets options as needed. - * @param addr: socket address. - * @param addrlen: length of address. - * @param pfxlen: length of network prefix (for address randomisation). - * @param port: port override for addr. - * @param inuse: if -1 is returned, this bool means the port was in use. - * @param rnd: random state (for address randomisation). - * @param dscp: DSCP to use. - * @return fd or -1 - */ -static int -udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen, - int port, int* inuse, struct ub_randstate* rnd, int dscp) -{ - int fd, noproto; - if(addr_is_ip6(addr, addrlen)) { - int freebind = 0; - struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr; - sa.sin6_port = (in_port_t)htons((uint16_t)port); - sa.sin6_flowinfo = 0; - sa.sin6_scope_id = 0; - if(pfxlen != 0) { - freebind = 1; - sai6_putrandom(&sa, pfxlen, rnd); - } - fd = create_udp_sock(AF_INET6, SOCK_DGRAM, - (struct sockaddr*)&sa, addrlen, 1, inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0, dscp); - } else { - struct sockaddr_in* sa = (struct sockaddr_in*)addr; - sa->sin_port = (in_port_t)htons((uint16_t)port); - fd = create_udp_sock(AF_INET, SOCK_DGRAM, - (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0, 0, NULL, 0, 0, 0, dscp); - } - return fd; -} - -/** Select random ID */ -static int -select_id(struct outside_network* outnet, struct pending* pend, - sldns_buffer* packet) -{ - int id_tries = 0; - pend->id = GET_RANDOM_ID(outnet->rnd); - LDNS_ID_SET(sldns_buffer_begin(packet), pend->id); - - /* insert in tree */ - pend->node.key = pend; - while(!rbtree_insert(outnet->pending, &pend->node)) { - /* change ID to avoid collision */ - pend->id = GET_RANDOM_ID(outnet->rnd); - LDNS_ID_SET(sldns_buffer_begin(packet), pend->id); - id_tries++; - if(id_tries == MAX_ID_RETRY) { - pend->id=99999; /* non existent ID */ - log_err("failed to generate unique ID, drop msg"); - return 0; - } - } - verbose(VERB_ALGO, "inserted new pending reply id=%4.4x", pend->id); - return 1; -} - -/** return true is UDP connect error needs to be logged */ -static int udp_connect_needs_log(int err) -{ - switch(err) { - case ECONNREFUSED: -# ifdef ENETUNREACH - case ENETUNREACH: -# endif -# ifdef EHOSTDOWN - case EHOSTDOWN: -# endif -# ifdef EHOSTUNREACH - case EHOSTUNREACH: -# endif -# ifdef ENETDOWN - case ENETDOWN: -# endif -# ifdef EADDRNOTAVAIL - case EADDRNOTAVAIL: -# endif - case EPERM: - case EACCES: - if(verbosity >= VERB_ALGO) - return 1; - return 0; - default: - break; - } - return 1; -} - - -/** Select random interface and port */ -static int -select_ifport(struct outside_network* outnet, struct pending* pend, - int num_if, struct port_if* ifs) -{ - int my_if, my_port, fd, portno, inuse, tries=0; - struct port_if* pif; - /* randomly select interface and port */ - if(num_if == 0) { - verbose(VERB_QUERY, "Need to send query but have no " - "outgoing interfaces of that family"); - return 0; - } - log_assert(outnet->unused_fds); - tries = 0; - while(1) { - my_if = ub_random_max(outnet->rnd, num_if); - pif = &ifs[my_if]; -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - if(outnet->udp_connect) { - /* if we connect() we cannot reuse fds for a port */ - if(pif->inuse >= pif->avail_total) { - tries++; - if(tries < MAX_PORT_RETRY) - continue; - log_err("failed to find an open port, drop msg"); - return 0; - } - my_port = pif->inuse + ub_random_max(outnet->rnd, - pif->avail_total - pif->inuse); - } else { - my_port = ub_random_max(outnet->rnd, pif->avail_total); - if(my_port < pif->inuse) { - /* port already open */ - pend->pc = pif->out[my_port]; - verbose(VERB_ALGO, "using UDP if=%d port=%d", - my_if, pend->pc->number); - break; - } - } - /* try to open new port, if fails, loop to try again */ - log_assert(pif->inuse < pif->maxout); - portno = pif->avail_ports[my_port - pif->inuse]; -#else - my_port = portno = 0; -#endif - fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen, - portno, &inuse, outnet->rnd, outnet->ip_dscp); - if(fd == -1 && !inuse) { - /* nonrecoverable error making socket */ - return 0; - } - if(fd != -1) { - verbose(VERB_ALGO, "opened UDP if=%d port=%d", - my_if, portno); - if(outnet->udp_connect) { - /* connect() to the destination */ - if(connect(fd, (struct sockaddr*)&pend->addr, - pend->addrlen) < 0) { - if(udp_connect_needs_log(errno)) { - log_err_addr("udp connect failed", - strerror(errno), &pend->addr, - pend->addrlen); - } - sock_close(fd); - return 0; - } - } - /* grab fd */ - pend->pc = outnet->unused_fds; - outnet->unused_fds = pend->pc->next; - - /* setup portcomm */ - pend->pc->next = NULL; - pend->pc->number = portno; - pend->pc->pif = pif; - pend->pc->index = pif->inuse; - pend->pc->num_outstanding = 0; - comm_point_start_listening(pend->pc->cp, fd, -1); - - /* grab port in interface */ - pif->out[pif->inuse] = pend->pc; -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - pif->avail_ports[my_port - pif->inuse] = - pif->avail_ports[pif->avail_total-pif->inuse-1]; -#endif - pif->inuse++; - break; - } - /* failed, already in use */ - verbose(VERB_QUERY, "port %d in use, trying another", portno); - tries++; - if(tries == MAX_PORT_RETRY) { - log_err("failed to find an open port, drop msg"); - return 0; - } - } - log_assert(pend->pc); - pend->pc->num_outstanding++; - - return 1; -} - -static int -randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) -{ - struct timeval tv; - struct outside_network* outnet = pend->sq->outnet; - - /* select id */ - if(!select_id(outnet, pend, packet)) { - return 0; - } - - /* select src_if, port */ - if(addr_is_ip6(&pend->addr, pend->addrlen)) { - if(!select_ifport(outnet, pend, - outnet->num_ip6, outnet->ip6_ifs)) - return 0; - } else { - if(!select_ifport(outnet, pend, - outnet->num_ip4, outnet->ip4_ifs)) - return 0; - } - log_assert(pend->pc && pend->pc->cp); - - /* send it over the commlink */ - if(!comm_point_send_udp_msg(pend->pc->cp, packet, - (struct sockaddr*)&pend->addr, pend->addrlen, outnet->udp_connect)) { - portcomm_loweruse(outnet, pend->pc); - return 0; - } - outnet->num_udp_outgoing++; - - /* system calls to set timeout after sending UDP to make roundtrip - smaller. */ -#ifndef S_SPLINT_S - tv.tv_sec = timeout/1000; - tv.tv_usec = (timeout%1000)*1000; -#endif - comm_timer_set(pend->timer, &tv); - -#ifdef USE_DNSTAP - /* - * sending src (local service)/dst (upstream) addresses over DNSTAP - * There are no chances to get the src (local service) addr if unbound - * is not configured with specific outgoing IP-addresses. So we will - * pass 0.0.0.0 (::) to argument for - * dt_msg_send_outside_query()/dt_msg_send_outside_response() calls. - */ - if(outnet->dtenv && - (outnet->dtenv->log_resolver_query_messages || - outnet->dtenv->log_forwarder_query_messages)) { - log_addr(VERB_ALGO, "from local addr", &pend->pc->pif->addr, pend->pc->pif->addrlen); - log_addr(VERB_ALGO, "request to upstream", &pend->addr, pend->addrlen); - dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp, - pend->sq->zone, pend->sq->zonelen, packet); - } -#endif - return 1; -} - -struct pending* -pending_udp_query(struct serviced_query* sq, struct sldns_buffer* packet, - int timeout, comm_point_callback_type* cb, void* cb_arg) -{ - struct pending* pend = (struct pending*)calloc(1, sizeof(*pend)); - if(!pend) return NULL; - pend->outnet = sq->outnet; - pend->sq = sq; - pend->addrlen = sq->addrlen; - memmove(&pend->addr, &sq->addr, sq->addrlen); - pend->cb = cb; - pend->cb_arg = cb_arg; - pend->node.key = pend; - pend->timer = comm_timer_create(sq->outnet->base, pending_udp_timer_cb, - pend); - if(!pend->timer) { - free(pend); - return NULL; - } - - if(sq->outnet->unused_fds == NULL) { - /* no unused fd, cannot create a new port (randomly) */ - verbose(VERB_ALGO, "no fds available, udp query waiting"); - pend->timeout = timeout; - pend->pkt_len = sldns_buffer_limit(packet); - pend->pkt = (uint8_t*)memdup(sldns_buffer_begin(packet), - pend->pkt_len); - if(!pend->pkt) { - comm_timer_delete(pend->timer); - free(pend); - return NULL; - } - /* put at end of waiting list */ - if(sq->outnet->udp_wait_last) - sq->outnet->udp_wait_last->next_waiting = pend; - else - sq->outnet->udp_wait_first = pend; - sq->outnet->udp_wait_last = pend; - return pend; - } - log_assert(!sq->busy); - sq->busy = 1; - if(!randomize_and_send_udp(pend, packet, timeout)) { - pending_delete(sq->outnet, pend); - return NULL; - } - sq->busy = 0; - return pend; -} - -void -outnet_tcptimer(void* arg) -{ - struct waiting_tcp* w = (struct waiting_tcp*)arg; - struct outside_network* outnet = w->outnet; - verbose(VERB_CLIENT, "outnet_tcptimer"); - if(w->on_tcp_waiting_list) { - /* it is on the waiting list */ - outnet_waiting_tcp_list_remove(outnet, w); - waiting_tcp_callback(w, NULL, NETEVENT_TIMEOUT, NULL); - waiting_tcp_delete(w); - } else { - /* it was in use */ - struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting; - reuse_cb_and_decommission(outnet, pend, NETEVENT_TIMEOUT); - } - use_free_buffer(outnet); -} - -/** close the oldest reuse_tcp connection to make a fd and struct pend - * available for a new stream connection */ -static void -reuse_tcp_close_oldest(struct outside_network* outnet) -{ - struct reuse_tcp* reuse; - verbose(VERB_CLIENT, "reuse_tcp_close_oldest"); - reuse = reuse_tcp_lru_snip(outnet); - if(!reuse) return; - /* free up */ - reuse_cb_and_decommission(outnet, reuse->pending, NETEVENT_CLOSED); -} - -static uint16_t -tcp_select_id(struct outside_network* outnet, struct reuse_tcp* reuse) -{ - if(reuse) - return reuse_tcp_select_id(reuse, outnet); - return GET_RANDOM_ID(outnet->rnd); -} - -/** find spare ID value for reuse tcp stream. That is random and also does - * not collide with an existing query ID that is in use or waiting */ -uint16_t -reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet) -{ - uint16_t id = 0, curid, nextid; - const int try_random = 2000; - int i; - unsigned select, count, space; - rbnode_type* node; - - /* make really sure the tree is not empty */ - if(reuse->tree_by_id.count == 0) { - id = GET_RANDOM_ID(outnet->rnd); - return id; - } - - /* try to find random empty spots by picking them */ - for(i = 0; irnd); - if(!reuse_tcp_by_id_find(reuse, id)) { - return id; - } - } - - /* equally pick a random unused element from the tree that is - * not in use. Pick a the n-th index of an unused number, - * then loop over the empty spaces in the tree and find it */ - log_assert(reuse->tree_by_id.count < 0xffff); - select = ub_random_max(outnet->rnd, 0xffff - reuse->tree_by_id.count); - /* select value now in 0 .. num free - 1 */ - - count = 0; /* number of free spaces passed by */ - node = rbtree_first(&reuse->tree_by_id); - log_assert(node && node != RBTREE_NULL); /* tree not empty */ - /* see if select is before first node */ - if(select < (unsigned)tree_by_id_get_id(node)) - return select; - count += tree_by_id_get_id(node); - /* perhaps select is between nodes */ - while(node && node != RBTREE_NULL) { - rbnode_type* next = rbtree_next(node); - if(next && next != RBTREE_NULL) { - curid = tree_by_id_get_id(node); - nextid = tree_by_id_get_id(next); - log_assert(curid < nextid); - if(curid != 0xffff && curid + 1 < nextid) { - /* space between nodes */ - space = nextid - curid - 1; - log_assert(select >= count); - if(select < count + space) { - /* here it is */ - return curid + 1 + (select - count); - } - count += space; - } - } - node = next; - } - - /* select is after the last node */ - /* count is the number of free positions before the nodes in the - * tree */ - node = rbtree_last(&reuse->tree_by_id); - log_assert(node && node != RBTREE_NULL); /* tree not empty */ - curid = tree_by_id_get_id(node); - log_assert(count + (0xffff-curid) + reuse->tree_by_id.count == 0xffff); - return curid + 1 + (select - count); -} - -struct waiting_tcp* -pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, - int timeout, comm_point_callback_type* callback, void* callback_arg) -{ - struct pending_tcp* pend = sq->outnet->tcp_free; - struct reuse_tcp* reuse = NULL; - struct waiting_tcp* w; - - verbose(VERB_CLIENT, "pending_tcp_query"); - if(sldns_buffer_limit(packet) < sizeof(uint16_t)) { - verbose(VERB_ALGO, "pending tcp query with too short buffer < 2"); - return NULL; - } - - /* find out if a reused stream to the target exists */ - /* if so, take it into use */ - reuse = reuse_tcp_find(sq->outnet, &sq->addr, sq->addrlen, - sq->ssl_upstream); - if(reuse) { - log_reuse_tcp(VERB_CLIENT, "pending_tcp_query: found reuse", reuse); - log_assert(reuse->pending); - pend = reuse->pending; - reuse_tcp_lru_touch(sq->outnet, reuse); - } - - log_assert(!reuse || (reuse && pend)); - /* if !pend but we have reuse streams, close a reuse stream - * to be able to open a new one to this target, no use waiting - * to reuse a file descriptor while another query needs to use - * that buffer and file descriptor now. */ - if(!pend) { - reuse_tcp_close_oldest(sq->outnet); - pend = sq->outnet->tcp_free; - log_assert(!reuse || (pend == reuse->pending)); - } - - /* allocate space to store query */ - w = (struct waiting_tcp*)malloc(sizeof(struct waiting_tcp) - + sldns_buffer_limit(packet)); - if(!w) { - return NULL; - } - if(!(w->timer = comm_timer_create(sq->outnet->base, outnet_tcptimer, w))) { - free(w); - return NULL; - } - w->pkt = (uint8_t*)w + sizeof(struct waiting_tcp); - w->pkt_len = sldns_buffer_limit(packet); - memmove(w->pkt, sldns_buffer_begin(packet), w->pkt_len); - w->id = tcp_select_id(sq->outnet, reuse); - LDNS_ID_SET(w->pkt, w->id); - memcpy(&w->addr, &sq->addr, sq->addrlen); - w->addrlen = sq->addrlen; - w->outnet = sq->outnet; - w->on_tcp_waiting_list = 0; - w->next_waiting = NULL; - w->cb = callback; - w->cb_arg = callback_arg; - w->ssl_upstream = sq->ssl_upstream; - w->tls_auth_name = sq->tls_auth_name; - w->timeout = timeout; - w->id_node.key = NULL; - w->write_wait_prev = NULL; - w->write_wait_next = NULL; - w->write_wait_queued = 0; - w->error_count = 0; -#ifdef USE_DNSTAP - w->sq = NULL; -#endif - w->in_cb_and_decommission = 0; - if(pend) { - /* we have a buffer available right now */ - if(reuse) { - log_assert(reuse == &pend->reuse); - /* reuse existing fd, write query and continue */ - /* store query in tree by id */ - verbose(VERB_CLIENT, "pending_tcp_query: reuse, store"); - w->next_waiting = (void*)pend; - reuse_tree_by_id_insert(&pend->reuse, w); - /* can we write right now? */ - if(pend->query == NULL) { - /* write straight away */ - /* stop the timer on read of the fd */ - comm_point_stop_listening(pend->c); - pend->query = w; - outnet_tcp_take_query_setup(pend->c->fd, pend, - w); - } else { - /* put it in the waiting list for - * this stream */ - reuse_write_wait_push_back(&pend->reuse, w); - } - } else { - /* create new fd and connect to addr, setup to - * write query */ - verbose(VERB_CLIENT, "pending_tcp_query: new fd, connect"); - rbtree_init(&pend->reuse.tree_by_id, reuse_id_cmp); - pend->reuse.pending = pend; - memcpy(&pend->reuse.addr, &sq->addr, sq->addrlen); - pend->reuse.addrlen = sq->addrlen; - if(!outnet_tcp_take_into_use(w)) { - waiting_tcp_delete(w); - return NULL; - } - } -#ifdef USE_DNSTAP - if(sq->outnet->dtenv && - (sq->outnet->dtenv->log_resolver_query_messages || - sq->outnet->dtenv->log_forwarder_query_messages)) { - /* use w->pkt, because it has the ID value */ - sldns_buffer tmp; - sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len); - dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, - &pend->pi->addr, comm_tcp, sq->zone, - sq->zonelen, &tmp); - } -#endif - } else { - /* queue up */ - /* waiting for a buffer on the outside network buffer wait - * list */ - verbose(VERB_CLIENT, "pending_tcp_query: queue to wait"); -#ifdef USE_DNSTAP - w->sq = sq; -#endif - outnet_waiting_tcp_list_add(sq->outnet, w, 1); - } - return w; -} - -/** create query for serviced queries */ -static void -serviced_gen_query(sldns_buffer* buff, uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags) -{ - sldns_buffer_clear(buff); - /* skip id */ - sldns_buffer_write_u16(buff, flags); - sldns_buffer_write_u16(buff, 1); /* qdcount */ - sldns_buffer_write_u16(buff, 0); /* ancount */ - sldns_buffer_write_u16(buff, 0); /* nscount */ - sldns_buffer_write_u16(buff, 0); /* arcount */ - sldns_buffer_write(buff, qname, qnamelen); - sldns_buffer_write_u16(buff, qtype); - sldns_buffer_write_u16(buff, qclass); - sldns_buffer_flip(buff); -} - -/** lookup serviced query in serviced query rbtree */ -static struct serviced_query* -lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, - struct sockaddr_storage* addr, socklen_t addrlen, - struct edns_option* opt_list) -{ - struct serviced_query key; - key.node.key = &key; - key.qbuf = sldns_buffer_begin(buff); - key.qbuflen = sldns_buffer_limit(buff); - key.dnssec = dnssec; - memcpy(&key.addr, addr, addrlen); - key.addrlen = addrlen; - key.outnet = outnet; - key.opt_list = opt_list; - return (struct serviced_query*)rbtree_search(outnet->serviced, &key); -} - -void -serviced_timer_cb(void* arg) -{ - struct serviced_query* sq = (struct serviced_query*)arg; - struct outside_network* outnet = sq->outnet; - verbose(VERB_ALGO, "serviced send timer"); - /* By the time this cb is called, if we don't have any registered - * callbacks for this serviced_query anymore; do not send. */ - if(!sq->cblist) - goto delete; - /* perform first network action */ - if(outnet->do_udp && !(sq->tcp_upstream || sq->ssl_upstream)) { - if(!serviced_udp_send(sq, outnet->udp_buff)) - goto delete; - } else { - if(!serviced_tcp_send(sq, outnet->udp_buff)) - goto delete; - } - /* Maybe by this time we don't have callbacks attached anymore. Don't - * proactively try to delete; let it run and maybe another callback - * will get attached by the time we get an answer. */ - return; -delete: - serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL); -} - -/** Create new serviced entry */ -static struct serviced_query* -serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, - int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream, - char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int qtype, struct edns_option* opt_list, - size_t pad_queries_block_size, struct alloc_cache* alloc, - struct regional* region) -{ - struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq)); - struct timeval t; -#ifdef UNBOUND_DEBUG - rbnode_type* ins; -#endif - if(!sq) { - alloc_reg_release(alloc, region); - return NULL; - } - sq->node.key = sq; - sq->alloc = alloc; - sq->region = region; - sq->qbuf = regional_alloc_init(region, sldns_buffer_begin(buff), - sldns_buffer_limit(buff)); - if(!sq->qbuf) { - alloc_reg_release(alloc, region); - free(sq); - return NULL; - } - sq->qbuflen = sldns_buffer_limit(buff); - sq->zone = regional_alloc_init(region, zone, zonelen); - if(!sq->zone) { - alloc_reg_release(alloc, region); - free(sq); - return NULL; - } - sq->zonelen = zonelen; - sq->qtype = qtype; - sq->dnssec = dnssec; - sq->want_dnssec = want_dnssec; - sq->nocaps = nocaps; - sq->tcp_upstream = tcp_upstream; - sq->ssl_upstream = ssl_upstream; - if(tls_auth_name) { - sq->tls_auth_name = regional_strdup(region, tls_auth_name); - if(!sq->tls_auth_name) { - alloc_reg_release(alloc, region); - free(sq); - return NULL; - } - } else { - sq->tls_auth_name = NULL; - } - memcpy(&sq->addr, addr, addrlen); - sq->addrlen = addrlen; - sq->opt_list = opt_list; - sq->busy = 0; - sq->timer = comm_timer_create(outnet->base, serviced_timer_cb, sq); - if(!sq->timer) { - alloc_reg_release(alloc, region); - free(sq); - return NULL; - } - memset(&t, 0, sizeof(t)); - comm_timer_set(sq->timer, &t); - sq->outnet = outnet; - sq->cblist = NULL; - sq->pending = NULL; - sq->status = serviced_initial; - sq->retry = 0; - sq->to_be_deleted = 0; - sq->padding_block_size = pad_queries_block_size; -#ifdef UNBOUND_DEBUG - ins = -#else - (void) -#endif - rbtree_insert(outnet->serviced, &sq->node); - log_assert(ins != NULL); /* must not be already present */ - return sq; -} - -/** reuse tcp stream, remove serviced query from stream, - * return true if the stream is kept, false if it is to be closed */ -static int -reuse_tcp_remove_serviced_keep(struct waiting_tcp* w, - struct serviced_query* sq) -{ - struct pending_tcp* pend_tcp = (struct pending_tcp*)w->next_waiting; - verbose(VERB_CLIENT, "reuse_tcp_remove_serviced_keep"); - /* remove the callback. let query continue to write to not cancel - * the stream itself. also keep it as an entry in the tree_by_id, - * in case the answer returns (that we no longer want), but we cannot - * pick the same ID number meanwhile */ - w->cb = NULL; - /* see if can be entered in reuse tree - * for that the FD has to be non-1 */ - if(pend_tcp->c->fd == -1) { - verbose(VERB_CLIENT, "reuse_tcp_remove_serviced_keep: -1 fd"); - return 0; - } - /* if in tree and used by other queries */ - if(pend_tcp->reuse.node.key) { - verbose(VERB_CLIENT, "reuse_tcp_remove_serviced_keep: in use by other queries"); - /* do not reset the keepalive timer, for that - * we'd need traffic, and this is where the serviced is - * removed due to state machine internal reasons, - * eg. iterator no longer interested in this query */ - return 1; - } - /* if still open and want to keep it open */ - if(pend_tcp->c->fd != -1 && sq->outnet->tcp_reuse.count < - sq->outnet->tcp_reuse_max) { - verbose(VERB_CLIENT, "reuse_tcp_remove_serviced_keep: keep open"); - /* set a keepalive timer on it */ - if(!reuse_tcp_insert(sq->outnet, pend_tcp)) { - return 0; - } - reuse_tcp_setup_timeout(pend_tcp, sq->outnet->tcp_reuse_timeout); - return 1; - } - return 0; -} - -/** cleanup serviced query entry */ -static void -serviced_delete(struct serviced_query* sq) -{ - verbose(VERB_CLIENT, "serviced_delete"); - if(sq->pending) { - /* clear up the pending query */ - if(sq->status == serviced_query_UDP_EDNS || - sq->status == serviced_query_UDP || - sq->status == serviced_query_UDP_EDNS_FRAG || - sq->status == serviced_query_UDP_EDNS_fallback) { - struct pending* p = (struct pending*)sq->pending; - verbose(VERB_CLIENT, "serviced_delete: UDP"); - if(p->pc) - portcomm_loweruse(sq->outnet, p->pc); - pending_delete(sq->outnet, p); - /* this call can cause reentrant calls back into the - * mesh */ - outnet_send_wait_udp(sq->outnet); - } else { - struct waiting_tcp* w = (struct waiting_tcp*) - sq->pending; - verbose(VERB_CLIENT, "serviced_delete: TCP"); - log_assert(!(w->write_wait_queued && w->on_tcp_waiting_list)); - /* if on stream-write-waiting list then - * remove from waiting list and waiting_tcp_delete */ - if(w->write_wait_queued) { - struct pending_tcp* pend = - (struct pending_tcp*)w->next_waiting; - verbose(VERB_CLIENT, "serviced_delete: writewait"); - if(!w->in_cb_and_decommission) - reuse_tree_by_id_delete(&pend->reuse, w); - reuse_write_wait_remove(&pend->reuse, w); - if(!w->in_cb_and_decommission) - waiting_tcp_delete(w); - } else if(!w->on_tcp_waiting_list) { - struct pending_tcp* pend = - (struct pending_tcp*)w->next_waiting; - verbose(VERB_CLIENT, "serviced_delete: tcpreusekeep"); - /* w needs to stay on tree_by_id to not assign - * the same ID; remove the callback since its - * serviced_query will be gone. */ - w->cb = NULL; - if(!reuse_tcp_remove_serviced_keep(w, sq)) { - if(!w->in_cb_and_decommission) - reuse_cb_and_decommission(sq->outnet, - pend, NETEVENT_CLOSED); - use_free_buffer(sq->outnet); - } - sq->pending = NULL; - } else { - verbose(VERB_CLIENT, "serviced_delete: tcpwait"); - outnet_waiting_tcp_list_remove(sq->outnet, w); - if(!w->in_cb_and_decommission) - waiting_tcp_delete(w); - } - } - } - /* does not delete from tree, caller has to do that */ - serviced_node_del(&sq->node, NULL); -} - -/** perturb a dname capitalization randomly */ -static void -serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len) -{ - uint8_t lablen; - uint8_t* d = qbuf + 10; - long int random = 0; - int bits = 0; - log_assert(len >= 10 + 5 /* offset qname, root, qtype, qclass */); - (void)len; - lablen = *d++; - while(lablen) { - while(lablen--) { - /* only perturb A-Z, a-z */ - if(isalpha((unsigned char)*d)) { - /* get a random bit */ - if(bits == 0) { - random = ub_random(rnd); - bits = 30; - } - if(random & 0x1) { - *d = (uint8_t)toupper((unsigned char)*d); - } else { - *d = (uint8_t)tolower((unsigned char)*d); - } - random >>= 1; - bits--; - } - d++; - } - lablen = *d++; - } - if(verbosity >= VERB_ALGO) { - char buf[LDNS_MAX_DOMAINLEN+1]; - dname_str(qbuf+10, buf); - verbose(VERB_ALGO, "qname perturbed to %s", buf); - } -} - -/** put serviced query into a buffer */ -static void -serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) -{ - /* if we are using 0x20 bits for ID randomness, perturb them */ - if(sq->outnet->use_caps_for_id && !sq->nocaps) { - serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen); - } - /* generate query */ - sldns_buffer_clear(buff); - sldns_buffer_write_u16(buff, 0); /* id placeholder */ - sldns_buffer_write(buff, sq->qbuf, sq->qbuflen); - sldns_buffer_flip(buff); - if(with_edns) { - /* add edns section */ - struct edns_data edns; - struct edns_option padding_option; - edns.edns_present = 1; - edns.ext_rcode = 0; - edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.opt_list_in = NULL; - edns.opt_list_out = sq->opt_list; - edns.opt_list_inplace_cb_out = NULL; - if(sq->status == serviced_query_UDP_EDNS_FRAG) { - if(addr_is_ip6(&sq->addr, sq->addrlen)) { - if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) - edns.udp_size = EDNS_FRAG_SIZE_IP6; - else edns.udp_size = EDNS_ADVERTISED_SIZE; - } else { - if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE) - edns.udp_size = EDNS_FRAG_SIZE_IP4; - else edns.udp_size = EDNS_ADVERTISED_SIZE; - } - } else { - edns.udp_size = EDNS_ADVERTISED_SIZE; - } - edns.bits = 0; - if(sq->dnssec & EDNS_DO) - edns.bits = EDNS_DO; - if(sq->dnssec & BIT_CD) - LDNS_CD_SET(sldns_buffer_begin(buff)); - if (sq->ssl_upstream && sq->padding_block_size) { - padding_option.opt_code = LDNS_EDNS_PADDING; - padding_option.opt_len = 0; - padding_option.opt_data = NULL; - padding_option.next = edns.opt_list_out; - edns.opt_list_out = &padding_option; - edns.padding_block_size = sq->padding_block_size; - } - attach_edns_record(buff, &edns); - } -} - -/** - * Perform serviced query UDP sending operation. - * Sends UDP with EDNS, unless infra host marked non EDNS. - * @param sq: query to send. - * @param buff: buffer scratch space. - * @return 0 on error. - */ -static int -serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff) -{ - int rtt, vs; - uint8_t edns_lame_known; - time_t now = *sq->outnet->now_secs; - - if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, - sq->zonelen, now, &vs, &edns_lame_known, &rtt)) - return 0; - sq->last_rtt = rtt; - verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs); - if(sq->status == serviced_initial) { - if(vs != -1) { - sq->status = serviced_query_UDP_EDNS; - } else { - sq->status = serviced_query_UDP; - } - } - serviced_encode(sq, buff, (sq->status == serviced_query_UDP_EDNS) || - (sq->status == serviced_query_UDP_EDNS_FRAG)); - sq->last_sent_time = *sq->outnet->now_tv; - sq->edns_lame_known = (int)edns_lame_known; - verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt); - sq->pending = pending_udp_query(sq, buff, rtt, - serviced_udp_callback, sq); - if(!sq->pending) - return 0; - return 1; -} - -/** check that perturbed qname is identical */ -static int -serviced_check_qname(sldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen) -{ - uint8_t* d1 = sldns_buffer_begin(pkt)+12; - uint8_t* d2 = qbuf+10; - uint8_t len1, len2; - int count = 0; - if(sldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */ - return 0; - log_assert(qbuflen >= 15 /* 10 header, root, type, class */); - len1 = *d1++; - len2 = *d2++; - while(len1 != 0 || len2 != 0) { - if(LABEL_IS_PTR(len1)) { - /* check if we can read *d1 with compression ptr rest */ - if(d1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt))) - return 0; - d1 = sldns_buffer_begin(pkt)+PTR_OFFSET(len1, *d1); - /* check if we can read the destination *d1 */ - if(d1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt))) - return 0; - len1 = *d1++; - if(count++ > MAX_COMPRESS_PTRS) - return 0; - continue; - } - if(d2 > qbuf+qbuflen) - return 0; - if(len1 != len2) - return 0; - if(len1 > LDNS_MAX_LABELLEN) - return 0; - /* check len1 + 1(next length) are okay to read */ - if(d1+len1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt))) - return 0; - log_assert(len1 <= LDNS_MAX_LABELLEN); - log_assert(len2 <= LDNS_MAX_LABELLEN); - log_assert(len1 == len2 && len1 != 0); - /* compare the labels - bitwise identical */ - if(memcmp(d1, d2, len1) != 0) - return 0; - d1 += len1; - d2 += len2; - len1 = *d1++; - len2 = *d2++; - } - return 1; -} - -/** call the callbacks for a serviced query */ -static void -serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, - struct comm_reply* rep) -{ - struct service_callback* p; - int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/ - uint8_t *backup_p = NULL; - size_t backlen = 0; -#ifdef UNBOUND_DEBUG - rbnode_type* rem = -#else - (void) -#endif - /* remove from tree, and schedule for deletion, so that callbacks - * can safely deregister themselves and even create new serviced - * queries that are identical to this one. */ - rbtree_delete(sq->outnet->serviced, sq); - log_assert(rem); /* should have been present */ - sq->to_be_deleted = 1; - verbose(VERB_ALGO, "svcd callbacks start"); - if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c && - !sq->nocaps && sq->qtype != LDNS_RR_TYPE_PTR) { - /* for type PTR do not check perturbed name in answer, - * compatibility with cisco dns guard boxes that mess up - * reverse queries 0x20 contents */ - /* noerror and nxdomain must have a qname in reply */ - if(sldns_buffer_read_u16_at(c->buffer, 4) == 0 && - (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) - == LDNS_RCODE_NOERROR || - LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) - == LDNS_RCODE_NXDOMAIN)) { - verbose(VERB_DETAIL, "no qname in reply to check 0x20ID"); - log_addr(VERB_DETAIL, "from server", - &sq->addr, sq->addrlen); - log_buf(VERB_DETAIL, "for packet", c->buffer); - error = NETEVENT_CLOSED; - c = NULL; - } else if(sldns_buffer_read_u16_at(c->buffer, 4) > 0 && - !serviced_check_qname(c->buffer, sq->qbuf, - sq->qbuflen)) { - verbose(VERB_DETAIL, "wrong 0x20-ID in reply qname"); - log_addr(VERB_DETAIL, "from server", - &sq->addr, sq->addrlen); - log_buf(VERB_DETAIL, "for packet", c->buffer); - error = NETEVENT_CAPSFAIL; - /* and cleanup too */ - pkt_dname_tolower(c->buffer, - sldns_buffer_at(c->buffer, 12)); - } else { - verbose(VERB_ALGO, "good 0x20-ID in reply qname"); - /* cleanup caps, prettier cache contents. */ - pkt_dname_tolower(c->buffer, - sldns_buffer_at(c->buffer, 12)); - } - } - if(dobackup && c) { - /* make a backup of the query, since the querystate processing - * may send outgoing queries that overwrite the buffer. - * use secondary buffer to store the query. - * This is a data copy, but faster than packet to server */ - backlen = sldns_buffer_limit(c->buffer); - backup_p = regional_alloc_init(sq->region, - sldns_buffer_begin(c->buffer), backlen); - if(!backup_p) { - log_err("malloc failure in serviced query callbacks"); - error = NETEVENT_CLOSED; - c = NULL; - } - sq->outnet->svcd_overhead = backlen; - } - /* test the actual sq->cblist, because the next elem could be deleted*/ - while((p=sq->cblist) != NULL) { - sq->cblist = p->next; /* remove this element */ - if(dobackup && c) { - sldns_buffer_clear(c->buffer); - sldns_buffer_write(c->buffer, backup_p, backlen); - sldns_buffer_flip(c->buffer); - } - fptr_ok(fptr_whitelist_serviced_query(p->cb)); - (void)(*p->cb)(c, p->cb_arg, error, rep); - } - if(backup_p) { - sq->outnet->svcd_overhead = 0; - } - verbose(VERB_ALGO, "svcd callbacks end"); - log_assert(sq->cblist == NULL); - serviced_delete(sq); -} - -int -serviced_tcp_callback(struct comm_point* c, void* arg, int error, - struct comm_reply* rep) -{ - struct serviced_query* sq = (struct serviced_query*)arg; - struct comm_reply r2; -#ifdef USE_DNSTAP - struct waiting_tcp* w = (struct waiting_tcp*)sq->pending; - struct pending_tcp* pend_tcp = NULL; - struct port_if* pi = NULL; - if(w && !w->on_tcp_waiting_list && w->next_waiting) { - pend_tcp = (struct pending_tcp*)w->next_waiting; - pi = pend_tcp->pi; - } -#endif - sq->pending = NULL; /* removed after this callback */ - if(error != NETEVENT_NOERROR) - log_addr(VERB_QUERY, "tcp error for address", - &sq->addr, sq->addrlen); - if(error==NETEVENT_NOERROR) - infra_update_tcp_works(sq->outnet->infra, &sq->addr, - sq->addrlen, sq->zone, sq->zonelen); -#ifdef USE_DNSTAP - /* - * sending src (local service)/dst (upstream) addresses over DNSTAP - */ - if(error==NETEVENT_NOERROR && pi && sq->outnet->dtenv && - (sq->outnet->dtenv->log_resolver_response_messages || - sq->outnet->dtenv->log_forwarder_response_messages)) { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen); - dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, - &pi->addr, c->type, sq->zone, sq->zonelen, sq->qbuf, - sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv, - c->buffer); - } -#endif - if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && - (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == - LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(sldns_buffer_begin( - c->buffer)) == LDNS_RCODE_NOTIMPL) ) { - /* attempt to fallback to nonEDNS */ - sq->status = serviced_query_TCP_EDNS_fallback; - serviced_tcp_initiate(sq, c->buffer); - return 0; - } else if(error==NETEVENT_NOERROR && - sq->status == serviced_query_TCP_EDNS_fallback && - (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == - LDNS_RCODE_NOERROR || LDNS_RCODE_WIRE( - sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN - || LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) - == LDNS_RCODE_YXDOMAIN)) { - /* the fallback produced a result that looks promising, note - * that this server should be approached without EDNS */ - /* only store noEDNS in cache if domain is noDNSSEC */ - if(!sq->want_dnssec) - if(!infra_edns_update(sq->outnet->infra, &sq->addr, - sq->addrlen, sq->zone, sq->zonelen, -1, - *sq->outnet->now_secs)) - log_err("Out of memory caching no edns for host"); - sq->status = serviced_query_TCP; - } - if(sq->tcp_upstream || sq->ssl_upstream) { - struct timeval now = *sq->outnet->now_tv; - if(error!=NETEVENT_NOERROR) { - if(!infra_rtt_update(sq->outnet->infra, &sq->addr, - sq->addrlen, sq->zone, sq->zonelen, sq->qtype, - -1, sq->last_rtt, (time_t)now.tv_sec)) - log_err("out of memory in TCP exponential backoff."); - } else if(now.tv_sec > sq->last_sent_time.tv_sec || - (now.tv_sec == sq->last_sent_time.tv_sec && - now.tv_usec > sq->last_sent_time.tv_usec)) { - /* convert from microseconds to milliseconds */ - int roundtime = ((int)(now.tv_sec - sq->last_sent_time.tv_sec))*1000 - + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; - verbose(VERB_ALGO, "measured TCP-time at %d msec", roundtime); - log_assert(roundtime >= 0); - /* only store if less then AUTH_TIMEOUT seconds, it could be - * huge due to system-hibernated and we woke up */ - if(roundtime < 60000) { - if(!infra_rtt_update(sq->outnet->infra, &sq->addr, - sq->addrlen, sq->zone, sq->zonelen, sq->qtype, - roundtime, sq->last_rtt, (time_t)now.tv_sec)) - log_err("out of memory noting rtt."); - } - } - } - /* insert address into reply info */ - if(!rep) { - /* create one if there isn't (on errors) */ - rep = &r2; - r2.c = c; - } - memcpy(&rep->remote_addr, &sq->addr, sq->addrlen); - rep->remote_addrlen = sq->addrlen; - serviced_callbacks(sq, error, c, rep); - return 0; -} - -static void -serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff) -{ - verbose(VERB_ALGO, "initiate TCP query %s", - sq->status==serviced_query_TCP_EDNS?"EDNS":""); - serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); - sq->last_sent_time = *sq->outnet->now_tv; - log_assert(!sq->busy); - sq->busy = 1; - sq->pending = pending_tcp_query(sq, buff, sq->outnet->tcp_auth_query_timeout, - serviced_tcp_callback, sq); - sq->busy = 0; - if(!sq->pending) { - /* delete from tree so that a retry by above layer does not - * clash with this entry */ - verbose(VERB_ALGO, "serviced_tcp_initiate: failed to send tcp query"); - serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL); - } -} - -/** Send serviced query over TCP return false on initial failure */ -static int -serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff) -{ - int vs, rtt, timeout; - uint8_t edns_lame_known; - if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, - sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known, - &rtt)) - return 0; - sq->last_rtt = rtt; - if(vs != -1) - sq->status = serviced_query_TCP_EDNS; - else sq->status = serviced_query_TCP; - serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); - sq->last_sent_time = *sq->outnet->now_tv; - if(sq->tcp_upstream || sq->ssl_upstream) { - timeout = rtt; - if(rtt >= UNKNOWN_SERVER_NICENESS && rtt < sq->outnet->tcp_auth_query_timeout) - timeout = sq->outnet->tcp_auth_query_timeout; - } else { - timeout = sq->outnet->tcp_auth_query_timeout; - } - log_assert(!sq->busy); - sq->busy = 1; - sq->pending = pending_tcp_query(sq, buff, timeout, - serviced_tcp_callback, sq); - sq->busy = 0; - return sq->pending != NULL; -} - -/* see if packet is edns malformed; got zeroes at start. - * This is from servers that return malformed packets to EDNS0 queries, - * but they return good packets for nonEDNS0 queries. - * We try to detect their output; without resorting to a full parse or - * check for too many bytes after the end of the packet. */ -static int -packet_edns_malformed(struct sldns_buffer* buf, int qtype) -{ - size_t len; - if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE) - return 1; /* malformed */ - /* they have NOERROR rcode, 1 answer. */ - if(LDNS_RCODE_WIRE(sldns_buffer_begin(buf)) != LDNS_RCODE_NOERROR) - return 0; - /* one query (to skip) and answer records */ - if(LDNS_QDCOUNT(sldns_buffer_begin(buf)) != 1 || - LDNS_ANCOUNT(sldns_buffer_begin(buf)) == 0) - return 0; - /* skip qname */ - len = dname_valid(sldns_buffer_at(buf, LDNS_HEADER_SIZE), - sldns_buffer_limit(buf)-LDNS_HEADER_SIZE); - if(len == 0) - return 0; - if(len == 1 && qtype == 0) - return 0; /* we asked for '.' and type 0 */ - /* and then 4 bytes (type and class of query) */ - if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE + len + 4 + 3) - return 0; - - /* and start with 11 zeroes as the answer RR */ - /* so check the qtype of the answer record, qname=0, type=0 */ - if(sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[0] == 0 && - sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[1] == 0 && - sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[2] == 0) - return 1; - return 0; -} - -int -serviced_udp_callback(struct comm_point* c, void* arg, int error, - struct comm_reply* rep) -{ - struct serviced_query* sq = (struct serviced_query*)arg; - struct outside_network* outnet = sq->outnet; - struct timeval now = *sq->outnet->now_tv; -#ifdef USE_DNSTAP - struct pending* p = (struct pending*)sq->pending; -#endif - - sq->pending = NULL; /* removed after callback */ - if(error == NETEVENT_TIMEOUT) { - if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) { - /* fallback to 1480/1280 */ - sq->status = serviced_query_UDP_EDNS_FRAG; - log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10, - &sq->addr, sq->addrlen); - if(!serviced_udp_send(sq, c->buffer)) { - serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); - } - return 0; - } - if(sq->status == serviced_query_UDP_EDNS_FRAG) { - /* fragmentation size did not fix it */ - sq->status = serviced_query_UDP_EDNS; - } - sq->retry++; - if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, - sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt, - (time_t)now.tv_sec)) - log_err("out of memory in UDP exponential backoff"); - if(sq->retry < OUTBOUND_UDP_RETRY) { - log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10, - &sq->addr, sq->addrlen); - if(!serviced_udp_send(sq, c->buffer)) { - serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); - } - return 0; - } - } - if(error != NETEVENT_NOERROR) { - /* udp returns error (due to no ID or interface available) */ - serviced_callbacks(sq, error, c, rep); - return 0; - } -#ifdef USE_DNSTAP - /* - * sending src (local service)/dst (upstream) addresses over DNSTAP - */ - if(error == NETEVENT_NOERROR && outnet->dtenv && p->pc && - (outnet->dtenv->log_resolver_response_messages || - outnet->dtenv->log_forwarder_response_messages)) { - log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen); - log_addr(VERB_ALGO, "to local addr", &p->pc->pif->addr, - p->pc->pif->addrlen); - dt_msg_send_outside_response(outnet->dtenv, &sq->addr, - &p->pc->pif->addr, c->type, sq->zone, sq->zonelen, - sq->qbuf, sq->qbuflen, &sq->last_sent_time, - sq->outnet->now_tv, c->buffer); - } -#endif - if( (sq->status == serviced_query_UDP_EDNS - ||sq->status == serviced_query_UDP_EDNS_FRAG) - && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) - == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE( - sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL - || packet_edns_malformed(c->buffer, sq->qtype) - )) { - /* try to get an answer by falling back without EDNS */ - verbose(VERB_ALGO, "serviced query: attempt without EDNS"); - sq->status = serviced_query_UDP_EDNS_fallback; - sq->retry = 0; - if(!serviced_udp_send(sq, c->buffer)) { - serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); - } - return 0; - } else if(sq->status == serviced_query_UDP_EDNS && - !sq->edns_lame_known) { - /* now we know that edns queries received answers store that */ - log_addr(VERB_ALGO, "serviced query: EDNS works for", - &sq->addr, sq->addrlen); - if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, - sq->zone, sq->zonelen, 0, (time_t)now.tv_sec)) { - log_err("Out of memory caching edns works"); - } - sq->edns_lame_known = 1; - } else if(sq->status == serviced_query_UDP_EDNS_fallback && - !sq->edns_lame_known && (LDNS_RCODE_WIRE( - sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || - LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == - LDNS_RCODE_NXDOMAIN || LDNS_RCODE_WIRE(sldns_buffer_begin( - c->buffer)) == LDNS_RCODE_YXDOMAIN)) { - /* the fallback produced a result that looks promising, note - * that this server should be approached without EDNS */ - /* only store noEDNS in cache if domain is noDNSSEC */ - if(!sq->want_dnssec) { - log_addr(VERB_ALGO, "serviced query: EDNS fails for", - &sq->addr, sq->addrlen); - if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, - sq->zone, sq->zonelen, -1, (time_t)now.tv_sec)) { - log_err("Out of memory caching no edns for host"); - } - } else { - log_addr(VERB_ALGO, "serviced query: EDNS fails, but " - "not stored because need DNSSEC for", &sq->addr, - sq->addrlen); - } - sq->status = serviced_query_UDP; - } - if(now.tv_sec > sq->last_sent_time.tv_sec || - (now.tv_sec == sq->last_sent_time.tv_sec && - now.tv_usec > sq->last_sent_time.tv_usec)) { - /* convert from microseconds to milliseconds */ - int roundtime = ((int)(now.tv_sec - sq->last_sent_time.tv_sec))*1000 - + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; - verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime); - log_assert(roundtime >= 0); - /* in case the system hibernated, do not enter a huge value, - * above this value gives trouble with server selection */ - if(roundtime < 60000) { - if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, - sq->zone, sq->zonelen, sq->qtype, roundtime, - sq->last_rtt, (time_t)now.tv_sec)) - log_err("out of memory noting rtt."); - } - } - /* perform TC flag check and TCP fallback after updating our - * cache entries for EDNS status and RTT times */ - if(LDNS_TC_WIRE(sldns_buffer_begin(c->buffer))) { - /* fallback to TCP */ - /* this discards partial UDP contents */ - if(sq->status == serviced_query_UDP_EDNS || - sq->status == serviced_query_UDP_EDNS_FRAG || - sq->status == serviced_query_UDP_EDNS_fallback) - /* if we have unfinished EDNS_fallback, start again */ - sq->status = serviced_query_TCP_EDNS; - else sq->status = serviced_query_TCP; - serviced_tcp_initiate(sq, c->buffer); - return 0; - } - /* yay! an answer */ - serviced_callbacks(sq, error, c, rep); - return 0; -} - -struct serviced_query* -outnet_serviced_query(struct outside_network* outnet, - struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream, - char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* qstate, - comm_point_callback_type* callback, void* callback_arg, - sldns_buffer* buff, struct module_env* env, int* was_ratelimited) -{ - struct serviced_query* sq; - struct service_callback* cb; - struct edns_string_addr* client_string_addr; - struct regional* region; - struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out; - struct edns_option* per_upstream_opt_list = NULL; - time_t timenow = 0; - - /* If we have an already populated EDNS option list make a copy since - * we may now add upstream specific EDNS options. */ - /* Use a region that could be attached to a serviced_query, if it needs - * to be created. If an existing one is found then this region will be - * destroyed here. */ - region = alloc_reg_obtain(env->alloc); - if(!region) return NULL; - if(qstate->edns_opts_back_out) { - per_upstream_opt_list = edns_opt_copy_region( - qstate->edns_opts_back_out, region); - if(!per_upstream_opt_list) { - alloc_reg_release(env->alloc, region); - return NULL; - } - qstate->edns_opts_back_out = per_upstream_opt_list; - } - - if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone, - zonelen, qstate, region)) { - alloc_reg_release(env->alloc, region); - return NULL; - } - /* Restore the option list; we can explicitly use the copied one from - * now on. */ - per_upstream_opt_list = qstate->edns_opts_back_out; - qstate->edns_opts_back_out = backed_up_opt_list; - - if((client_string_addr = edns_string_addr_lookup( - &env->edns_strings->client_strings, addr, addrlen))) { - edns_opt_list_append(&per_upstream_opt_list, - env->edns_strings->client_string_opcode, - client_string_addr->string_len, - client_string_addr->string, region); - } - - serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype, - qinfo->qclass, flags); - sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen, - per_upstream_opt_list); - if(!sq) { - /* Check ratelimit only for new serviced_query */ - if(check_ratelimit) { - timenow = *env->now; - if(!infra_ratelimit_inc(env->infra_cache, zone, - zonelen, timenow, env->cfg->ratelimit_backoff, - &qstate->qinfo, qstate->reply)) { - /* Can we pass through with slip factor? */ - if(env->cfg->ratelimit_factor == 0 || - ub_random_max(env->rnd, - env->cfg->ratelimit_factor) != 1) { - *was_ratelimited = 1; - alloc_reg_release(env->alloc, region); - return NULL; - } - log_nametypeclass(VERB_ALGO, - "ratelimit allowed through for " - "delegation point", zone, - LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN); - } - } - /* make new serviced query entry */ - sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps, - tcp_upstream, ssl_upstream, tls_auth_name, addr, - addrlen, zone, zonelen, (int)qinfo->qtype, - per_upstream_opt_list, - ( ssl_upstream && env->cfg->pad_queries - ? env->cfg->pad_queries_block_size : 0 ), - env->alloc, region); - if(!sq) { - if(check_ratelimit) { - infra_ratelimit_dec(env->infra_cache, - zone, zonelen, timenow); - } - return NULL; - } - if(!(cb = (struct service_callback*)regional_alloc( - sq->region, sizeof(*cb)))) { - if(check_ratelimit) { - infra_ratelimit_dec(env->infra_cache, - zone, zonelen, timenow); - } - (void)rbtree_delete(outnet->serviced, sq); - serviced_node_del(&sq->node, NULL); - return NULL; - } - /* No network action at this point; it will be invoked with the - * serviced_query timer instead to run outside of the mesh. */ - } else { - /* We don't need this region anymore. */ - alloc_reg_release(env->alloc, region); - /* duplicate entries are included in the callback list, because - * there is a counterpart registration by our caller that needs - * to be doubly-removed (with callbacks perhaps). */ - if(!(cb = (struct service_callback*)regional_alloc( - sq->region, sizeof(*cb)))) { - return NULL; - } - } - /* add callback to list of callbacks */ - cb->cb = callback; - cb->cb_arg = callback_arg; - cb->next = sq->cblist; - sq->cblist = cb; - return sq; -} - -/** remove callback from list */ -static void -callback_list_remove(struct serviced_query* sq, void* cb_arg) -{ - struct service_callback** pp = &sq->cblist; - while(*pp) { - if((*pp)->cb_arg == cb_arg) { - struct service_callback* del = *pp; - *pp = del->next; - return; - } - pp = &(*pp)->next; - } -} - -void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) -{ - if(!sq) - return; - callback_list_remove(sq, cb_arg); - /* if callbacks() routine scheduled deletion, let it do that */ - if(!sq->cblist && !sq->busy && !sq->to_be_deleted) { - (void)rbtree_delete(sq->outnet->serviced, sq); - serviced_delete(sq); - } -} - -/** create fd to send to this destination */ -static int -fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr, - socklen_t to_addrlen) -{ - struct sockaddr_storage* addr; - socklen_t addrlen; - int i, try, pnum, dscp; - struct port_if* pif; - - /* create fd */ - dscp = outnet->ip_dscp; - for(try = 0; try<1000; try++) { - int port = 0; - int freebind = 0; - int noproto = 0; - int inuse = 0; - int fd = -1; - - /* select interface */ - if(addr_is_ip6(to_addr, to_addrlen)) { - if(outnet->num_ip6 == 0) { - char to[64]; - addr_to_str(to_addr, to_addrlen, to, sizeof(to)); - verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to); - return -1; - } - i = ub_random_max(outnet->rnd, outnet->num_ip6); - pif = &outnet->ip6_ifs[i]; - } else { - if(outnet->num_ip4 == 0) { - char to[64]; - addr_to_str(to_addr, to_addrlen, to, sizeof(to)); - verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to); - return -1; - } - i = ub_random_max(outnet->rnd, outnet->num_ip4); - pif = &outnet->ip4_ifs[i]; - } - addr = &pif->addr; - addrlen = pif->addrlen; -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - pnum = ub_random_max(outnet->rnd, pif->avail_total); - if(pnum < pif->inuse) { - /* port already open */ - port = pif->out[pnum]->number; - } else { - /* unused ports in start part of array */ - port = pif->avail_ports[pnum - pif->inuse]; - } -#else - pnum = port = 0; -#endif - if(addr_is_ip6(to_addr, to_addrlen)) { - struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr; - sa.sin6_port = (in_port_t)htons((uint16_t)port); - fd = create_udp_sock(AF_INET6, SOCK_DGRAM, - (struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0, dscp); - } else { - struct sockaddr_in* sa = (struct sockaddr_in*)addr; - sa->sin_port = (in_port_t)htons((uint16_t)port); - fd = create_udp_sock(AF_INET, SOCK_DGRAM, - (struct sockaddr*)addr, addrlen, 1, &inuse, &noproto, - 0, 0, 0, NULL, 0, freebind, 0, dscp); - } - if(fd != -1) { - return fd; - } - if(!inuse) { - return -1; - } - } - /* too many tries */ - log_err("cannot send probe, ports are in use"); - return -1; -} - -struct comm_point* -outnet_comm_point_for_udp(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen) -{ - struct comm_point* cp; - int fd = fd_for_dest(outnet, to_addr, to_addrlen); - if(fd == -1) { - return NULL; - } - cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, 0, - cb, cb_arg, NULL); - if(!cp) { - log_err("malloc failure"); - close(fd); - return NULL; - } - return cp; -} - -/** setup SSL for comm point */ -static int -setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet, - int fd, char* host) -{ - cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd); - if(!cp->ssl) { - log_err("cannot create SSL object"); - return 0; - } -#ifdef USE_WINSOCK - comm_point_tcp_win_bio_cb(cp, cp->ssl); -#endif - cp->ssl_shake_state = comm_ssl_shake_write; - /* https verification */ -#ifdef HAVE_SSL - if(outnet->tls_use_sni) { - (void)SSL_set_tlsext_host_name(cp->ssl, host); - } -#endif -#ifdef HAVE_SSL_SET1_HOST - if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) { - /* because we set SSL_VERIFY_PEER, in netevent in - * ssl_handshake, it'll check if the certificate - * verification has succeeded */ - /* SSL_VERIFY_PEER is set on the sslctx */ - /* and the certificates to verify with are loaded into - * it with SSL_load_verify_locations or - * SSL_CTX_set_default_verify_paths */ - /* setting the hostname makes openssl verify the - * host name in the x509 certificate in the - * SSL connection*/ - if(!SSL_set1_host(cp->ssl, host)) { - log_err("SSL_set1_host failed"); - return 0; - } - } -#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - /* openssl 1.0.2 has this function that can be used for - * set1_host like verification */ - if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) { - X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl); -# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS - X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); -# endif - if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) { - log_err("X509_VERIFY_PARAM_set1_host failed"); - return 0; - } - } -#else - (void)host; -#endif /* HAVE_SSL_SET1_HOST */ - return 1; -} - -struct comm_point* -outnet_comm_point_for_tcp(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen, - sldns_buffer* query, int timeout, int ssl, char* host) -{ - struct comm_point* cp; - int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp); - if(fd == -1) { - return 0; - } - fd_set_nonblock(fd); - if(!outnet_tcp_connect(fd, to_addr, to_addrlen)) { - /* outnet_tcp_connect has closed fd on error for us */ - return 0; - } - cp = comm_point_create_tcp_out(outnet->base, 65552, cb, cb_arg); - if(!cp) { - log_err("malloc failure"); - close(fd); - return 0; - } - cp->repinfo.remote_addrlen = to_addrlen; - memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen); - - /* setup for SSL (if needed) */ - if(ssl) { - if(!setup_comm_ssl(cp, outnet, fd, host)) { - log_err("cannot setup XoT"); - comm_point_delete(cp); - return NULL; - } - } - - /* set timeout on TCP connection */ - comm_point_start_listening(cp, fd, timeout); - /* copy scratch buffer to cp->buffer */ - sldns_buffer_copy(cp->buffer, query); - return cp; -} - -/** setup the User-Agent HTTP header based on http-user-agent configuration */ -static void -setup_http_user_agent(sldns_buffer* buf, struct config_file* cfg) -{ - if(cfg->hide_http_user_agent) return; - if(cfg->http_user_agent==NULL || cfg->http_user_agent[0] == 0) { - sldns_buffer_printf(buf, "User-Agent: %s/%s\r\n", PACKAGE_NAME, - PACKAGE_VERSION); - } else { - sldns_buffer_printf(buf, "User-Agent: %s\r\n", cfg->http_user_agent); - } -} - -/** setup http request headers in buffer for sending query to destination */ -static int -setup_http_request(sldns_buffer* buf, char* host, char* path, - struct config_file* cfg) -{ - sldns_buffer_clear(buf); - sldns_buffer_printf(buf, "GET /%s HTTP/1.1\r\n", path); - sldns_buffer_printf(buf, "Host: %s\r\n", host); - setup_http_user_agent(buf, cfg); - /* We do not really do multiple queries per connection, - * but this header setting is also not needed. - * sldns_buffer_printf(buf, "Connection: close\r\n") */ - sldns_buffer_printf(buf, "\r\n"); - if(sldns_buffer_position(buf)+10 > sldns_buffer_capacity(buf)) - return 0; /* somehow buffer too short, but it is about 60K - and the request is only a couple bytes long. */ - sldns_buffer_flip(buf); - return 1; -} - -struct comm_point* -outnet_comm_point_for_http(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout, - int ssl, char* host, char* path, struct config_file* cfg) -{ - /* cp calls cb with err=NETEVENT_DONE when transfer is done */ - struct comm_point* cp; - int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp); - if(fd == -1) { - return 0; - } - fd_set_nonblock(fd); - if(!outnet_tcp_connect(fd, to_addr, to_addrlen)) { - /* outnet_tcp_connect has closed fd on error for us */ - return 0; - } - cp = comm_point_create_http_out(outnet->base, 65552, cb, cb_arg, - outnet->udp_buff); - if(!cp) { - log_err("malloc failure"); - close(fd); - return 0; - } - cp->repinfo.remote_addrlen = to_addrlen; - memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen); - - /* setup for SSL (if needed) */ - if(ssl) { - if(!setup_comm_ssl(cp, outnet, fd, host)) { - log_err("cannot setup https"); - comm_point_delete(cp); - return NULL; - } - } - - /* set timeout on TCP connection */ - comm_point_start_listening(cp, fd, timeout); - - /* setup http request in cp->buffer */ - if(!setup_http_request(cp->buffer, host, path, cfg)) { - log_err("error setting up http request"); - comm_point_delete(cp); - return NULL; - } - return cp; -} - -/** get memory used by waiting tcp entry (in use or not) */ -static size_t -waiting_tcp_get_mem(struct waiting_tcp* w) -{ - size_t s; - if(!w) return 0; - s = sizeof(*w) + w->pkt_len; - if(w->timer) - s += comm_timer_get_mem(w->timer); - return s; -} - -/** get memory used by port if */ -static size_t -if_get_mem(struct port_if* pif) -{ - size_t s; - int i; - s = sizeof(*pif) + -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - sizeof(int)*pif->avail_total + -#endif - sizeof(struct port_comm*)*pif->maxout; - for(i=0; iinuse; i++) - s += sizeof(*pif->out[i]) + - comm_point_get_mem(pif->out[i]->cp); - return s; -} - -/** get memory used by waiting udp */ -static size_t -waiting_udp_get_mem(struct pending* w) -{ - size_t s; - s = sizeof(*w) + comm_timer_get_mem(w->timer) + w->pkt_len; - return s; -} - -size_t outnet_get_mem(struct outside_network* outnet) -{ - size_t i; - int k; - struct waiting_tcp* w; - struct pending* u; - struct serviced_query* sq; - struct service_callback* sb; - struct port_comm* pc; - size_t s = sizeof(*outnet) + sizeof(*outnet->base) + - sizeof(*outnet->udp_buff) + - sldns_buffer_capacity(outnet->udp_buff); - /* second buffer is not ours */ - for(pc = outnet->unused_fds; pc; pc = pc->next) { - s += sizeof(*pc) + comm_point_get_mem(pc->cp); - } - for(k=0; knum_ip4; k++) - s += if_get_mem(&outnet->ip4_ifs[k]); - for(k=0; knum_ip6; k++) - s += if_get_mem(&outnet->ip6_ifs[k]); - for(u=outnet->udp_wait_first; u; u=u->next_waiting) - s += waiting_udp_get_mem(u); - - s += sizeof(struct pending_tcp*)*outnet->num_tcp; - for(i=0; inum_tcp; i++) { - s += sizeof(struct pending_tcp); - s += comm_point_get_mem(outnet->tcp_conns[i]->c); - if(outnet->tcp_conns[i]->query) - s += waiting_tcp_get_mem(outnet->tcp_conns[i]->query); - } - for(w=outnet->tcp_wait_first; w; w = w->next_waiting) - s += waiting_tcp_get_mem(w); - s += sizeof(*outnet->pending); - s += (sizeof(struct pending) + comm_timer_get_mem(NULL)) * - outnet->pending->count; - s += sizeof(*outnet->serviced); - s += outnet->svcd_overhead; - RBTREE_FOR(sq, struct serviced_query*, outnet->serviced) { - s += sizeof(*sq) + sq->qbuflen; - for(sb = sq->cblist; sb; sb = sb->next) - s += sizeof(*sb); - } - return s; -} - -size_t -serviced_get_mem(struct serviced_query* sq) -{ - struct service_callback* sb; - size_t s; - s = sizeof(*sq) + sq->qbuflen; - for(sb = sq->cblist; sb; sb = sb->next) - s += sizeof(*sb); - if(sq->status == serviced_query_UDP_EDNS || - sq->status == serviced_query_UDP || - sq->status == serviced_query_UDP_EDNS_FRAG || - sq->status == serviced_query_UDP_EDNS_fallback) { - s += sizeof(struct pending); - s += comm_timer_get_mem(NULL); - } else { - /* does not have size of the pkt pointer */ - /* always has a timer except on malloc failures */ - - /* these sizes are part of the main outside network mem */ - /* - s += sizeof(struct waiting_tcp); - s += comm_timer_get_mem(NULL); - */ - } - return s; -} - diff --git a/crates/libunbound-sys/unbound/services/outside_network.h b/crates/libunbound-sys/unbound/services/outside_network.h deleted file mode 100644 index 467c81f6..00000000 --- a/crates/libunbound-sys/unbound/services/outside_network.h +++ /dev/null @@ -1,853 +0,0 @@ -/* - * services/outside_network.h - listen to answers from the network - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file has functions to send queries to authoritative servers, - * and wait for the pending answer, with timeouts. - */ - -#ifndef OUTSIDE_NETWORK_H -#define OUTSIDE_NETWORK_H - -#include "util/alloc.h" -#include "util/rbtree.h" -#include "util/regional.h" -#include "util/netevent.h" -#include "dnstap/dnstap_config.h" -struct pending; -struct pending_timeout; -struct ub_randstate; -struct pending_tcp; -struct waiting_tcp; -struct waiting_udp; -struct reuse_tcp; -struct infra_cache; -struct port_comm; -struct port_if; -struct sldns_buffer; -struct serviced_query; -struct dt_env; -struct edns_option; -struct module_env; -struct module_qstate; -struct query_info; -struct config_file; - -/** - * Send queries to outside servers and wait for answers from servers. - * Contains answer-listen sockets. - */ -struct outside_network { - /** Base for select calls */ - struct comm_base* base; - /** pointer to time in seconds */ - time_t* now_secs; - /** pointer to time in microseconds */ - struct timeval* now_tv; - - /** buffer shared by UDP connections, since there is only one - datagram at any time. */ - struct sldns_buffer* udp_buff; - /** serviced_callbacks malloc overhead when processing multiple - * identical serviced queries to the same server. */ - size_t svcd_overhead; - /** use x20 bits to encode additional ID random bits */ - int use_caps_for_id; - /** outside network wants to quit. Stop queued msgs from sent. */ - int want_to_quit; - - /** number of unwanted replies received (for statistics) */ - size_t unwanted_replies; - /** cumulative total of unwanted replies (for defense) */ - size_t unwanted_total; - /** threshold when to take defensive action. If 0 then never. */ - size_t unwanted_threshold; - /** what action to take, called when defensive action is needed */ - void (*unwanted_action)(void*); - /** user param for action */ - void* unwanted_param; - - /** linked list of available commpoints, unused file descriptors, - * for use as outgoing UDP ports. cp.fd=-1 in them. */ - struct port_comm* unused_fds; - /** if udp is done */ - int do_udp; - /** if udp is delay-closed (delayed answers do not meet closed port)*/ - int delayclose; - /** timeout for delayclose */ - struct timeval delay_tv; - /** if we perform udp-connect, connect() for UDP socket to mitigate - * ICMP side channel leakage */ - int udp_connect; - /** number of udp packets sent. */ - size_t num_udp_outgoing; - - /** array of outgoing IP4 interfaces */ - struct port_if* ip4_ifs; - /** number of outgoing IP4 interfaces */ - int num_ip4; - - /** array of outgoing IP6 interfaces */ - struct port_if* ip6_ifs; - /** number of outgoing IP6 interfaces */ - int num_ip6; - - /** pending udp queries waiting to be sent out, waiting for fd */ - struct pending* udp_wait_first; - /** last pending udp query in list */ - struct pending* udp_wait_last; - - /** pending udp answers. sorted by id, addr */ - rbtree_type* pending; - /** serviced queries, sorted by qbuf, addr, dnssec */ - rbtree_type* serviced; - /** host cache, pointer but not owned by outnet. */ - struct infra_cache* infra; - /** where to get random numbers */ - struct ub_randstate* rnd; - /** ssl context to create ssl wrapped TCP with DNS connections */ - void* sslctx; - /** if SNI will be used for TLS connections */ - int tls_use_sni; -#ifdef USE_DNSTAP - /** dnstap environment */ - struct dt_env* dtenv; -#endif - /** maximum segment size of tcp socket */ - int tcp_mss; - /** IP_TOS socket option requested on the sockets */ - int ip_dscp; - - /** - * Array of tcp pending used for outgoing TCP connections. - * Each can be used to establish a TCP connection with a server. - * The file descriptors are -1 if they are free, and need to be - * opened for the tcp connection. Can be used for ip4 and ip6. - */ - struct pending_tcp **tcp_conns; - /** number of tcp communication points. */ - size_t num_tcp; - /** number of tcp communication points in use. */ - size_t num_tcp_outgoing; - /** max number of queries on a reuse connection */ - size_t max_reuse_tcp_queries; - /** timeout for REUSE entries in milliseconds. */ - int tcp_reuse_timeout; - /** timeout in milliseconds for TCP queries to auth servers. */ - int tcp_auth_query_timeout; - /** - * tree of still-open and waiting tcp connections for reuse. - * can be closed and reopened to get a new tcp connection. - * or reused to the same destination again. with timeout to close. - * Entries are of type struct reuse_tcp. - * The entries are both active and empty connections. - */ - rbtree_type tcp_reuse; - /** max number of tcp_reuse entries we want to keep open */ - size_t tcp_reuse_max; - /** first and last(oldest) in lru list of reuse connections. - * the oldest can be closed to get a new free pending_tcp if needed - * The list contains empty connections, that wait for timeout or - * a new query that can use the existing connection. */ - struct reuse_tcp* tcp_reuse_first, *tcp_reuse_last; - /** list of tcp comm points that are free for use */ - struct pending_tcp* tcp_free; - /** list of tcp queries waiting for a buffer */ - struct waiting_tcp* tcp_wait_first; - /** last of waiting query list */ - struct waiting_tcp* tcp_wait_last; -}; - -/** - * Outgoing interface. Ports available and currently used are tracked - * per interface - */ -struct port_if { - /** address ready to allocate new socket (except port no). */ - struct sockaddr_storage addr; - /** length of addr field */ - socklen_t addrlen; - - /** prefix length of network address (in bits), for randomisation. - * if 0, no randomisation. */ - int pfxlen; - -#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION - /** the available ports array. These are unused. - * Only the first total-inuse part is filled. */ - int* avail_ports; - /** the total number of available ports (size of the array) */ - int avail_total; -#endif - - /** array of the commpoints currently in use. - * allocated for max number of fds, first part in use. */ - struct port_comm** out; - /** max number of fds, size of out array */ - int maxout; - /** number of commpoints (and thus also ports) in use */ - int inuse; -}; - -/** - * Outgoing commpoint for UDP port. - */ -struct port_comm { - /** next in free list */ - struct port_comm* next; - /** which port number (when in use) */ - int number; - /** interface it is used in */ - struct port_if* pif; - /** index in the out array of the interface */ - int index; - /** number of outstanding queries on this port */ - int num_outstanding; - /** UDP commpoint, fd=-1 if not in use */ - struct comm_point* cp; -}; - -/** - * Reuse TCP connection, still open can be used again. - */ -struct reuse_tcp { - /** rbtree node with links in tcp_reuse tree. key is NULL when not - * in tree. Both active and empty connections are in the tree. - * key is a pointer to this structure, the members used to compare - * are the sockaddr and and then is-ssl bool, and then ptr value is - * used in case the same address exists several times in the tree - * when there are multiple connections to the same destination to - * make the rbtree items unique. */ - rbnode_type node; - /** the key for the tcp_reuse tree. address of peer, ip4 or ip6, - * and port number of peer */ - struct sockaddr_storage addr; - /** length of addr */ - socklen_t addrlen; - /** also key for tcp_reuse tree, if ssl is used */ - int is_ssl; - /** lru chain, so that the oldest can be removed to get a new - * connection when all are in (re)use. oldest is last in list. - * The lru only contains empty connections waiting for reuse, - * the ones with active queries are not on the list because they - * do not need to be closed to make space for others. They already - * service a query so the close for another query does not help - * service a larger number of queries. */ - struct reuse_tcp* lru_next, *lru_prev; - /** true if the reuse_tcp item is on the lru list with empty items */ - int item_on_lru_list; - /** the connection to reuse, the fd is non-1 and is open. - * the addr and port determine where the connection is going, - * and is key to the rbtree. The SSL ptr determines if it is - * a TLS connection or a plain TCP connection there. And TLS - * or not is also part of the key to the rbtree. - * There is a timeout and read event on the fd, to close it. */ - struct pending_tcp* pending; - /** - * The more read again value pointed to by the commpoint - * tcp_more_read_again pointer, so that it exists after commpoint - * delete - */ - int cp_more_read_again; - /** - * The more write again value pointed to by the commpoint - * tcp_more_write_again pointer, so that it exists after commpoint - * delete - */ - int cp_more_write_again; - /** rbtree with other queries waiting on the connection, by ID number, - * of type struct waiting_tcp. It is for looking up received - * answers to the structure for callback. And also to see if ID - * numbers are unused and can be used for a new query. - * The write_wait elements are also in the tree, so that ID numbers - * can be looked up also for them. They are bool write_wait_queued. */ - rbtree_type tree_by_id; - /** list of queries waiting to be written on the channel, - * if NULL no queries are waiting to be written and the pending->query - * is the query currently serviced. The first is the next in line. - * They are also in the tree_by_id. Once written, the are removed - * from this list, but stay in the tree. */ - struct waiting_tcp* write_wait_first, *write_wait_last; - /** the outside network it is part of */ - struct outside_network* outnet; -}; - -/** - * A query that has an answer pending for it. - */ -struct pending { - /** redblacktree entry, key is the pending struct(id, addr). */ - rbnode_type node; - /** the ID for the query. int so that a value out of range can - * be used to signify a pending that is for certain not present in - * the rbtree. (and for which deletion is safe). */ - unsigned int id; - /** remote address. */ - struct sockaddr_storage addr; - /** length of addr field in use. */ - socklen_t addrlen; - /** comm point it was sent on (and reply must come back on). */ - struct port_comm* pc; - /** timeout event */ - struct comm_timer* timer; - /** callback for the timeout, error or reply to the message */ - comm_point_callback_type* cb; - /** callback user argument */ - void* cb_arg; - /** the outside network it is part of */ - struct outside_network* outnet; - /** the corresponding serviced_query */ - struct serviced_query* sq; - - /*---- filled if udp pending is waiting -----*/ - /** next in waiting list. */ - struct pending* next_waiting; - /** timeout in msec */ - int timeout; - /** The query itself, the query packet to send. */ - uint8_t* pkt; - /** length of query packet. */ - size_t pkt_len; -}; - -/** - * Pending TCP query to server. - */ -struct pending_tcp { - /** next in list of free tcp comm points, or NULL. */ - struct pending_tcp* next_free; - /** port for of the outgoing interface that is used */ - struct port_if* pi; - /** tcp comm point it was sent on (and reply must come back on). */ - struct comm_point* c; - /** the query being serviced, NULL if the pending_tcp is unused. */ - struct waiting_tcp* query; - /** the pre-allocated reuse tcp structure. if ->pending is nonNULL - * it is in use and the connection is waiting for reuse. - * It is here for memory pre-allocation, and used to make this - * pending_tcp wait for reuse. */ - struct reuse_tcp reuse; -}; - -/** - * Query waiting for TCP buffer. - */ -struct waiting_tcp { - /** - * next in waiting list. - * if on_tcp_waiting_list==0, this points to the pending_tcp structure. - */ - struct waiting_tcp* next_waiting; - /** if true the item is on the tcp waiting list and next_waiting - * is used for that. If false, the next_waiting points to the - * pending_tcp */ - int on_tcp_waiting_list; - /** next and prev in query waiting list for stream connection */ - struct waiting_tcp* write_wait_prev, *write_wait_next; - /** true if the waiting_tcp structure is on the write_wait queue */ - int write_wait_queued; - /** entry in reuse.tree_by_id, if key is NULL, not in tree, otherwise, - * this struct is key and sorted by ID (from waiting_tcp.id). */ - rbnode_type id_node; - /** the ID for the query; checked in reply */ - uint16_t id; - /** timeout event; timer keeps running whether the query is - * waiting for a buffer or the tcp reply is pending */ - struct comm_timer* timer; - /** timeout in msec */ - int timeout; - /** the outside network it is part of */ - struct outside_network* outnet; - /** remote address. */ - struct sockaddr_storage addr; - /** length of addr field in use. */ - socklen_t addrlen; - /** - * The query itself, the query packet to send. - * allocated after the waiting_tcp structure. - */ - uint8_t* pkt; - /** length of query packet. */ - size_t pkt_len; - /** callback for the timeout, error or reply to the message, - * or NULL if no user is waiting. the entry uses an ID number. - * a query that was written is no longer needed, but the ID number - * and a reply will come back and can be ignored if NULL */ - comm_point_callback_type* cb; - /** callback user argument */ - void* cb_arg; - /** if it uses ssl upstream */ - int ssl_upstream; - /** ref to the tls_auth_name from the serviced_query */ - char* tls_auth_name; - /** the packet was involved in an error, to stop looping errors */ - int error_count; - /** if true, the item is at the cb_and_decommission stage */ - int in_cb_and_decommission; -#ifdef USE_DNSTAP - /** serviced query pointer for dnstap to get logging info, if nonNULL*/ - struct serviced_query* sq; -#endif -}; - -/** - * Callback to party interested in serviced query results. - */ -struct service_callback { - /** next in callback list */ - struct service_callback* next; - /** callback function */ - comm_point_callback_type* cb; - /** user argument for callback function */ - void* cb_arg; -}; - -/** fallback size for fragmentation for EDNS in IPv4 */ -#define EDNS_FRAG_SIZE_IP4 1472 -/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */ -#define EDNS_FRAG_SIZE_IP6 1232 - -/** - * Query service record. - * Contains query and destination. UDP, TCP, EDNS are all tried. - * complete with retries and timeouts. A number of interested parties can - * receive a callback. - */ -struct serviced_query { - /** The rbtree node, key is this record */ - rbnode_type node; - /** The query that needs to be answered. Starts with flags u16, - * then qdcount, ..., including qname, qtype, qclass. Does not include - * EDNS record. */ - uint8_t* qbuf; - /** length of qbuf. */ - size_t qbuflen; - /** If an EDNS section is included, the DO/CD bit will be turned on. */ - int dnssec; - /** We want signatures, or else the answer is likely useless */ - int want_dnssec; - /** ignore capsforid */ - int nocaps; - /** tcp upstream used, use tcp, or ssl_upstream for SSL */ - int tcp_upstream, ssl_upstream; - /** the name of the tls authentication name, eg. 'ns.example.com' - * or NULL */ - char* tls_auth_name; - /** where to send it */ - struct sockaddr_storage addr; - /** length of addr field in use. */ - socklen_t addrlen; - /** zone name, uncompressed domain name in wireformat */ - uint8_t* zone; - /** length of zone name */ - size_t zonelen; - /** qtype */ - int qtype; - /** current status */ - enum serviced_query_status { - /** initial status */ - serviced_initial, - /** UDP with EDNS sent */ - serviced_query_UDP_EDNS, - /** UDP without EDNS sent */ - serviced_query_UDP, - /** TCP with EDNS sent */ - serviced_query_TCP_EDNS, - /** TCP without EDNS sent */ - serviced_query_TCP, - /** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */ - serviced_query_UDP_EDNS_fallback, - /** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */ - serviced_query_TCP_EDNS_fallback, - /** send UDP query with EDNS1480 (or 1280) */ - serviced_query_UDP_EDNS_FRAG - } - /** variable with current status */ - status; - /** true if serviced_query is scheduled for deletion already */ - int to_be_deleted; - /** number of UDP retries */ - int retry; - /** time last UDP was sent */ - struct timeval last_sent_time; - /** rtt of last message */ - int last_rtt; - /** do we know edns probe status already, for UDP_EDNS queries */ - int edns_lame_known; - /** edns options to use for sending upstream packet */ - struct edns_option* opt_list; - /** outside network this is part of */ - struct outside_network* outnet; - /** list of interested parties that need callback on results. */ - struct service_callback* cblist; - /** the UDP or TCP query that is pending, see status which */ - void* pending; - /** block size with which to pad encrypted queries (default: 128) */ - size_t padding_block_size; - /** region for this serviced query. Will be cleared when this - * serviced_query will be deleted */ - struct regional* region; - /** allocation service for the region */ - struct alloc_cache* alloc; - /** flash timer to start the net I/O as a separate event */ - struct comm_timer* timer; - /** true if serviced_query is currently doing net I/O and may block */ - int busy; -}; - -/** - * Create outside_network structure with N udp ports. - * @param base: the communication base to use for event handling. - * @param bufsize: size for network buffers. - * @param num_ports: number of udp ports to open per interface. - * @param ifs: interface names (or NULL for default interface). - * These interfaces must be able to access all authoritative servers. - * @param num_ifs: number of names in array ifs. - * @param do_ip4: service IP4. - * @param do_ip6: service IP6. - * @param num_tcp: number of outgoing tcp buffers to preallocate. - * @param dscp: DSCP to use. - * @param infra: pointer to infra cached used for serviced queries. - * @param rnd: stored to create random numbers for serviced queries. - * @param use_caps_for_id: enable to use 0x20 bits to encode id randomness. - * @param availports: array of available ports. - * @param numavailports: number of available ports in array. - * @param unwanted_threshold: when to take defensive action. - * @param unwanted_action: the action to take. - * @param unwanted_param: user parameter to action. - * @param tcp_mss: maximum segment size of tcp socket. - * @param do_udp: if udp is done. - * @param sslctx: context to create outgoing connections with (if enabled). - * @param delayclose: if not 0, udp sockets are delayed before timeout closure. - * msec to wait on timeouted udp sockets. - * @param tls_use_sni: if SNI is used for TLS connections. - * @param dtenv: environment to send dnstap events with (if enabled). - * @param udp_connect: if the udp_connect option is enabled. - * @param max_reuse_tcp_queries: max number of queries on a reuse connection. - * @param tcp_reuse_timeout: timeout for REUSE entries in milliseconds. - * @param tcp_auth_query_timeout: timeout in milliseconds for TCP queries to auth servers. - * @return: the new structure (with no pending answers) or NULL on error. - */ -struct outside_network* outside_network_create(struct comm_base* base, - size_t bufsize, size_t num_ports, char** ifs, int num_ifs, - int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra, - struct ub_randstate* rnd, int use_caps_for_id, int* availports, - int numavailports, size_t unwanted_threshold, int tcp_mss, - void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv, - int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout, - int tcp_auth_query_timeout); - -/** - * Delete outside_network structure. - * @param outnet: object to delete. - */ -void outside_network_delete(struct outside_network* outnet); - -/** - * Prepare for quit. Sends no more queries, even if queued up. - * @param outnet: object to prepare for removal - */ -void outside_network_quit_prepare(struct outside_network* outnet); - -/** - * Send UDP query, create pending answer. - * Changes the ID for the query to be random and unique for that destination. - * @param sq: serviced query. - * @param packet: wireformat query to send to destination. - * @param timeout: in milliseconds from now. - * @param callback: function to call on error, timeout or reply. - * @param callback_arg: user argument for callback function. - * @return: NULL on error for malloc or socket. Else the pending query object. - */ -struct pending* pending_udp_query(struct serviced_query* sq, - struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback, - void* callback_arg); - -/** - * Send TCP query. May wait for TCP buffer. Selects ID to be random, and - * checks id. - * @param sq: serviced query. - * @param packet: wireformat query to send to destination. copied from. - * @param timeout: in milliseconds from now. - * Timer starts running now. Timer may expire if all buffers are used, - * without any query been sent to the server yet. - * @param callback: function to call on error, timeout or reply. - * @param callback_arg: user argument for callback function. - * @return: false on error for malloc or socket. Else the pending TCP object. - */ -struct waiting_tcp* pending_tcp_query(struct serviced_query* sq, - struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback, - void* callback_arg); - -/** - * Delete pending answer. - * @param outnet: outside network the pending query is part of. - * Internal feature: if outnet is NULL, p is not unlinked from rbtree. - * @param p: deleted - */ -void pending_delete(struct outside_network* outnet, struct pending* p); - -/** - * Perform a serviced query to the authoritative servers. - * Duplicate efforts are detected, and EDNS, TCP and UDP retry is performed. - * @param outnet: outside network, with rbtree of serviced queries. - * @param qinfo: query info. - * @param flags: flags u16 (host format), includes opcode, CD bit. - * @param dnssec: if set, DO bit is set in EDNS queries. - * If the value includes BIT_CD, CD bit is set when in EDNS queries. - * If the value includes BIT_DO, DO bit is set when in EDNS queries. - * @param want_dnssec: signatures are needed, without EDNS the answer is - * likely to be useless. - * @param nocaps: ignore use_caps_for_id and use unperturbed qname. - * @param check_ratelimit: if set, will check ratelimit before sending out. - * @param tcp_upstream: use TCP for upstream queries. - * @param ssl_upstream: use SSL for upstream queries. - * @param tls_auth_name: when ssl_upstream is true, use this name to check - * the server's peer certificate. - * @param addr: to which server to send the query. - * @param addrlen: length of addr. - * @param zone: name of the zone of the delegation point. wireformat dname. - This is the delegation point name for which the server is deemed - authoritative. - * @param zonelen: length of zone. - * @param qstate: module qstate. Mainly for inspecting the available - * edns_opts_lists. - * @param callback: callback function. - * @param callback_arg: user argument to callback function. - * @param buff: scratch buffer to create query contents in. Empty on exit. - * @param env: the module environment. - * @param was_ratelimited: it will signal back if the query failed to pass the - * ratelimit check. - * @return 0 on error, or pointer to serviced query that is used to answer - * this serviced query may be shared with other callbacks as well. - */ -struct serviced_query* outnet_serviced_query(struct outside_network* outnet, - struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream, - char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* qstate, - comm_point_callback_type* callback, void* callback_arg, - struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited); - -/** - * Remove service query callback. - * If that leads to zero callbacks, the query is completely cancelled. - * @param sq: serviced query to adjust. - * @param cb_arg: callback argument of callback that needs removal. - * same as the callback_arg to outnet_serviced_query(). - */ -void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg); - -/** - * Get memory size in use by outside network. - * Counts buffers and outstanding query (serviced queries) malloced data. - * @param outnet: outside network structure. - * @return size in bytes. - */ -size_t outnet_get_mem(struct outside_network* outnet); - -/** - * Get memory size in use by serviced query while it is servicing callbacks. - * This takes into account the pre-deleted status of it; it will be deleted - * when the callbacks are done. - * @param sq: serviced query. - * @return size in bytes. - */ -size_t serviced_get_mem(struct serviced_query* sq); - -/** Pick random ID value for a tcp stream, avoids existing IDs. */ -uint16_t reuse_tcp_select_id(struct reuse_tcp* reuse, - struct outside_network* outnet); - -/** find element in tree by id */ -struct waiting_tcp* reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id); - -/** insert element in tree by id */ -void reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w); - -/** insert element in tcp_reuse tree and LRU list */ -int reuse_tcp_insert(struct outside_network* outnet, - struct pending_tcp* pend_tcp); - -/** touch the LRU of the element */ -void reuse_tcp_lru_touch(struct outside_network* outnet, - struct reuse_tcp* reuse); - -/** remove element from tree and LRU list */ -void reuse_tcp_remove_tree_list(struct outside_network* outnet, - struct reuse_tcp* reuse); - -/** snip the last reuse_tcp element off of the LRU list if any */ -struct reuse_tcp* reuse_tcp_lru_snip(struct outside_network* outnet); - -/** delete readwait waiting_tcp elements, deletes the elements in the list */ -void reuse_del_readwait(rbtree_type* tree_by_id); - -/** remove waiting tcp from the outnet waiting list */ -void outnet_waiting_tcp_list_remove(struct outside_network* outnet, - struct waiting_tcp* w); - -/** pop the first waiting tcp from the outnet waiting list */ -struct waiting_tcp* outnet_waiting_tcp_list_pop(struct outside_network* outnet); - -/** add waiting_tcp element to the outnet tcp waiting list */ -void outnet_waiting_tcp_list_add(struct outside_network* outnet, - struct waiting_tcp* w, int set_timer); - -/** add waiting_tcp element as first to the outnet tcp waiting list */ -void outnet_waiting_tcp_list_add_first(struct outside_network* outnet, - struct waiting_tcp* w, int reset_timer); - -/** pop the first element from the writewait list */ -struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse); - -/** remove the element from the writewait list */ -void reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w); - -/** push the element after the last on the writewait list */ -void reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w); - -/** get TCP file descriptor for address, returns -1 on failure, - * tcp_mss is 0 or maxseg size to set for TCP packets. */ -int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, - int tcp_mss, int dscp); - -/** - * Create udp commpoint suitable for sending packets to the destination. - * @param outnet: outside_network with the comm_base it is attached to, - * with the outgoing interfaces chosen from, and rnd gen for random. - * @param cb: callback function for the commpoint. - * @param cb_arg: callback argument for cb. - * @param to_addr: intended destination. - * @param to_addrlen: length of to_addr. - * @return commpoint that you can comm_point_send_udp_msg with, or NULL. - */ -struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen); - -/** - * Create tcp commpoint suitable for communication to the destination. - * It also performs connect() to the to_addr. - * @param outnet: outside_network with the comm_base it is attached to, - * and the tcp_mss. - * @param cb: callback function for the commpoint. - * @param cb_arg: callback argument for cb. - * @param to_addr: intended destination. - * @param to_addrlen: length of to_addr. - * @param query: initial packet to send writing, in buffer. It is copied - * to the commpoint buffer that is created. - * @param timeout: timeout for the TCP connection. - * timeout in milliseconds, or -1 for no (change to the) timeout. - * So seconds*1000. - * @param ssl: set to true for TLS. - * @param host: hostname for host name verification of TLS (or NULL if no TLS). - * @return tcp_out commpoint, or NULL. - */ -struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen, - struct sldns_buffer* query, int timeout, int ssl, char* host); - -/** - * Create http commpoint suitable for communication to the destination. - * Creates the http request buffer. It also performs connect() to the to_addr. - * @param outnet: outside_network with the comm_base it is attached to, - * and the tcp_mss. - * @param cb: callback function for the commpoint. - * @param cb_arg: callback argument for cb. - * @param to_addr: intended destination. - * @param to_addrlen: length of to_addr. - * @param timeout: timeout for the TCP connection. - * timeout in milliseconds, or -1 for no (change to the) timeout. - * So seconds*1000. - * @param ssl: set to true for https. - * @param host: hostname to use for the destination. part of http request. - * @param path: pathname to lookup, eg. name of the file on the destination. - * @param cfg: running configuration for User-Agent setup. - * @return http_out commpoint, or NULL. - */ -struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet, - comm_point_callback_type* cb, void* cb_arg, - struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout, - int ssl, char* host, char* path, struct config_file* cfg); - -/** connect tcp connection to addr, 0 on failure */ -int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen); - -/** callback for incoming udp answers from the network */ -int outnet_udp_cb(struct comm_point* c, void* arg, int error, - struct comm_reply *reply_info); - -/** callback for pending tcp connections */ -int outnet_tcp_cb(struct comm_point* c, void* arg, int error, - struct comm_reply *reply_info); - -/** callback for udp timeout */ -void pending_udp_timer_cb(void *arg); - -/** callback for udp delay for timeout */ -void pending_udp_timer_delay_cb(void *arg); - -/** callback for outgoing TCP timer event */ -void outnet_tcptimer(void* arg); - -/** callback to send serviced queries */ -void serviced_timer_cb(void *arg); - -/** callback for serviced query UDP answers */ -int serviced_udp_callback(struct comm_point* c, void* arg, int error, - struct comm_reply* rep); - -/** TCP reply or error callback for serviced queries */ -int serviced_tcp_callback(struct comm_point* c, void* arg, int error, - struct comm_reply* rep); - -/** compare function of pending rbtree */ -int pending_cmp(const void* key1, const void* key2); - -/** compare function of serviced query rbtree */ -int serviced_cmp(const void* key1, const void* key2); - -/** compare function of reuse_tcp rbtree in outside_network struct */ -int reuse_cmp(const void* key1, const void* key2); - -/** compare function of reuse_tcp tree_by_id rbtree */ -int reuse_id_cmp(const void* key1, const void* key2); - -#endif /* OUTSIDE_NETWORK_H */ diff --git a/crates/libunbound-sys/unbound/services/rpz.c b/crates/libunbound-sys/unbound/services/rpz.c deleted file mode 100644 index 6ce83cb6..00000000 --- a/crates/libunbound-sys/unbound/services/rpz.c +++ /dev/null @@ -1,2591 +0,0 @@ -/* - * services/rpz.c - rpz service - * - * Copyright (c) 2019, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable RPZ service. - */ - -#include "config.h" -#include "services/rpz.h" -#include "util/config_file.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" -#include "util/data/dname.h" -#include "util/net_help.h" -#include "util/log.h" -#include "util/data/dname.h" -#include "util/locks.h" -#include "util/regional.h" -#include "util/data/msgencode.h" -#include "services/cache/dns.h" -#include "iterator/iterator.h" -#include "iterator/iter_delegpt.h" -#include "daemon/worker.h" - -typedef struct resp_addr rpz_aclnode_type; - -struct matched_delegation_point { - uint8_t* dname; - size_t dname_len; -}; - -/** string for RPZ action enum */ -const char* -rpz_action_to_string(enum rpz_action a) -{ - switch(a) { - case RPZ_NXDOMAIN_ACTION: return "rpz-nxdomain"; - case RPZ_NODATA_ACTION: return "rpz-nodata"; - case RPZ_PASSTHRU_ACTION: return "rpz-passthru"; - case RPZ_DROP_ACTION: return "rpz-drop"; - case RPZ_TCP_ONLY_ACTION: return "rpz-tcp-only"; - case RPZ_INVALID_ACTION: return "rpz-invalid"; - case RPZ_LOCAL_DATA_ACTION: return "rpz-local-data"; - case RPZ_DISABLED_ACTION: return "rpz-disabled"; - case RPZ_CNAME_OVERRIDE_ACTION: return "rpz-cname-override"; - case RPZ_NO_OVERRIDE_ACTION: return "rpz-no-override"; - default: return "rpz-unknown-action"; - } -} - -/** RPZ action enum for config string */ -static enum rpz_action -rpz_config_to_action(char* a) -{ - if(strcmp(a, "nxdomain") == 0) return RPZ_NXDOMAIN_ACTION; - else if(strcmp(a, "nodata") == 0) return RPZ_NODATA_ACTION; - else if(strcmp(a, "passthru") == 0) return RPZ_PASSTHRU_ACTION; - else if(strcmp(a, "drop") == 0) return RPZ_DROP_ACTION; - else if(strcmp(a, "tcp_only") == 0) return RPZ_TCP_ONLY_ACTION; - else if(strcmp(a, "cname") == 0) return RPZ_CNAME_OVERRIDE_ACTION; - else if(strcmp(a, "disabled") == 0) return RPZ_DISABLED_ACTION; - else return RPZ_INVALID_ACTION; -} - -/** string for RPZ trigger enum */ -static const char* -rpz_trigger_to_string(enum rpz_trigger r) -{ - switch(r) { - case RPZ_QNAME_TRIGGER: return "rpz-qname"; - case RPZ_CLIENT_IP_TRIGGER: return "rpz-client-ip"; - case RPZ_RESPONSE_IP_TRIGGER: return "rpz-response-ip"; - case RPZ_NSDNAME_TRIGGER: return "rpz-nsdname"; - case RPZ_NSIP_TRIGGER: return "rpz-nsip"; - case RPZ_INVALID_TRIGGER: return "rpz-invalid"; - default: return "rpz-unknown-trigger"; - } -} - -/** - * Get the label that is just before the root label. - * @param dname: dname to work on - * @param maxdnamelen: maximum length of the dname - * @return: pointer to TLD label, NULL if not found or invalid dname - */ -static uint8_t* -get_tld_label(uint8_t* dname, size_t maxdnamelen) -{ - uint8_t* prevlab = dname; - size_t dnamelen = 0; - - /* one byte needed for label length */ - if(dnamelen+1 > maxdnamelen) - return NULL; - - /* only root label */ - if(*dname == 0) - return NULL; - - while(*dname) { - dnamelen += ((size_t)*dname)+1; - if(dnamelen+1 > maxdnamelen) - return NULL; - dname = dname+((size_t)*dname)+1; - if(*dname != 0) - prevlab = dname; - } - return prevlab; -} - -/** - * The RR types that are to be ignored. - * DNSSEC RRs at the apex, and SOA and NS are ignored. - */ -static int -rpz_type_ignored(uint16_t rr_type) -{ - switch(rr_type) { - case LDNS_RR_TYPE_SOA: - case LDNS_RR_TYPE_NS: - case LDNS_RR_TYPE_DNAME: - /* all DNSSEC-related RRs must be ignored */ - case LDNS_RR_TYPE_DNSKEY: - case LDNS_RR_TYPE_DS: - case LDNS_RR_TYPE_RRSIG: - case LDNS_RR_TYPE_NSEC: - case LDNS_RR_TYPE_NSEC3: - case LDNS_RR_TYPE_NSEC3PARAM: - return 1; - default: - break; - } - return 0; -} - -/** - * Classify RPZ action for RR type/rdata - * @param rr_type: the RR type - * @param rdatawl: RDATA with 2 bytes length - * @param rdatalen: the length of rdatawl (including its 2 bytes length) - * @return: the RPZ action - */ -static enum rpz_action -rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - char* endptr; - uint8_t* rdata; - int rdatalabs; - uint8_t* tldlab = NULL; - - switch(rr_type) { - case LDNS_RR_TYPE_SOA: - case LDNS_RR_TYPE_NS: - case LDNS_RR_TYPE_DNAME: - /* all DNSSEC-related RRs must be ignored */ - case LDNS_RR_TYPE_DNSKEY: - case LDNS_RR_TYPE_DS: - case LDNS_RR_TYPE_RRSIG: - case LDNS_RR_TYPE_NSEC: - case LDNS_RR_TYPE_NSEC3: - case LDNS_RR_TYPE_NSEC3PARAM: - return RPZ_INVALID_ACTION; - case LDNS_RR_TYPE_CNAME: - break; - default: - return RPZ_LOCAL_DATA_ACTION; - } - - /* use CNAME target to determine RPZ action */ - log_assert(rr_type == LDNS_RR_TYPE_CNAME); - if(rdatalen < 3) - return RPZ_INVALID_ACTION; - - rdata = rdatawl + 2; /* 2 bytes of rdata length */ - if(dname_valid(rdata, rdatalen-2) != rdatalen-2) - return RPZ_INVALID_ACTION; - - rdatalabs = dname_count_labels(rdata); - if(rdatalabs == 1) - return RPZ_NXDOMAIN_ACTION; - else if(rdatalabs == 2) { - if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000")) - return RPZ_NODATA_ACTION; - else if(dname_subdomain_c(rdata, - (uint8_t*)&"\014rpz-passthru\000")) - return RPZ_PASSTHRU_ACTION; - else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000")) - return RPZ_DROP_ACTION; - else if(dname_subdomain_c(rdata, - (uint8_t*)&"\014rpz-tcp-only\000")) - return RPZ_TCP_ONLY_ACTION; - } - - /* all other TLDs starting with "rpz-" are invalid */ - tldlab = get_tld_label(rdata, rdatalen-2); - if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr)) - return RPZ_INVALID_ACTION; - - /* no special label found */ - return RPZ_LOCAL_DATA_ACTION; -} - -static enum localzone_type -rpz_action_to_localzone_type(enum rpz_action a) -{ - switch(a) { - case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain; - case RPZ_NODATA_ACTION: return local_zone_always_nodata; - case RPZ_DROP_ACTION: return local_zone_always_deny; - case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent; - case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ - case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect; - case RPZ_TCP_ONLY_ACTION: return local_zone_truncate; - case RPZ_INVALID_ACTION: /* fallthrough */ - default: return local_zone_invalid; - } -} - -enum respip_action -rpz_action_to_respip_action(enum rpz_action a) -{ - switch(a) { - case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain; - case RPZ_NODATA_ACTION: return respip_always_nodata; - case RPZ_DROP_ACTION: return respip_always_deny; - case RPZ_PASSTHRU_ACTION: return respip_always_transparent; - case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ - case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect; - case RPZ_TCP_ONLY_ACTION: return respip_truncate; - case RPZ_INVALID_ACTION: /* fallthrough */ - default: return respip_invalid; - } -} - -static enum rpz_action -localzone_type_to_rpz_action(enum localzone_type lzt) -{ - switch(lzt) { - case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION; - case local_zone_always_nodata: return RPZ_NODATA_ACTION; - case local_zone_always_deny: return RPZ_DROP_ACTION; - case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION; - case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION; - case local_zone_truncate: return RPZ_TCP_ONLY_ACTION; - case local_zone_invalid: /* fallthrough */ - default: return RPZ_INVALID_ACTION; - } -} - -enum rpz_action -respip_action_to_rpz_action(enum respip_action a) -{ - switch(a) { - case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION; - case respip_always_nodata: return RPZ_NODATA_ACTION; - case respip_always_deny: return RPZ_DROP_ACTION; - case respip_always_transparent: return RPZ_PASSTHRU_ACTION; - case respip_redirect: return RPZ_LOCAL_DATA_ACTION; - case respip_truncate: return RPZ_TCP_ONLY_ACTION; - case respip_invalid: /* fallthrough */ - default: return RPZ_INVALID_ACTION; - } -} - -/** - * Get RPZ trigger for dname - * @param dname: dname containing RPZ trigger - * @param dname_len: length of the dname - * @return: RPZ trigger enum - */ -static enum rpz_trigger -rpz_dname_to_trigger(uint8_t* dname, size_t dname_len) -{ - uint8_t* tldlab; - char* endptr; - - if(dname_valid(dname, dname_len) != dname_len) - return RPZ_INVALID_TRIGGER; - - tldlab = get_tld_label(dname, dname_len); - if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr)) - return RPZ_QNAME_TRIGGER; - - if(dname_subdomain_c(tldlab, - (uint8_t*)&"\015rpz-client-ip\000")) - return RPZ_CLIENT_IP_TRIGGER; - else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000")) - return RPZ_RESPONSE_IP_TRIGGER; - else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000")) - return RPZ_NSDNAME_TRIGGER; - else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000")) - return RPZ_NSIP_TRIGGER; - - return RPZ_QNAME_TRIGGER; -} - -static inline struct clientip_synthesized_rrset* -rpz_clientip_synthesized_set_create(void) -{ - struct clientip_synthesized_rrset* set = calloc(1, sizeof(*set)); - if(set == NULL) { - return NULL; - } - set->region = regional_create(); - if(set->region == NULL) { - free(set); - return NULL; - } - addr_tree_init(&set->entries); - lock_rw_init(&set->lock); - return set; -} - -static void -rpz_clientip_synthesized_rr_delete(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct clientip_synthesized_rr* r = (struct clientip_synthesized_rr*)n->key; - lock_rw_destroy(&r->lock); -#ifdef THREADS_DISABLED - (void)r; -#endif -} - -static inline void -rpz_clientip_synthesized_set_delete(struct clientip_synthesized_rrset* set) -{ - if(set == NULL) { - return; - } - lock_rw_destroy(&set->lock); - traverse_postorder(&set->entries, rpz_clientip_synthesized_rr_delete, NULL); - regional_destroy(set->region); - free(set); -} - -void -rpz_delete(struct rpz* r) -{ - if(!r) - return; - local_zones_delete(r->local_zones); - local_zones_delete(r->nsdname_zones); - respip_set_delete(r->respip_set); - rpz_clientip_synthesized_set_delete(r->client_set); - rpz_clientip_synthesized_set_delete(r->ns_set); - regional_destroy(r->region); - free(r->taglist); - free(r->log_name); - free(r); -} - -int -rpz_clear(struct rpz* r) -{ - /* must hold write lock on auth_zone */ - local_zones_delete(r->local_zones); - r->local_zones = NULL; - local_zones_delete(r->nsdname_zones); - r->nsdname_zones = NULL; - respip_set_delete(r->respip_set); - r->respip_set = NULL; - rpz_clientip_synthesized_set_delete(r->client_set); - r->client_set = NULL; - rpz_clientip_synthesized_set_delete(r->ns_set); - r->ns_set = NULL; - if(!(r->local_zones = local_zones_create())){ - return 0; - } - r->nsdname_zones = local_zones_create(); - if(r->nsdname_zones == NULL) { - return 0; - } - if(!(r->respip_set = respip_set_create())) { - return 0; - } - if(!(r->client_set = rpz_clientip_synthesized_set_create())) { - return 0; - } - if(!(r->ns_set = rpz_clientip_synthesized_set_create())) { - return 0; - } - return 1; -} - -void -rpz_finish_config(struct rpz* r) -{ - lock_rw_wrlock(&r->respip_set->lock); - addr_tree_init_parents(&r->respip_set->ip_tree); - lock_rw_unlock(&r->respip_set->lock); - - lock_rw_wrlock(&r->client_set->lock); - addr_tree_init_parents(&r->client_set->entries); - lock_rw_unlock(&r->client_set->lock); - - lock_rw_wrlock(&r->ns_set->lock); - addr_tree_init_parents(&r->ns_set->entries); - lock_rw_unlock(&r->ns_set->lock); -} - -/** new rrset containing CNAME override, does not yet contain a dname */ -static struct ub_packed_rrset_key* -new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen) -{ - struct ub_packed_rrset_key* rrset; - struct packed_rrset_data* pd; - uint16_t rdlength = htons(ctlen); - rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region, - sizeof(*rrset)); - if(!rrset) { - log_err("out of memory"); - return NULL; - } - rrset->entry.key = rrset; - pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd)); - if(!pd) { - log_err("out of memory"); - return NULL; - } - pd->trust = rrset_trust_prim_noglue; - pd->security = sec_status_insecure; - - pd->count = 1; - pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len)); - pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl)); - pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data)); - if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) { - log_err("out of memory"); - return NULL; - } - pd->rr_len[0] = ctlen+2; - pd->rr_ttl[0] = 3600; - pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen); - if(!pd->rr_data[0]) { - log_err("out of memory"); - return NULL; - } - memmove(pd->rr_data[0], &rdlength, 2); - memmove(pd->rr_data[0]+2, ct, ctlen); - - rrset->entry.data = pd; - rrset->rk.type = htons(LDNS_RR_TYPE_CNAME); - rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN); - return rrset; -} - -struct rpz* -rpz_create(struct config_auth* p) -{ - struct rpz* r = calloc(1, sizeof(*r)); - if(!r) - goto err; - - r->region = regional_create_custom(sizeof(struct regional)); - if(!r->region) { - goto err; - } - - if(!(r->local_zones = local_zones_create())){ - goto err; - } - - r->nsdname_zones = local_zones_create(); - if(r->local_zones == NULL){ - goto err; - } - - if(!(r->respip_set = respip_set_create())) { - goto err; - } - - r->client_set = rpz_clientip_synthesized_set_create(); - if(r->client_set == NULL) { - goto err; - } - - r->ns_set = rpz_clientip_synthesized_set_create(); - if(r->ns_set == NULL) { - goto err; - } - - r->taglistlen = p->rpz_taglistlen; - r->taglist = memdup(p->rpz_taglist, r->taglistlen); - if(p->rpz_action_override) { - r->action_override = rpz_config_to_action(p->rpz_action_override); - } - else - r->action_override = RPZ_NO_OVERRIDE_ACTION; - - if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) { - uint8_t nm[LDNS_MAX_DOMAINLEN+1]; - size_t nmlen = sizeof(nm); - - if(!p->rpz_cname) { - log_err("rpz: override with cname action found, but no " - "rpz-cname-override configured"); - goto err; - } - - if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) { - log_err("rpz: cannot parse cname override: %s", - p->rpz_cname); - goto err; - } - r->cname_override = new_cname_override(r->region, nm, nmlen); - if(!r->cname_override) { - goto err; - } - } - r->log = p->rpz_log; - r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra; - if(p->rpz_log_name) { - if(!(r->log_name = strdup(p->rpz_log_name))) { - log_err("malloc failure on RPZ log_name strdup"); - goto err; - } - } - return r; -err: - if(r) { - if(r->local_zones) - local_zones_delete(r->local_zones); - if(r->nsdname_zones) - local_zones_delete(r->nsdname_zones); - if(r->respip_set) - respip_set_delete(r->respip_set); - if(r->client_set != NULL) - rpz_clientip_synthesized_set_delete(r->client_set); - if(r->ns_set != NULL) - rpz_clientip_synthesized_set_delete(r->ns_set); - if(r->taglist) - free(r->taglist); - if(r->region) - regional_destroy(r->region); - free(r); - } - return NULL; -} - -/** - * Remove RPZ zone name from dname - * Copy dname to newdname, without the originlen number of trailing bytes - */ -static size_t -strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen, - uint8_t* newdname, size_t maxnewdnamelen) -{ - size_t newdnamelen; - if(dnamelen < originlen) - return 0; - newdnamelen = dnamelen - originlen; - if(newdnamelen+1 > maxnewdnamelen) - return 0; - memmove(newdname, dname, newdnamelen); - newdname[newdnamelen] = 0; - return newdnamelen + 1; /* + 1 for root label */ -} - -static void -rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname, - size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass, - uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - struct local_zone* z; - enum localzone_type tp = local_zone_always_transparent; - int dnamelabs = dname_count_labels(dname); - int newzone = 0; - - if(a == RPZ_INVALID_ACTION) { - char str[255+1]; - if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS || - rrtype == LDNS_RR_TYPE_DNAME || - rrtype == LDNS_RR_TYPE_DNSKEY || - rrtype == LDNS_RR_TYPE_RRSIG || - rrtype == LDNS_RR_TYPE_NSEC || - rrtype == LDNS_RR_TYPE_NSEC3PARAM || - rrtype == LDNS_RR_TYPE_NSEC3 || - rrtype == LDNS_RR_TYPE_DS) { - free(dname); - return; /* no need to log these types as unsupported */ - } - dname_str(dname, str); - verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s", - str, rpz_action_to_string(a)); - free(dname); - return; - } - - lock_rw_wrlock(&lz->lock); - /* exact match */ - z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN); - if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) { - char* rrstr = sldns_wire2str_rr(rr, rr_len); - if(rrstr == NULL) { - log_err("malloc error while inserting rpz nsdname trigger"); - free(dname); - lock_rw_unlock(&lz->lock); - return; - } - if(rrstr[0]) - rrstr[strlen(rrstr)-1]=0; /* remove newline */ - verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr); - free(rrstr); - free(dname); - lock_rw_unlock(&lz->lock); - return; - } - if(z == NULL) { - tp = rpz_action_to_localzone_type(a); - z = local_zones_add_zone(lz, dname, dnamelen, - dnamelabs, rrclass, tp); - if(z == NULL) { - log_warn("rpz: create failed"); - lock_rw_unlock(&lz->lock); - /* dname will be free'd in failed local_zone_create() */ - return; - } - newzone = 1; - } - if(a == RPZ_LOCAL_DATA_ACTION) { - char* rrstr = sldns_wire2str_rr(rr, rr_len); - if(rrstr == NULL) { - log_err("malloc error while inserting rpz nsdname trigger"); - free(dname); - lock_rw_unlock(&lz->lock); - return; - } - lock_rw_wrlock(&z->lock); - local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype, - rrclass, ttl, rdata, rdata_len, rrstr); - lock_rw_unlock(&z->lock); - free(rrstr); - } - if(!newzone) { - free(dname); - } - lock_rw_unlock(&lz->lock); -} - -static void -rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len) -{ - char buf[LDNS_MAX_DOMAINLEN+1]; - (void)dname_len; - dname_str(dname, buf); - verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf); -} - -static void -rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - if(a == RPZ_INVALID_ACTION) { - verbose(VERB_ALGO, "rpz: skipping invalid action"); - free(dname); - return; - } - - rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype, - rrclass, ttl, rdata, rdata_len, rr, rr_len); -} - -static int -rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen, - uint8_t** stripdname, size_t* stripdnamelen) -{ - uint8_t* tldstart = get_tld_label(dname, maxdnamelen); - uint8_t swap; - if(tldstart == NULL) { - if(dname == NULL) { - *stripdname = NULL; - *stripdnamelen = 0; - return 0; - } - *stripdname = memdup(dname, maxdnamelen); - if(!*stripdname) { - *stripdnamelen = 0; - log_err("malloc failure for rpz strip suffix"); - return 0; - } - *stripdnamelen = maxdnamelen; - return 1; - } - /* shorten the domain name briefly, - * then we allocate a new name with the correct length */ - swap = *tldstart; - *tldstart = 0; - (void)dname_count_size_labels(dname, stripdnamelen); - *stripdname = memdup(dname, *stripdnamelen); - *tldstart = swap; - if(!*stripdname) { - *stripdnamelen = 0; - log_err("malloc failure for rpz strip suffix"); - return 0; - } - return 1; -} - -static void -rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - uint8_t* dname_stripped = NULL; - size_t dnamelen_stripped = 0; - - rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped, - &dnamelen_stripped); - if(a == RPZ_INVALID_ACTION) { - verbose(VERB_ALGO, "rpz: skipping invalid action"); - free(dname_stripped); - return; - } - - /* dname_stripped is consumed or freed by the insert routine */ - rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped, - dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len, - rr, rr_len); -} - -static int -rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr, - socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype, - uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len, - uint8_t* rr, size_t rr_len) -{ - struct resp_addr* node; - char* rrstr; - enum respip_action respa = rpz_action_to_respip_action(a); - - lock_rw_wrlock(&set->lock); - rrstr = sldns_wire2str_rr(rr, rr_len); - if(rrstr == NULL) { - log_err("malloc error while inserting rpz ipaddr based trigger"); - lock_rw_unlock(&set->lock); - return 0; - } - - node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr); - if(node == NULL) { - lock_rw_unlock(&set->lock); - free(rrstr); - return 0; - } - - lock_rw_wrlock(&node->lock); - lock_rw_unlock(&set->lock); - - node->action = respa; - - if(a == RPZ_LOCAL_DATA_ACTION) { - respip_enter_rr(set->region, node, rrtype, - rrclass, ttl, rdata, rdata_len, rrstr, ""); - } - - lock_rw_unlock(&node->lock); - free(rrstr); - return 1; -} - -static inline struct clientip_synthesized_rr* -rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set, - struct sockaddr_storage* addr, socklen_t addrlen, int net) -{ - int insert_ok; - struct clientip_synthesized_rr* node = - (struct clientip_synthesized_rr*)addr_tree_find(&set->entries, - addr, addrlen, net); - - if(node != NULL) { return node; } - - /* node does not yet exist => allocate one */ - node = regional_alloc_zero(set->region, sizeof(*node)); - if(node == NULL) { - log_err("out of memory"); - return NULL; - } - - lock_rw_init(&node->lock); - node->action = RPZ_INVALID_ACTION; - insert_ok = addr_tree_insert(&set->entries, &node->node, - addr, addrlen, net); - if (!insert_ok) { - log_warn("rpz: unexpected: unable to insert clientip address node"); - /* we can not free the just allocated node. - * theoretically a memleak */ - return NULL; - } - - return node; -} - -static void -rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) { - char* rrstr = sldns_wire2str_rr(rr, rr_len); - if(rrstr == NULL) { - log_err("malloc error while inserting rpz clientip based record"); - return; - } - log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr); - free(rrstr); -} - -/* from localzone.c; difference is we don't have a dname */ -static struct local_rrset* -rpz_clientip_new_rrset(struct regional* region, - struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass) -{ - struct packed_rrset_data* pd; - struct local_rrset* rrset = (struct local_rrset*) - regional_alloc_zero(region, sizeof(*rrset)); - if(rrset == NULL) { - log_err("out of memory"); - return NULL; - } - rrset->next = raddr->data; - raddr->data = rrset; - rrset->rrset = (struct ub_packed_rrset_key*) - regional_alloc_zero(region, sizeof(*rrset->rrset)); - if(rrset->rrset == NULL) { - log_err("out of memory"); - return NULL; - } - rrset->rrset->entry.key = rrset->rrset; - pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd)); - if(pd == NULL) { - log_err("out of memory"); - return NULL; - } - pd->trust = rrset_trust_prim_noglue; - pd->security = sec_status_insecure; - rrset->rrset->entry.data = pd; - rrset->rrset->rk.type = htons(rrtype); - rrset->rrset->rk.rrset_class = htons(rrclass); - rrset->rrset->rk.dname = regional_alloc_zero(region, 1); - if(rrset->rrset->rk.dname == NULL) { - log_err("out of memory"); - return NULL; - } - rrset->rrset->rk.dname_len = 1; - return rrset; -} - -static int -rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr, - uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, - size_t rdata_len) -{ - struct local_rrset* rrset; - if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) { - log_err("CNAME response-ip data can not co-exist with other " - "client-ip data"); - return 0; - } - - rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass); - if(raddr->data == NULL) { - return 0; - } - - return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, ""); -} - -static int -rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr, - socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype, - uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len, - uint8_t* rr, size_t rr_len) -{ - struct clientip_synthesized_rr* node; - - lock_rw_wrlock(&set->lock); - - node = rpz_clientip_ensure_entry(set, addr, addrlen, net); - if(node == NULL) { - lock_rw_unlock(&set->lock); - rpz_report_rrset_error("client ip address", rr, rr_len); - return 0; - } - - lock_rw_wrlock(&node->lock); - lock_rw_unlock(&set->lock); - - node->action = a; - if(a == RPZ_LOCAL_DATA_ACTION) { - if(!rpz_clientip_enter_rr(set->region, node, rrtype, - rrclass, ttl, rdata, rdata_len)) { - verbose(VERB_ALGO, "rpz: unable to insert clientip rr"); - lock_rw_unlock(&node->lock); - return 0; - } - - } - - lock_rw_unlock(&node->lock); - - return 1; -} - -static int -rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - - if(a == RPZ_INVALID_ACTION) { - return 0; - } - - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { - verbose(VERB_ALGO, "rpz: unable to parse client ip"); - return 0; - } - - return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net, - a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); -} - -static int -rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - - if(a == RPZ_INVALID_ACTION) { - return 0; - } - - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { - verbose(VERB_ALGO, "rpz: unable to parse ns ip"); - return 0; - } - - return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net, - a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); -} - -/** Insert RR into RPZ's respip_set */ -static int -rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - - if(a == RPZ_INVALID_ACTION) { - return 0; - } - - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { - verbose(VERB_ALGO, "rpz: unable to parse response ip"); - return 0; - } - - if(a == RPZ_INVALID_ACTION || - rpz_action_to_respip_action(a) == respip_invalid) { - char str[255+1]; - dname_str(dname, str); - verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s", - str, rpz_action_to_string(a)); - return 0; - } - - return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net, - a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); -} - -int -rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, - size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl, - uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len) -{ - size_t policydnamelen; - /* name is free'd in local_zone delete */ - enum rpz_trigger t; - enum rpz_action a; - uint8_t* policydname; - - if(rpz_type_ignored(rr_type)) { - /* this rpz action is not valid, eg. this is the SOA or NS RR */ - return 1; - } - if(!dname_subdomain_c(dname, azname)) { - char* dname_str = sldns_wire2str_dname(dname, dnamelen); - char* azname_str = sldns_wire2str_dname(azname, aznamelen); - if(dname_str && azname_str) { - log_err("rpz: name of record (%s) to insert into RPZ is not a " - "subdomain of the configured name of the RPZ zone (%s)", - dname_str, azname_str); - } else { - log_err("rpz: name of record to insert into RPZ is not a " - "subdomain of the configured name of the RPZ zone"); - } - free(dname_str); - free(azname_str); - return 0; - } - - log_assert(dnamelen >= aznamelen); - if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) { - log_err("malloc error while inserting RPZ RR"); - return 0; - } - - a = rpz_rr_to_action(rr_type, rdatawl, rdatalen); - if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen, - policydname, (dnamelen-aznamelen)+1))) { - free(policydname); - return 0; - } - t = rpz_dname_to_trigger(policydname, policydnamelen); - if(t == RPZ_INVALID_TRIGGER) { - free(policydname); - verbose(VERB_ALGO, "rpz: skipping invalid trigger"); - return 1; - } - if(t == RPZ_QNAME_TRIGGER) { - /* policydname will be consumed, no free */ - rpz_insert_qname_trigger(r, policydname, policydnamelen, - a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, - rr_len); - } else if(t == RPZ_RESPONSE_IP_TRIGGER) { - rpz_insert_response_ip_trigger(r, policydname, policydnamelen, - a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, - rr_len); - free(policydname); - } else if(t == RPZ_CLIENT_IP_TRIGGER) { - rpz_insert_clientip_trigger(r, policydname, policydnamelen, - a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, - rr_len); - free(policydname); - } else if(t == RPZ_NSIP_TRIGGER) { - rpz_insert_nsip_trigger(r, policydname, policydnamelen, - a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, - rr_len); - free(policydname); - } else if(t == RPZ_NSDNAME_TRIGGER) { - rpz_insert_nsdname_trigger(r, policydname, policydnamelen, - a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, - rr_len); - free(policydname); - } else { - free(policydname); - verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s", - rpz_trigger_to_string(t)); - } - return 1; -} - -/** - * Find RPZ local-zone by qname. - * @param zones: local-zone tree - * @param qname: qname - * @param qname_len: length of qname - * @param qclass: qclass - * @param only_exact: if 1 only exact (non wildcard) matches are returned - * @param wr: get write lock for local-zone if 1, read lock if 0 - * @param zones_keep_lock: if set do not release the r->local_zones lock, this - * makes the caller of this function responsible for releasing the lock. - * @return: NULL or local-zone holding rd or wr lock - */ -static struct local_zone* -rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass, - int only_exact, int wr, int zones_keep_lock) -{ - uint8_t* ce; - size_t ce_len; - int ce_labs; - uint8_t wc[LDNS_MAX_DOMAINLEN+1]; - int exact; - struct local_zone* z = NULL; - - if(wr) { - lock_rw_wrlock(&zones->lock); - } else { - lock_rw_rdlock(&zones->lock); - } - z = local_zones_find_le(zones, qname, qname_len, - dname_count_labels(qname), - LDNS_RR_CLASS_IN, &exact); - if(!z || (only_exact && !exact)) { - if(!zones_keep_lock) { - lock_rw_unlock(&zones->lock); - } - return NULL; - } - if(wr) { - lock_rw_wrlock(&z->lock); - } else { - lock_rw_rdlock(&z->lock); - } - if(!zones_keep_lock) { - lock_rw_unlock(&zones->lock); - } - - if(exact) - return z; - - /* No exact match found, lookup wildcard. closest encloser must - * be the shared parent between the qname and the best local - * zone match, append '*' to that and do another lookup. */ - - ce = dname_get_shared_topdomain(z->name, qname); - if(!ce /* should not happen */) { - lock_rw_unlock(&z->lock); - if(zones_keep_lock) { - lock_rw_unlock(&zones->lock); - } - return NULL; - } - ce_labs = dname_count_size_labels(ce, &ce_len); - if(ce_len+2 > sizeof(wc)) { - lock_rw_unlock(&z->lock); - if(zones_keep_lock) { - lock_rw_unlock(&zones->lock); - } - return NULL; - } - wc[0] = 1; /* length of wildcard label */ - wc[1] = (uint8_t)'*'; /* wildcard label */ - memmove(wc+2, ce, ce_len); - lock_rw_unlock(&z->lock); - - if(!zones_keep_lock) { - if(wr) { - lock_rw_wrlock(&zones->lock); - } else { - lock_rw_rdlock(&zones->lock); - } - } - z = local_zones_find_le(zones, wc, - ce_len+2, ce_labs+1, qclass, &exact); - if(!z || !exact) { - lock_rw_unlock(&zones->lock); - return NULL; - } - if(wr) { - lock_rw_wrlock(&z->lock); - } else { - lock_rw_rdlock(&z->lock); - } - if(!zones_keep_lock) { - lock_rw_unlock(&zones->lock); - } - return z; -} - -/** Find entry for RR type in the list of rrsets for the clientip. */ -static struct local_rrset* -rpz_find_synthesized_rrset(uint16_t qtype, - struct clientip_synthesized_rr* data) -{ - struct local_rrset* cursor = data->data; - while( cursor != NULL) { - struct packed_rrset_key* packed_rrset = &cursor->rrset->rk; - if(htons(qtype) == packed_rrset->type) { - return cursor; - } - cursor = cursor->next; - } - return NULL; -} - -/** - * Remove RR from RPZ's local-data - * @param z: local-zone for RPZ, holding write lock - * @param policydname: dname of RR to remove - * @param policydnamelen: length of policydname - * @param rr_type: RR type of RR to remove - * @param rdata: rdata of RR to remove - * @param rdatalen: length of rdata - * @return: 1 if zone must be removed after RR deletion - */ -static int -rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname, - size_t policydnamelen, uint16_t rr_type, uint8_t* rdata, - size_t rdatalen) -{ - struct local_data* ld; - struct packed_rrset_data* d; - size_t index; - ld = local_zone_find_data(z, policydname, policydnamelen, - dname_count_labels(policydname)); - if(ld) { - struct local_rrset* prev=NULL, *p=ld->rrsets; - while(p && ntohs(p->rrset->rk.type) != rr_type) { - prev = p; - p = p->next; - } - if(!p) - return 0; - d = (struct packed_rrset_data*)p->rrset->entry.data; - if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) { - if(d->count == 1) { - /* no memory recycling for zone deletions ... */ - if(prev) prev->next = p->next; - else ld->rrsets = p->next; - } - if(d->count > 1) { - if(!local_rrset_remove_rr(d, index)) - return 0; - } - } - } - if(ld && ld->rrsets) - return 0; - return 1; -} - -/** - * Remove RR from RPZ's respip set - * @param raddr: respip node - * @param rr_type: RR type of RR to remove - * @param rdata: rdata of RR to remove - * @param rdatalen: length of rdata - * @return: 1 if zone must be removed after RR deletion - */ -static int -rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata, - size_t rdatalen) -{ - size_t index; - struct packed_rrset_data* d; - if(!raddr->data) - return 1; - d = raddr->data->entry.data; - if(ntohs(raddr->data->rk.type) != rr_type) { - return 0; - } - if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) { - if(d->count == 1) { - /* regional alloc'd */ - raddr->data->entry.data = NULL; - raddr->data = NULL; - return 1; - } - if(d->count > 1) { - if(!local_rrset_remove_rr(d, index)) - return 0; - } - } - return 0; - -} - -/** Remove RR from rpz localzones structure */ -static void -rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname, - size_t dnamelen, enum rpz_action a, uint16_t rr_type, - uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen) -{ - struct local_zone* z; - int delete_zone = 1; - z = rpz_find_zone(zones, dname, dnamelen, rr_class, - 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/); - if(!z) { - verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, " - "RPZ domain not found"); - return; - } - if(a == RPZ_LOCAL_DATA_ACTION) - delete_zone = rpz_data_delete_rr(z, dname, - dnamelen, rr_type, rdatawl, rdatalen); - else if(a != localzone_type_to_rpz_action(z->type)) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&zones->lock); - return; - } - lock_rw_unlock(&z->lock); - if(delete_zone) { - local_zones_del_zone(zones, z); - } - lock_rw_unlock(&zones->lock); -} - -/** Remove RR from RPZ's local-zone */ -static void -rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rr_type, uint16_t rr_class, - uint8_t* rdatawl, size_t rdatalen) -{ - rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen, - a, rr_type, rr_class, rdatawl, rdatalen); -} - -static void -rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - struct resp_addr* node; - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - int delete_respip = 1; - - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) - return; - - lock_rw_wrlock(&r->respip_set->lock); - if(!(node = (struct resp_addr*)addr_tree_find( - &r->respip_set->ip_tree, &addr, addrlen, net))) { - verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, " - "RPZ domain not found"); - lock_rw_unlock(&r->respip_set->lock); - return; - } - - lock_rw_wrlock(&node->lock); - if(a == RPZ_LOCAL_DATA_ACTION) { - /* remove RR, signal whether RR can be removed */ - delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl, - rdatalen); - } - lock_rw_unlock(&node->lock); - if(delete_respip) - respip_sockaddr_delete(r->respip_set, node); - lock_rw_unlock(&r->respip_set->lock); -} - -/** find and remove type from list of local_rrset entries*/ -static void -del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype) -{ - struct local_rrset* prev=NULL, *p=*list_head; - while(p && ntohs(p->rrset->rk.type) != dtype) { - prev = p; - p = p->next; - } - if(!p) - return; /* rrset type not found */ - /* unlink it */ - if(prev) prev->next = p->next; - else *list_head = p->next; - /* no memory recycling for zone deletions ... */ -} - -/** Delete client-ip trigger RR from its RRset and perhaps also the rrset - * from the linked list. Returns if the local data is empty and the node can - * be deleted too, or not. */ -static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node, - uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - struct local_rrset* rrset; - struct packed_rrset_data* d; - size_t index; - rrset = rpz_find_synthesized_rrset(rr_type, node); - if(rrset == NULL) - return 0; /* type not found, ignore */ - d = (struct packed_rrset_data*)rrset->rrset->entry.data; - if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index)) - return 0; /* RR not found, ignore */ - if(d->count == 1) { - /* regional alloc'd */ - /* delete the type entry from the list */ - del_local_rrset_from_list(&node->data, rr_type); - /* if the list is empty, the node can be removed too */ - if(node->data == NULL) - return 1; - } else if (d->count > 1) { - if(!local_rrset_remove_rr(d, index)) - return 0; - } - return 0; -} - -/** remove trigger RR from clientip_syntheized set tree. */ -static void -rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set, - struct sockaddr_storage* addr, socklen_t addrlen, int net, - enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - struct clientip_synthesized_rr* node; - int delete_node = 1; - - lock_rw_wrlock(&set->lock); - node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries, - addr, addrlen, net); - if(node == NULL) { - /* netblock not found */ - verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, " - "RPZ address, netblock not found"); - lock_rw_unlock(&set->lock); - return; - } - lock_rw_wrlock(&node->lock); - if(a == RPZ_LOCAL_DATA_ACTION) { - /* remove RR, signal whether entry can be removed */ - delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl, - rdatalen); - } else if(a != node->action) { - /* ignore the RR with different action specification */ - delete_node = 0; - } - if(delete_node) { - rbtree_delete(&set->entries, node->node.node.key); - } - lock_rw_unlock(&set->lock); - lock_rw_unlock(&node->lock); - if(delete_node) { - lock_rw_destroy(&node->lock); - } -} - -/** Remove clientip trigger RR from RPZ. */ -static void -rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - if(a == RPZ_INVALID_ACTION) - return; - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) - return; - rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net, - a, rr_type, rdatawl, rdatalen); -} - -/** Remove nsip trigger RR from RPZ. */ -static void -rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen) -{ - struct sockaddr_storage addr; - socklen_t addrlen; - int net, af; - if(a == RPZ_INVALID_ACTION) - return; - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) - return; - rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net, - a, rr_type, rdatawl, rdatalen); -} - -/** Remove nsdname trigger RR from RPZ. */ -static void -rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rr_type, uint16_t rr_class, - uint8_t* rdatawl, size_t rdatalen) -{ - uint8_t* dname_stripped = NULL; - size_t dnamelen_stripped = 0; - if(a == RPZ_INVALID_ACTION) - return; - if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped, - &dnamelen_stripped)) - return; - rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped, - dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen); - free(dname_stripped); -} - -void -rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, - size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, - size_t rdatalen) -{ - size_t policydnamelen; - enum rpz_trigger t; - enum rpz_action a; - uint8_t* policydname; - - if(rpz_type_ignored(rr_type)) { - /* this rpz action is not valid, eg. this is the SOA or NS RR */ - return; - } - if(!dname_subdomain_c(dname, azname)) { - /* not subdomain of the RPZ zone. */ - return; - } - - if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1))) - return; - - a = rpz_rr_to_action(rr_type, rdatawl, rdatalen); - if(a == RPZ_INVALID_ACTION) { - free(policydname); - return; - } - if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen, - policydname, LDNS_MAX_DOMAINLEN + 1))) { - free(policydname); - return; - } - t = rpz_dname_to_trigger(policydname, policydnamelen); - if(t == RPZ_INVALID_TRIGGER) { - /* skipping invalid trigger */ - free(policydname); - return; - } - if(t == RPZ_QNAME_TRIGGER) { - rpz_remove_qname_trigger(r, policydname, policydnamelen, a, - rr_type, rr_class, rdatawl, rdatalen); - } else if(t == RPZ_RESPONSE_IP_TRIGGER) { - rpz_remove_response_ip_trigger(r, policydname, policydnamelen, - a, rr_type, rdatawl, rdatalen); - } else if(t == RPZ_CLIENT_IP_TRIGGER) { - rpz_remove_clientip_trigger(r, policydname, policydnamelen, a, - rr_type, rdatawl, rdatalen); - } else if(t == RPZ_NSIP_TRIGGER) { - rpz_remove_nsip_trigger(r, policydname, policydnamelen, a, - rr_type, rdatawl, rdatalen); - } else if(t == RPZ_NSDNAME_TRIGGER) { - rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a, - rr_type, rr_class, rdatawl, rdatalen); - } - /* else it was an unsupported trigger, also skipped. */ - free(policydname); -} - -/** print log information for an applied RPZ policy. Based on local-zone's - * lz_inform_print(). - * The repinfo contains the reply address. If it is NULL, the module - * state is used to report the first IP address (if any). - * The dname is used, for the applied rpz, if NULL, addrnode is used. - */ -static void -log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode, - enum rpz_action a, struct query_info* qinfo, - struct comm_reply* repinfo, struct module_qstate* ms, char* log_name) -{ - char ip[128], txt[512], portstr[32]; - char dnamestr[LDNS_MAX_DOMAINLEN+1]; - uint16_t port = 0; - if(dname) { - dname_str(dname, dnamestr); - } else if(addrnode) { - char addrbuf[128]; - addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf)); - snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net); - } else { - dnamestr[0]=0; - } - if(repinfo) { - addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip)); - port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port); - } else if(ms && ms->mesh_info && ms->mesh_info->reply_list) { - addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr, - ms->mesh_info->reply_list->query_reply.client_addrlen, - ip, sizeof(ip)); - port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port); - } else { - ip[0]=0; - port = 0; - } - snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port); - snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s", - (log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""), - (strcmp(trigger,"qname")==0?"":trigger), - (strcmp(trigger,"qname")==0?"":" "), - dnamestr, rpz_action_to_string(a), - (ip[0]?ip:""), (ip[0]?portstr:"")); - log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass); -} - -static struct clientip_synthesized_rr* -rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set, - struct sockaddr_storage* addr, socklen_t addrlen, char* triggername) -{ - struct clientip_synthesized_rr* raddr = NULL; - enum rpz_action action = RPZ_INVALID_ACTION; - - lock_rw_rdlock(&set->lock); - - raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries, - addr, addrlen); - if(raddr != NULL) { - lock_rw_rdlock(&raddr->lock); - action = raddr->action; - if(verbosity >= VERB_ALGO) { - char ip[256], net[256]; - addr_to_str(addr, addrlen, ip, sizeof(ip)); - addr_to_str(&raddr->node.addr, raddr->node.addrlen, - net, sizeof(net)); - verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s", - triggername, net, raddr->node.net, ip, rpz_action_to_string(action)); - } - } - lock_rw_unlock(&set->lock); - - return raddr; -} - -static inline -struct clientip_synthesized_rr* -rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo, - struct comm_reply* repinfo, uint8_t* taglist, size_t taglen, - struct ub_server_stats* stats, - /* output parameters */ - struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out) -{ - struct clientip_synthesized_rr* node = NULL; - struct auth_zone* a = NULL; - struct rpz* r = NULL; - struct local_zone* z = NULL; - - lock_rw_rdlock(&az->rpz_lock); - - for(a = az->rpz_first; a; a = a->rpz_az_next) { - lock_rw_rdlock(&a->lock); - r = a->rpz; - if(r->disabled) { - lock_rw_unlock(&a->lock); - continue; - } - if(r->taglist && !taglist_intersect(r->taglist, - r->taglistlen, taglist, taglen)) { - lock_rw_unlock(&a->lock); - continue; - } - z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len, - qinfo->qclass, 0, 0, 0); - node = rpz_ipbased_trigger_lookup(r->client_set, - &repinfo->client_addr, repinfo->client_addrlen, - "clientip"); - if((z || node) && r->action_override == RPZ_DISABLED_ACTION) { - if(r->log) - log_rpz_apply((node?"clientip":"qname"), - (z?z->name:NULL), - (node?&node->node:NULL), - r->action_override, - qinfo, repinfo, NULL, r->log_name); - stats->rpz_action[r->action_override]++; - if(z != NULL) { - lock_rw_unlock(&z->lock); - z = NULL; - } - if(node != NULL) { - lock_rw_unlock(&node->lock); - node = NULL; - } - } - if(z || node) { - break; - } - /* not found in this auth_zone */ - lock_rw_unlock(&a->lock); - } - - lock_rw_unlock(&az->rpz_lock); - - *r_out = r; - *a_out = a; - *z_out = z; - - return node; -} - -static inline int -rpz_is_udp_query(struct comm_reply* repinfo) { - return repinfo != NULL - ? (repinfo->c != NULL - ? repinfo->c->type == comm_udp - : 0) - : 0; -} - -/** encode answer consisting of 1 rrset */ -static int -rpz_local_encode(struct module_env* env, struct query_info* qinfo, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec, - int rcode, struct ub_packed_rrset_key* soa_rrset) -{ - struct reply_info rep; - uint16_t udpsize; - struct ub_packed_rrset_key* rrsetlist[3]; - - memset(&rep, 0, sizeof(rep)); - rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode); - rep.qdcount = 1; - rep.rrset_count = ansec; - rep.rrsets = rrsetlist; - if(ansec > 0) { - rep.an_numrrsets = 1; - rep.rrsets[0] = rrset; - rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0]; - } - if(soa_rrset != NULL) { - rep.ar_numrrsets = 1; - rep.rrsets[rep.rrset_count] = soa_rrset; - rep.rrset_count ++; - if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) { - rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]; - } - } - - udpsize = edns->udp_size; - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->ext_rcode = 0; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, - repinfo, temp, env->now_tv) || - !reply_info_answer_encode(qinfo, &rep, - *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), - buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) { - error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, - *(uint16_t*)sldns_buffer_begin(buf), - sldns_buffer_read_u16_at(buf, 2), edns); - } - - return 1; -} - -/** allocate SOA record ubrrsetkey in region */ -static struct ub_packed_rrset_key* -make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa, - struct regional* temp) -{ - struct ub_packed_rrset_key csoa; - if(!soa) - return NULL; - memset(&csoa, 0, sizeof(csoa)); - csoa.entry.key = &csoa; - csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN); - csoa.rk.type = htons(LDNS_RR_TYPE_SOA); - csoa.rk.flags |= PACKED_RRSET_FIXEDTTL - | PACKED_RRSET_RPZ; - csoa.rk.dname = auth_zone->name; - csoa.rk.dname_len = auth_zone->namelen; - csoa.entry.hash = rrset_key_hash(&csoa.rk); - csoa.entry.data = soa->data; - return respip_copy_rrset(&csoa, temp); -} - -static void -rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr, - struct module_env* env, struct query_info* qinfo, - struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, - struct regional* temp, struct auth_zone* auth_zone) -{ - struct local_rrset* rrset; - enum rpz_action action = RPZ_INVALID_ACTION; - struct ub_packed_rrset_key* rp = NULL; - struct ub_packed_rrset_key* rsoa = NULL; - int rcode = LDNS_RCODE_NOERROR|BIT_AA; - int rrset_count = 1; - - /* prepare synthesized answer for client */ - action = raddr->action; - if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) { - verbose(VERB_ALGO, "rpz: bug: local-data action but no local data"); - return; - } - - /* check query type / rr type */ - rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr); - if(rrset == NULL) { - verbose(VERB_ALGO, "rpz: unable to find local-data for query"); - rrset_count = 0; - goto nodata; - } - - rp = respip_copy_rrset(rrset->rrset, temp); - if(!rp) { - verbose(VERB_ALGO, "rpz: local data action: out of memory"); - return; - } - - rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ; - rp->rk.dname = qinfo->qname; - rp->rk.dname_len = qinfo->qname_len; - rp->entry.hash = rrset_key_hash(&rp->rk); -nodata: - if(auth_zone) { - struct auth_rrset* soa = NULL; - soa = auth_zone_get_soa_rrset(auth_zone); - if(soa) { - rsoa = make_soa_ubrrset(auth_zone, soa, temp); - if(!rsoa) { - verbose(VERB_ALGO, "rpz: local data action soa: out of memory"); - return; - } - } - } - - rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp, - rrset_count, rcode, rsoa); -} - -/** add additional section SOA record to the reply. - * Since this gets fed into the normal iterator answer creation, it - * gets minimal-responses applied to it, that can remove the additional SOA - * again. */ -static int -rpz_add_soa(struct reply_info* rep, struct module_qstate* ms, - struct auth_zone* az) -{ - struct auth_rrset* soa = NULL; - struct ub_packed_rrset_key* rsoa = NULL; - struct ub_packed_rrset_key** prevrrsets; - if(!az) return 1; - soa = auth_zone_get_soa_rrset(az); - if(!soa) return 1; - if(!rep) return 0; - rsoa = make_soa_ubrrset(az, soa, ms->region); - if(!rsoa) return 0; - prevrrsets = rep->rrsets; - rep->rrsets = regional_alloc_zero(ms->region, - sizeof(*rep->rrsets)*(rep->rrset_count+1)); - if(!rep->rrsets) - return 0; - if(prevrrsets && rep->rrset_count > 0) - memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets)); - rep->rrset_count++; - rep->ar_numrrsets++; - rep->rrsets[rep->rrset_count-1] = rsoa; - return 1; -} - -static inline struct dns_msg* -rpz_dns_msg_new(struct regional* region) -{ - struct dns_msg* msg = - (struct dns_msg*)regional_alloc(region, - sizeof(struct dns_msg)); - if(msg == NULL) { return NULL; } - memset(msg, 0, sizeof(struct dns_msg)); - - return msg; -} - -static inline struct dns_msg* -rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms, - struct query_info* qinfo, struct auth_zone* az) -{ - struct dns_msg* msg = rpz_dns_msg_new(ms->region); - if(msg == NULL) { return msg; } - msg->qinfo = *qinfo; - msg->rep = construct_reply_info_base(ms->region, - LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA, - 1, /* qd */ - 0, /* ttl */ - 0, /* prettl */ - 0, /* expttl */ - 0, /* an */ - 0, /* ns */ - 0, /* ar */ - 0, /* total */ - sec_status_insecure, - LDNS_EDE_NONE); - if(msg->rep) - msg->rep->authoritative = 1; - if(!rpz_add_soa(msg->rep, ms, az)) - return NULL; - return msg; -} - -static inline struct dns_msg* -rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms, - struct query_info* qinfo, struct auth_zone* az) -{ - struct dns_msg* msg = rpz_dns_msg_new(ms->region); - uint16_t flags; - if(msg == NULL) { return msg; } - msg->qinfo = *qinfo; - flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA; - if(r->signal_nxdomain_ra) - flags &= ~BIT_RA; - msg->rep = construct_reply_info_base(ms->region, - flags, - 1, /* qd */ - 0, /* ttl */ - 0, /* prettl */ - 0, /* expttl */ - 0, /* an */ - 0, /* ns */ - 0, /* ar */ - 0, /* total */ - sec_status_insecure, - LDNS_EDE_NONE); - if(msg->rep) - msg->rep->authoritative = 1; - if(!rpz_add_soa(msg->rep, ms, az)) - return NULL; - return msg; -} - -static inline struct dns_msg* -rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms, - struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az) -{ - struct dns_msg* msg = NULL; - struct reply_info* new_reply_info; - struct ub_packed_rrset_key* rp; - - - msg = rpz_dns_msg_new(ms->region); - if(msg == NULL) { return NULL; } - - new_reply_info = construct_reply_info_base(ms->region, - LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA, - 1, /* qd */ - 0, /* ttl */ - 0, /* prettl */ - 0, /* expttl */ - 1, /* an */ - 0, /* ns */ - 0, /* ar */ - 1, /* total */ - sec_status_insecure, - LDNS_EDE_NONE); - if(new_reply_info == NULL) { - log_err("out of memory"); - return NULL; - } - new_reply_info->authoritative = 1; - rp = respip_copy_rrset(rrset->rrset, ms->region); - if(rp == NULL) { - log_err("out of memory"); - return NULL; - } - rp->rk.dname = qi->qname; - rp->rk.dname_len = qi->qname_len; - /* this rrset is from the rpz data, or synthesized. - * It is not actually from the network, so we flag it with this - * flags as a fake RRset. If later the cache is used to look up - * rrsets, then the fake ones are not returned (if you look without - * the flag). For like CNAME lookups from the iterator or A, AAAA - * lookups for nameserver targets, it would use the without flag - * actual data. So that the actual network data and fake data - * are kept track of separately. */ - rp->rk.flags |= PACKED_RRSET_RPZ; - new_reply_info->rrsets[0] = rp; - msg->rep = new_reply_info; - if(!rpz_add_soa(msg->rep, ms, az)) - return NULL; - return msg; -} - -static inline struct dns_msg* -rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, - struct clientip_synthesized_rr* data, struct auth_zone* az) -{ - struct query_info* qi = &ms->qinfo; - struct local_rrset* rrset; - - rrset = rpz_find_synthesized_rrset(qi->qtype, data); - if(rrset == NULL) { - verbose(VERB_ALGO, "rpz: nsip: no matching local data found"); - return NULL; - } - - return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); -} - -/* copy'n'paste from localzone.c */ -static struct local_rrset* -local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) -{ - struct local_rrset* p; - type = htons(type); - for(p = data->rrsets; p; p = p->next) { - if(p->rrset->rk.type == type) - return p; - if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) - return p; - } - return NULL; -} - -/* based on localzone.c:local_data_answer() */ -static inline struct dns_msg* -rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms, - struct local_zone* z, struct matched_delegation_point const* match, - struct auth_zone* az) -{ - struct local_data key; - struct local_data* ld; - struct local_rrset* rrset; - - if(match->dname == NULL) { return NULL; } - - key.node.key = &key; - key.name = match->dname; - key.namelen = match->dname_len; - key.namelabs = dname_count_labels(match->dname); - - rpz_log_dname("nsdname local data", key.name, key.namelen); - - ld = (struct local_data*)rbtree_search(&z->data, &key.node); - if(ld == NULL) { - verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found"); - return NULL; - } - - rrset = local_data_find_type(ld, ms->qinfo.qtype, 1); - if(rrset == NULL) { - verbose(VERB_ALGO, "rpz: nsdname: no matching local data found"); - return NULL; - } - - return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); -} - -/* like local_data_answer for qname triggers after a cname */ -static struct dns_msg* -rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms, - struct query_info* qinfo, struct local_zone* z, struct auth_zone* az) -{ - struct local_data key; - struct local_data* ld; - struct local_rrset* rrset; - key.node.key = &key; - key.name = qinfo->qname; - key.namelen = qinfo->qname_len; - key.namelabs = dname_count_labels(qinfo->qname); - ld = (struct local_data*)rbtree_search(&z->data, &key.node); - if(ld == NULL) { - verbose(VERB_ALGO, "rpz: qname after cname: name not found"); - return NULL; - } - rrset = local_data_find_type(ld, qinfo->qtype, 1); - if(rrset == NULL) { - verbose(VERB_ALGO, "rpz: qname after cname: type not found"); - return NULL; - } - return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az); -} - -static int -rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r, - struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo, - struct edns_data* edns, sldns_buffer* buf, struct regional* temp, - struct comm_reply* repinfo, struct ub_server_stats* stats) -{ - struct local_data* ld = NULL; - int ret = 0; - if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) { - qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset)); - if(qinfo->local_alias == NULL) { - return 0; /* out of memory */ - } - qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override, - sizeof(*r->cname_override)); - if(qinfo->local_alias->rrset == NULL) { - return 0; /* out of memory */ - } - qinfo->local_alias->rrset->rk.dname = qinfo->qname; - qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len; - if(r->log) { - log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION, - qinfo, repinfo, NULL, r->log_name); - } - stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++; - return 0; - } - - if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo, - edns, repinfo, buf, temp, dname_count_labels(qinfo->qname), - &ld, lzt, -1, NULL, 0, NULL, 0)) { - if(r->log) { - log_rpz_apply("qname", z->name, NULL, - localzone_type_to_rpz_action(lzt), qinfo, - repinfo, NULL, r->log_name); - } - stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; - return !qinfo->local_alias; - } - - ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, - 0 /* no local data used */, lzt); - if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf)) - == LDNS_RCODE_NXDOMAIN) - LDNS_RA_CLR(sldns_buffer_begin(buf)); - if(r->log) { - log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt), - qinfo, repinfo, NULL, r->log_name); - } - stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; - return ret; -} - -static struct clientip_synthesized_rr* -rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is) -{ - struct delegpt_addr* cursor; - struct clientip_synthesized_rr* action = NULL; - if(is->dp == NULL) { return NULL; } - for(cursor = is->dp->target_list; - cursor != NULL; - cursor = cursor->next_target) { - if(cursor->bogus) { continue; } - action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr, - cursor->addrlen, "nsip"); - if(action != NULL) { return action; } - } - return NULL; -} - -static struct dns_msg* -rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, - struct clientip_synthesized_rr* raddr, struct auth_zone* az) -{ - enum rpz_action action = raddr->action; - struct dns_msg* ret = NULL; - - if(r->action_override != RPZ_NO_OVERRIDE_ACTION) { - verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)", - rpz_action_to_string(r->action_override), rpz_action_to_string(action)); - action = r->action_override; - } - - if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) { - verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data"); - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); - goto done; - } - - switch(action) { - case RPZ_NXDOMAIN_ACTION: - ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); - break; - case RPZ_NODATA_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); - break; - case RPZ_TCP_ONLY_ACTION: - /* basically a passthru here but the tcp-only will be - * honored before the query gets sent. */ - ms->respip_action_info->action = respip_truncate; - ret = NULL; - break; - case RPZ_DROP_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); - ms->is_drop = 1; - break; - case RPZ_LOCAL_DATA_ACTION: - ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az); - if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } - break; - case RPZ_PASSTHRU_ACTION: - ret = NULL; - ms->rpz_passthru = 1; - break; - default: - verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", - rpz_action_to_string(action)); - ret = NULL; - } - -done: - if(r->log) - log_rpz_apply("nsip", NULL, &raddr->node, - action, &ms->qinfo, NULL, ms, r->log_name); - if(ms->env->worker) - ms->env->worker->stats.rpz_action[action]++; - lock_rw_unlock(&raddr->lock); - return ret; -} - -static struct dns_msg* -rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, - struct local_zone* z, struct matched_delegation_point const* match, - struct auth_zone* az) -{ - struct dns_msg* ret = NULL; - enum rpz_action action = localzone_type_to_rpz_action(z->type); - - if(r->action_override != RPZ_NO_OVERRIDE_ACTION) { - verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)", - rpz_action_to_string(r->action_override), rpz_action_to_string(action)); - action = r->action_override; - } - - switch(action) { - case RPZ_NXDOMAIN_ACTION: - ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); - break; - case RPZ_NODATA_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); - break; - case RPZ_TCP_ONLY_ACTION: - /* basically a passthru here but the tcp-only will be - * honored before the query gets sent. */ - ms->respip_action_info->action = respip_truncate; - ret = NULL; - break; - case RPZ_DROP_ACTION: - ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); - ms->is_drop = 1; - break; - case RPZ_LOCAL_DATA_ACTION: - ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az); - if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } - break; - case RPZ_PASSTHRU_ACTION: - ret = NULL; - ms->rpz_passthru = 1; - break; - default: - verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", - rpz_action_to_string(action)); - ret = NULL; - } - - if(r->log) - log_rpz_apply("nsdname", match->dname, NULL, - action, &ms->qinfo, NULL, ms, r->log_name); - if(ms->env->worker) - ms->env->worker->stats.rpz_action[action]++; - lock_rw_unlock(&z->lock); - return ret; -} - -static struct local_zone* -rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones, - uint16_t qclass, - /* output parameter */ - struct matched_delegation_point* match) -{ - struct delegpt_ns* nameserver; - struct local_zone* z = NULL; - - /* the rpz specs match the nameserver names (NS records), not the - * name of the delegation point itself, to the nsdname triggers */ - for(nameserver = dp->nslist; - nameserver != NULL; - nameserver = nameserver->next) { - z = rpz_find_zone(zones, nameserver->name, nameserver->namelen, - qclass, 0, 0, 0); - if(z != NULL) { - match->dname = nameserver->name; - match->dname_len = nameserver->namelen; - if(verbosity >= VERB_ALGO) { - char nm[255+1], zn[255+1]; - dname_str(match->dname, nm); - dname_str(z->name, zn); - if(strcmp(nm, zn) != 0) - verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s", - zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type))); - else - verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s", - nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type))); - } - break; - } - } - - return z; -} - -struct dns_msg* -rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is) -{ - struct auth_zones* az; - struct auth_zone* a; - struct clientip_synthesized_rr* raddr = NULL; - struct rpz* r = NULL; - struct local_zone* z = NULL; - struct matched_delegation_point match = {0}; - - if(ms->rpz_passthru) { - verbose(VERB_ALGO, "query is rpz_passthru, no further processing"); - return NULL; - } - - if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } - - az = ms->env->auth_zones; - - verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL); - - lock_rw_rdlock(&az->rpz_lock); - - /* precedence of RPZ works, loosely, like this: - * CNAMEs in order of the CNAME chain. rpzs in the order they are - * configured. In an RPZ: first client-IP addr, then QNAME, then - * response IP, then NSDNAME, then NSIP. Longest match first. Smallest - * one from a set. */ - /* we use the precedence rules for the topics and triggers that - * are pertinent at this stage of the resolve processing */ - for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) { - lock_rw_rdlock(&a->lock); - r = a->rpz; - if(r->disabled) { - lock_rw_unlock(&a->lock); - continue; - } - - /* the nsdname has precedence over the nsip triggers */ - z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones, - ms->qinfo.qclass, &match); - if(z != NULL) { - lock_rw_unlock(&a->lock); - break; - } - - raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is); - if(raddr != NULL) { - lock_rw_unlock(&a->lock); - break; - } - lock_rw_unlock(&a->lock); - } - - lock_rw_unlock(&az->rpz_lock); - - if(raddr == NULL && z == NULL) - return NULL; - - if(raddr != NULL) { - if(z) { - lock_rw_unlock(&z->lock); - } - return rpz_apply_nsip_trigger(ms, r, raddr, a); - } - return rpz_apply_nsdname_trigger(ms, r, z, &match, a); -} - -struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, - struct iter_qstate* is) -{ - struct auth_zones* az; - struct auth_zone* a = NULL; - struct rpz* r = NULL; - struct local_zone* z = NULL; - enum localzone_type lzt; - struct dns_msg* ret = NULL; - - if(ms->rpz_passthru) { - verbose(VERB_ALGO, "query is rpz_passthru, no further processing"); - return NULL; - } - - if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } - az = ms->env->auth_zones; - - lock_rw_rdlock(&az->rpz_lock); - - for(a = az->rpz_first; a; a = a->rpz_az_next) { - lock_rw_rdlock(&a->lock); - r = a->rpz; - if(r->disabled) { - lock_rw_unlock(&a->lock); - continue; - } - z = rpz_find_zone(r->local_zones, is->qchase.qname, - is->qchase.qname_len, is->qchase.qclass, 0, 0, 0); - if(z && r->action_override == RPZ_DISABLED_ACTION) { - if(r->log) - log_rpz_apply("qname", z->name, NULL, - r->action_override, - &ms->qinfo, NULL, ms, r->log_name); - if(ms->env->worker) - ms->env->worker->stats.rpz_action[r->action_override]++; - lock_rw_unlock(&z->lock); - z = NULL; - } - if(z) { - break; - } - /* not found in this auth_zone */ - lock_rw_unlock(&a->lock); - } - lock_rw_unlock(&az->rpz_lock); - - if(z == NULL) - return NULL; - if(r->action_override == RPZ_NO_OVERRIDE_ACTION) { - lzt = z->type; - } else { - lzt = rpz_action_to_localzone_type(r->action_override); - } - - if(verbosity >= VERB_ALGO) { - char nm[255+1], zn[255+1]; - dname_str(is->qchase.qname, nm); - dname_str(z->name, zn); - if(strcmp(zn, nm) != 0) - verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s", - zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); - else - verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s", - nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); - } - switch(localzone_type_to_rpz_action(lzt)) { - case RPZ_NXDOMAIN_ACTION: - ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a); - break; - case RPZ_NODATA_ACTION: - ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); - break; - case RPZ_TCP_ONLY_ACTION: - /* basically a passthru here but the tcp-only will be - * honored before the query gets sent. */ - ms->respip_action_info->action = respip_truncate; - ret = NULL; - break; - case RPZ_DROP_ACTION: - ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); - ms->is_drop = 1; - break; - case RPZ_LOCAL_DATA_ACTION: - ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a); - if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); } - break; - case RPZ_PASSTHRU_ACTION: - ret = NULL; - ms->rpz_passthru = 1; - break; - default: - verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'", - rpz_action_to_string(localzone_type_to_rpz_action(lzt))); - ret = NULL; - } - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); - return ret; -} - -static int -rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo, - uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, - sldns_buffer* buf, struct regional* temp, - /* output parameters */ - struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out, - int* passthru) -{ - int ret = 0; - enum rpz_action client_action; - struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone( - az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out); - - client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action); - if(client_action == RPZ_PASSTHRU_ACTION) { - *passthru = 1; - } - if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION && - client_action != RPZ_PASSTHRU_ACTION)) { - if(client_action == RPZ_PASSTHRU_ACTION - || client_action == RPZ_INVALID_ACTION - || (client_action == RPZ_TCP_ONLY_ACTION - && !rpz_is_udp_query(repinfo))) { - ret = 0; - goto done; - } - stats->rpz_action[client_action]++; - if(client_action == RPZ_LOCAL_DATA_ACTION) { - rpz_apply_clientip_localdata_action(node, env, qinfo, - edns, repinfo, buf, temp, *a_out); - } else { - if(*r_out && (*r_out)->log) - log_rpz_apply( - (node?"clientip":"qname"), - ((*z_out)?(*z_out)->name:NULL), - (node?&node->node:NULL), - client_action, qinfo, repinfo, NULL, - (*r_out)->log_name); - local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns, - repinfo, buf, temp, 0 /* no local data used */, - rpz_action_to_localzone_type(client_action)); - if(*r_out && (*r_out)->signal_nxdomain_ra && - LDNS_RCODE_WIRE(sldns_buffer_begin(buf)) - == LDNS_RCODE_NXDOMAIN) - LDNS_RA_CLR(sldns_buffer_begin(buf)); - } - ret = 1; - goto done; - } - ret = -1; -done: - if(node != NULL) { - lock_rw_unlock(&node->lock); - } - return ret; -} - -int -rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, - struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, - size_t taglen, struct ub_server_stats* stats, int* passthru) -{ - struct rpz* r = NULL; - struct auth_zone* a = NULL; - struct local_zone* z = NULL; - int ret; - enum localzone_type lzt; - - int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo, - edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r, - passthru); - if(clientip_trigger >= 0) { - if(a) { - lock_rw_unlock(&a->lock); - } - if(z) { - lock_rw_unlock(&z->lock); - } - return clientip_trigger; - } - - if(z == NULL) { - if(a) { - lock_rw_unlock(&a->lock); - } - return 0; - } - - log_assert(r); - - if(r->action_override == RPZ_NO_OVERRIDE_ACTION) { - lzt = z->type; - } else { - lzt = rpz_action_to_localzone_type(r->action_override); - } - if(r->action_override == RPZ_PASSTHRU_ACTION || - lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) { - *passthru = 1; - } - - if(verbosity >= VERB_ALGO) { - char nm[255+1], zn[255+1]; - dname_str(qinfo->qname, nm); - dname_str(z->name, zn); - if(strcmp(zn, nm) != 0) - verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s", - zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); - else - verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s", - nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); - } - - ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp, - repinfo, stats); - - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); - - return ret; -} - -void rpz_enable(struct rpz* r) -{ - if(!r) - return; - r->disabled = 0; -} - -void rpz_disable(struct rpz* r) -{ - if(!r) - return; - r->disabled = 1; -} diff --git a/crates/libunbound-sys/unbound/services/rpz.h b/crates/libunbound-sys/unbound/services/rpz.h deleted file mode 100644 index e6d8bf56..00000000 --- a/crates/libunbound-sys/unbound/services/rpz.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * services/rpz.h - rpz service - * - * Copyright (c) 2019, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable RPZ service. - */ - -#ifndef SERVICES_RPZ_H -#define SERVICES_RPZ_H - -#include "services/localzone.h" -#include "util/locks.h" -#include "util/log.h" -#include "util/config_file.h" -#include "services/authzone.h" -#include "sldns/sbuffer.h" -#include "daemon/stats.h" -#include "respip/respip.h" -struct iter_qstate; - -/** - * RPZ triggers, only the QNAME trigger is currently supported in Unbound. - */ -enum rpz_trigger { - RPZ_QNAME_TRIGGER = 0, - /* unsupported triggers */ - RPZ_CLIENT_IP_TRIGGER, /* rpz-client-ip */ - RPZ_RESPONSE_IP_TRIGGER, /* rpz-ip */ - RPZ_NSDNAME_TRIGGER, /* rpz-nsdname */ - RPZ_NSIP_TRIGGER, /* rpz-nsip */ - RPZ_INVALID_TRIGGER, /* dname does not contain valid trigger */ -}; - -/** - * RPZ actions. - */ -enum rpz_action { - RPZ_NXDOMAIN_ACTION = 0,/* CNAME . */ - RPZ_NODATA_ACTION, /* CNAME *. */ - RPZ_PASSTHRU_ACTION, /* CNAME rpz-passthru. */ - RPZ_DROP_ACTION, /* CNAME rpz-drop. */ - RPZ_TCP_ONLY_ACTION, /* CNAME rpz-tcp-only. */ - RPZ_INVALID_ACTION, /* CNAME with (child of) TLD starting with - "rpz-" in target, SOA, NS, DNAME and - DNSSEC-related records. */ - RPZ_LOCAL_DATA_ACTION, /* anything else */ - /* RPZ override actions */ - RPZ_DISABLED_ACTION, /* RPZ action disabled using override */ - RPZ_NO_OVERRIDE_ACTION, /* RPZ action no override*/ - RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/ -}; - -struct clientip_synthesized_rrset { - struct regional* region; - struct rbtree_type entries; - /** lock on the entries tree */ - lock_rw_type lock; -}; - -struct clientip_synthesized_rr { - /** node in address tree */ - struct addr_tree_node node; - /** lock on the node item */ - lock_rw_type lock; - /** action for this address span */ - enum rpz_action action; - /** "local data" for this node */ - struct local_rrset* data; -}; - -/** - * RPZ containing policies. Pointed to from corresponding auth-zone. Part of a - * linked list to keep configuration order. Iterating or changing the linked - * list requires the rpz_lock from struct auth_zones. Changing items in this - * struct require the lock from struct auth_zone. - */ -struct rpz { - struct local_zones* local_zones; - struct respip_set* respip_set; - struct clientip_synthesized_rrset* client_set; - struct clientip_synthesized_rrset* ns_set; - struct local_zones* nsdname_zones; - uint8_t* taglist; - size_t taglistlen; - enum rpz_action action_override; - struct ub_packed_rrset_key* cname_override; - int log; - char* log_name; - /** signal NXDOMAIN blocked with unset RA flag */ - int signal_nxdomain_ra; - struct regional* region; - int disabled; -}; - -/** - * Create policy from RR and add to this RPZ. - * @param r: the rpz to add the policy to. - * @param azname: dname of the auth-zone - * @param aznamelen: the length of the auth-zone name - * @param dname: dname of the RR - * @param dnamelen: length of the dname - * @param rr_type: RR type of the RR - * @param rr_class: RR class of the RR - * @param rr_ttl: TTL of the RR - * @param rdatawl: rdata of the RR, prepended with the rdata size - * @param rdatalen: length if the RR, including the prepended rdata size - * @param rr: the complete RR, for logging purposes - * @param rr_len: the length of the complete RR - * @return: 0 on error - */ -int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, - size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl, - uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len); - -/** - * Delete policy matching RR, used for IXFR. - * @param r: the rpz to add the policy to. - * @param azname: dname of the auth-zone - * @param aznamelen: the length of the auth-zone name - * @param dname: dname of the RR - * @param dnamelen: length of the dname - * @param rr_type: RR type of the RR - * @param rr_class: RR class of the RR - * @param rdatawl: rdata of the RR, prepended with the rdata size - * @param rdatalen: length if the RR, including the prepended rdata size - */ -void rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, - uint8_t* dname, size_t dnamelen, uint16_t rr_type, uint16_t rr_class, - uint8_t* rdatawl, size_t rdatalen); - -/** - * Walk over the RPZ zones to find and apply a QNAME trigger policy. - * @param az: auth_zones struct, containing first RPZ item and RPZ lock - * @param env: module env - * @param qinfo: qinfo containing qname and qtype - * @param edns: edns data - * @param buf: buffer to write answer to - * @param temp: scratchpad - * @param repinfo: reply info - * @param taglist: taglist to lookup. - * @param taglen: length of taglist. - * @param stats: worker stats struct - * @param passthru: returns if the query can passthru further rpz processing. - * @return: 1 if client answer is ready, 0 to continue resolving - */ -int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, - struct regional* temp, struct comm_reply* repinfo, - uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, - int* passthru); - -/** - * Callback to process when the iterator module is about to send queries. - * Checks for nsip and nsdname triggers. - * @param qstate: the query state. - * @param iq: iterator module query state. - * @return NULL if nothing is done. Or a new message with the contents from - * the rpz, based on the delegation point. It is allocated in the - * qstate region. - */ -struct dns_msg* rpz_callback_from_iterator_module(struct module_qstate* qstate, - struct iter_qstate* iq); - -/** - * Callback to process when the iterator module has followed a cname. - * There can be a qname trigger for the new query name. - * @param qstate: the query state. - * @param iq: iterator module query state. - * @return NULL if nothing is done. Or a new message with the contents from - * the rpz, based on the iq.qchase. It is allocated in the qstate region. - */ -struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* qstate, - struct iter_qstate* iq); - -/** - * Delete RPZ - * @param r: RPZ struct to delete - */ -void rpz_delete(struct rpz* r); - -/** - * Clear local-zones and respip data in RPZ, used after reloading file or - * AXFR/HTTP transfer. - * @param r: RPZ to use - */ -int rpz_clear(struct rpz* r); - -/** - * Create RPZ. RPZ must be added to linked list after creation. - * @return: the newly created RPZ - */ -struct rpz* rpz_create(struct config_auth* p); - -/** - * String for RPZ action enum - * @param a: RPZ action to get string for - * @return: string for RPZ action - */ -const char* rpz_action_to_string(enum rpz_action a); - -enum rpz_action -respip_action_to_rpz_action(enum respip_action a); - -/** - * Prepare RPZ after processing feed content. - * @param r: RPZ to use - */ -void rpz_finish_config(struct rpz* r); - -/** - * Classify respip action for RPZ action - * @param a: RPZ action - * @return: the respip action - */ -enum respip_action -rpz_action_to_respip_action(enum rpz_action a); - -/** - * Enable RPZ - * @param r: RPZ struct to enable - */ -void rpz_enable(struct rpz* r); - -/** - * Disable RPZ - * @param r: RPZ struct to disable - */ -void rpz_disable(struct rpz* r); - -#endif /* SERVICES_RPZ_H */ diff --git a/crates/libunbound-sys/unbound/services/view.c b/crates/libunbound-sys/unbound/services/view.c deleted file mode 100644 index 72f36431..00000000 --- a/crates/libunbound-sys/unbound/services/view.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * services/view.c - named views containing local zones authority service. - * - * Copyright (c) 2016, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable named views that can hold local zone - * authority service. - */ -#include "config.h" -#include "services/view.h" -#include "services/localzone.h" -#include "util/config_file.h" - -int -view_cmp(const void* v1, const void* v2) -{ - struct view* a = (struct view*)v1; - struct view* b = (struct view*)v2; - - return strcmp(a->name, b->name); -} - -struct views* -views_create(void) -{ - struct views* v = (struct views*)calloc(1, - sizeof(*v)); - if(!v) - return NULL; - rbtree_init(&v->vtree, &view_cmp); - lock_rw_init(&v->lock); - lock_protect(&v->lock, &v->vtree, sizeof(v->vtree)); - return v; -} - -/* \noop (ignore this comment for doxygen) - * This prototype is defined in in respip.h, but we want to avoid - * unnecessary dependencies */ -void respip_set_delete(struct respip_set *set); - -void -view_delete(struct view* v) -{ - if(!v) - return; - lock_rw_destroy(&v->lock); - local_zones_delete(v->local_zones); - respip_set_delete(v->respip_set); - free(v->name); - free(v); -} - -static void -delviewnode(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct view* v = (struct view*)n; - view_delete(v); -} - -void -views_delete(struct views* v) -{ - if(!v) - return; - lock_rw_destroy(&v->lock); - traverse_postorder(&v->vtree, delviewnode, NULL); - free(v); -} - -/** create a new view */ -static struct view* -view_create(char* name) -{ - struct view* v = (struct view*)calloc(1, sizeof(*v)); - if(!v) - return NULL; - v->node.key = v; - if(!(v->name = strdup(name))) { - free(v); - return NULL; - } - lock_rw_init(&v->lock); - lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_type)); - return v; -} - -/** enter a new view returns with WRlock */ -static struct view* -views_enter_view_name(struct views* vs, char* name) -{ - struct view* v = view_create(name); - if(!v) { - log_err("out of memory"); - return NULL; - } - - /* add to rbtree */ - lock_rw_wrlock(&vs->lock); - lock_rw_wrlock(&v->lock); - if(!rbtree_insert(&vs->vtree, &v->node)) { - log_warn("duplicate view: %s", name); - lock_rw_unlock(&v->lock); - view_delete(v); - lock_rw_unlock(&vs->lock); - return NULL; - } - lock_rw_unlock(&vs->lock); - return v; -} - -int -views_apply_cfg(struct views* vs, struct config_file* cfg) -{ - struct config_view* cv; - struct view* v; - struct config_file lz_cfg; - /* Check existence of name in first view (last in config). Rest of - * views are already checked when parsing config. */ - if(cfg->views && !cfg->views->name) { - log_err("view without a name"); - return 0; - } - for(cv = cfg->views; cv; cv = cv->next) { - /* create and enter view */ - if(!(v = views_enter_view_name(vs, cv->name))) - return 0; - v->isfirst = cv->isfirst; - if(cv->local_zones || cv->local_data) { - if(!(v->local_zones = local_zones_create())){ - lock_rw_unlock(&v->lock); - return 0; - } - memset(&lz_cfg, 0, sizeof(lz_cfg)); - lz_cfg.local_zones = cv->local_zones; - lz_cfg.local_data = cv->local_data; - lz_cfg.local_zones_nodefault = - cv->local_zones_nodefault; - if(v->isfirst) { - /* Do not add defaults to view-specific - * local-zone when global local zone will be - * used. */ - struct config_strlist* nd; - lz_cfg.local_zones_disable_default = 1; - /* Add nodefault zones to list of zones to add, - * so they will be used as if they are - * configured as type transparent */ - for(nd = cv->local_zones_nodefault; nd; - nd = nd->next) { - char* nd_str, *nd_type; - nd_str = strdup(nd->str); - if(!nd_str) { - log_err("out of memory"); - lock_rw_unlock(&v->lock); - return 0; - } - nd_type = strdup("nodefault"); - if(!nd_type) { - log_err("out of memory"); - free(nd_str); - lock_rw_unlock(&v->lock); - return 0; - } - if(!cfg_str2list_insert( - &lz_cfg.local_zones, nd_str, - nd_type)) { - log_err("failed to insert " - "default zones into " - "local-zone list"); - lock_rw_unlock(&v->lock); - return 0; - } - } - } - if(!local_zones_apply_cfg(v->local_zones, &lz_cfg)){ - lock_rw_unlock(&v->lock); - return 0; - } - /* local_zones, local_zones_nodefault and local_data - * are free'd from config_view by local_zones_apply_cfg. - * Set pointers to NULL. */ - cv->local_zones = NULL; - cv->local_data = NULL; - cv->local_zones_nodefault = NULL; - } - lock_rw_unlock(&v->lock); - } - return 1; -} - -/** find a view by name */ -struct view* -views_find_view(struct views* vs, const char* name, int write) -{ - struct view* v; - struct view key; - key.node.key = &v; - key.name = (char *)name; - lock_rw_rdlock(&vs->lock); - if(!(v = (struct view*)rbtree_search(&vs->vtree, &key.node))) { - lock_rw_unlock(&vs->lock); - return 0; - } - if(write) { - lock_rw_wrlock(&v->lock); - } else { - lock_rw_rdlock(&v->lock); - } - lock_rw_unlock(&vs->lock); - return v; -} - -void views_print(struct views* v) -{ - /* TODO implement print */ - (void)v; -} diff --git a/crates/libunbound-sys/unbound/services/view.h b/crates/libunbound-sys/unbound/services/view.h deleted file mode 100644 index 17778100..00000000 --- a/crates/libunbound-sys/unbound/services/view.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * services/view.h - named views containing local zones authority service. - * - * Copyright (c) 2016, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to enable named views that can hold local zone - * authority service. - */ - -#ifndef SERVICES_VIEW_H -#define SERVICES_VIEW_H -#include "util/rbtree.h" -#include "util/locks.h" -struct regional; -struct config_file; -struct config_view; -struct respip_set; - - -/** - * Views storage, shared. - */ -struct views { - /** lock on the view tree */ - lock_rw_type lock; - /** rbtree of struct view */ - rbtree_type vtree; -}; - -/** - * View. Named structure holding local authority zones. - */ -struct view { - /** rbtree node, key is name */ - rbnode_type node; - /** view name. - * Has to be right after rbnode_t due to pointer arithmetic in - * view_create's lock protect */ - char* name; - /** view specific local authority zones */ - struct local_zones* local_zones; - /** response-ip configuration data for this view */ - struct respip_set* respip_set; - /** Fallback to global local_zones when there is no match in the view - * specific tree. 1 for yes, 0 for no */ - int isfirst; - /** lock on the data in the structure - * For the node and name you need to also hold the views_tree lock to - * change them. */ - lock_rw_type lock; -}; - - -/** - * Create views storage - * @return new struct or NULL on error. - */ -struct views* views_create(void); - -/** - * Delete views storage - * @param v: views to delete. - */ -void views_delete(struct views* v); - -/** - * Apply config settings; - * Takes care of locking. - * @param v: view is set up. - * @param cfg: config data. - * @return false on error. - */ -int views_apply_cfg(struct views* v, struct config_file* cfg); - -/** - * Compare two view entries in rbtree. Sort canonical. - * @param v1: view 1 - * @param v2: view 2 - * @return: negative, positive or 0 comparison value. - */ -int view_cmp(const void* v1, const void* v2); - -/** - * Delete one view - * @param v: view to delete. - */ -void view_delete(struct view* v); - -/** - * Debug helper. Print all views - * Takes care of locking. - * @param v: the views tree - */ -void views_print(struct views* v); - -/* Find a view by name. - * @param vs: views - * @param name: name of the view we are looking for - * @param write: 1 for obtaining write lock on found view, 0 for read lock - * @return: locked view or NULL. - */ -struct view* views_find_view(struct views* vs, const char* name, int write); - -#endif /* SERVICES_VIEW_H */ diff --git a/crates/libunbound-sys/unbound/sldns/keyraw.c b/crates/libunbound-sys/unbound/sldns/keyraw.c deleted file mode 100644 index befe1f72..00000000 --- a/crates/libunbound-sys/unbound/sldns/keyraw.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * keyraw.c - raw key operations and conversions - * - * (c) NLnet Labs, 2004-2008 - * - * See the file LICENSE for the license - */ -/** - * \file - * Implementation of raw DNSKEY functions (work on wire rdata). - */ - -#include "config.h" -#include "sldns/keyraw.h" -#include "sldns/rrdef.h" - -#ifdef HAVE_SSL -#include -#include -#include -#include -#include -#ifdef HAVE_OPENSSL_ENGINE_H -# include -#endif -#ifdef HAVE_OPENSSL_BN_H -#include -#endif -#ifdef HAVE_OPENSSL_PARAM_BUILD_H -# include -#else -# ifdef HAVE_OPENSSL_RSA_H -# include -# endif -# ifdef HAVE_OPENSSL_DSA_H -# include -# endif -#endif -#endif /* HAVE_SSL */ - -size_t -sldns_rr_dnskey_key_size_raw(const unsigned char* keydata, - const size_t len, int alg) -{ - /* for DSA keys */ - uint8_t t; - - /* for RSA keys */ - uint16_t exp; - uint16_t int16; - - switch ((sldns_algorithm)alg) { - case LDNS_DSA: - case LDNS_DSA_NSEC3: - if (len > 0) { - t = keydata[0]; - return (64 + t*8)*8; - } else { - return 0; - } - break; - case LDNS_RSAMD5: - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#ifdef USE_SHA2 - case LDNS_RSASHA256: - case LDNS_RSASHA512: -#endif - if (len > 0) { - if (keydata[0] == 0) { - /* big exponent */ - if (len > 3) { - memmove(&int16, keydata + 1, 2); - exp = ntohs(int16); - return (len - exp - 3)*8; - } else { - return 0; - } - } else { - exp = keydata[0]; - return (len-exp-1)*8; - } - } else { - return 0; - } - break; -#ifdef USE_GOST - case LDNS_ECC_GOST: - return 512; -#endif -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - return 256; - case LDNS_ECDSAP384SHA384: - return 384; -#endif -#ifdef USE_ED25519 - case LDNS_ED25519: - return 256; -#endif -#ifdef USE_ED448 - case LDNS_ED448: - return 456; -#endif - default: - return 0; - } -} - -uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) -{ - if(keysize < 4) { - return 0; - } - /* look at the algorithm field, copied from 2535bis */ - if (key[3] == LDNS_RSAMD5) { - uint16_t ac16 = 0; - if (keysize > 4) { - memmove(&ac16, key + keysize - 3, 2); - } - ac16 = ntohs(ac16); - return (uint16_t) ac16; - } else { - size_t i; - uint32_t ac32 = 0; - for (i = 0; i < keysize; ++i) { - ac32 += (i & 1) ? key[i] : key[i] << 8; - } - ac32 += (ac32 >> 16) & 0xFFFF; - return (uint16_t) (ac32 & 0xFFFF); - } -} - -#ifdef HAVE_SSL -#ifdef USE_GOST -/** store GOST engine reference loaded into OpenSSL library */ -ENGINE* sldns_gost_engine = NULL; - -int -sldns_key_EVP_load_gost_id(void) -{ - static int gost_id = 0; - const EVP_PKEY_ASN1_METHOD* meth; - ENGINE* e; - - if(gost_id) return gost_id; - - /* see if configuration loaded gost implementation from other engine*/ - meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); - if(meth) { - EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); - return gost_id; - } - - /* see if engine can be loaded already */ - e = ENGINE_by_id("gost"); - if(!e) { - /* load it ourself, in case statically linked */ - ENGINE_load_builtin_engines(); - ENGINE_load_dynamic(); - e = ENGINE_by_id("gost"); - } - if(!e) { - /* no gost engine in openssl */ - return 0; - } - if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { - ENGINE_finish(e); - ENGINE_free(e); - return 0; - } - - meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); - if(!meth) { - /* algo not found */ - ENGINE_finish(e); - ENGINE_free(e); - return 0; - } - /* Note: do not ENGINE_finish and ENGINE_free the acquired engine - * on some platforms this frees up the meth and unloads gost stuff */ - sldns_gost_engine = e; - - EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); - return gost_id; -} - -void sldns_key_EVP_unload_gost(void) -{ - if(sldns_gost_engine) { - ENGINE_finish(sldns_gost_engine); - ENGINE_free(sldns_gost_engine); - sldns_gost_engine = NULL; - } -} -#endif /* USE_GOST */ - -/* Retrieve params as BIGNUM from raw buffer */ -static int -sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p, - BIGNUM** q, BIGNUM** g, BIGNUM** y) -{ - uint8_t T; - uint16_t length; - uint16_t offset; - - if(len == 0) - return 0; - T = (uint8_t)key[0]; - length = (64 + T * 8); - offset = 1; - - if (T > 8) { - return 0; - } - if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) - return 0; - - *q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); - offset += SHA_DIGEST_LENGTH; - - *p = BN_bin2bn(key+offset, (int)length, NULL); - offset += length; - - *g = BN_bin2bn(key+offset, (int)length, NULL); - offset += length; - - *y = BN_bin2bn(key+offset, (int)length, NULL); - - if(!*q || !*p || !*g || !*y) { - BN_free(*q); - BN_free(*p); - BN_free(*g); - BN_free(*y); - return 0; - } - return 1; -} - -#ifndef HAVE_OSSL_PARAM_BLD_NEW -DSA * -sldns_key_buf2dsa_raw(unsigned char* key, size_t len) -{ - DSA *dsa; - BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL; - if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) { - return NULL; - } - /* create the key and set its properties */ - if(!(dsa = DSA_new())) { - return NULL; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000 || \ - (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f) -#ifndef S_SPLINT_S - dsa->p = P; - dsa->q = Q; - dsa->g = G; - dsa->pub_key = Y; -#endif /* splint */ - -#else /* OPENSSL_VERSION_NUMBER */ - if (!DSA_set0_pqg(dsa, P, Q, G)) { - /* QPG not yet attached, need to free */ - BN_free(Q); - BN_free(P); - BN_free(G); - - DSA_free(dsa); - BN_free(Y); - return NULL; - } - if (!DSA_set0_key(dsa, Y, NULL)) { - /* QPG attached, cleaned up by DSA_fre() */ - DSA_free(dsa); - BN_free(Y); - return NULL; - } -#endif - - return dsa; -} -#endif /* HAVE_OSSL_PARAM_BLD_NEW */ - -EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len) -{ -#ifdef HAVE_OSSL_PARAM_BLD_NEW - EVP_PKEY* evp_key = NULL; - EVP_PKEY_CTX* ctx; - BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL; - OSSL_PARAM_BLD* param_bld; - OSSL_PARAM* params = NULL; - if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) { - return NULL; - } - - param_bld = OSSL_PARAM_BLD_new(); - if(!param_bld) { - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return NULL; - } - if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) || - !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) || - !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) || - !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) { - OSSL_PARAM_BLD_free(param_bld); - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return NULL; - } - params = OSSL_PARAM_BLD_to_param(param_bld); - OSSL_PARAM_BLD_free(param_bld); - - ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL); - if(!ctx) { - OSSL_PARAM_free(params); - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return NULL; - } - if(EVP_PKEY_fromdata_init(ctx) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return NULL; - } - if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return NULL; - } - - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(y); - return evp_key; -#else - DSA* dsa; - EVP_PKEY* evp_key = EVP_PKEY_new(); - if(!evp_key) { - return NULL; - } - dsa = sldns_key_buf2dsa_raw(key, len); - if(!dsa) { - EVP_PKEY_free(evp_key); - return NULL; - } - if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) { - DSA_free(dsa); - EVP_PKEY_free(evp_key); - return NULL; - } - return evp_key; -#endif -} - -/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */ -static int -sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n, - BIGNUM** e) -{ - uint16_t offset; - uint16_t exp; - uint16_t int16; - - if (len == 0) - return 0; - if (key[0] == 0) { - if(len < 3) - return 0; - memmove(&int16, key+1, 2); - exp = ntohs(int16); - offset = 3; - } else { - exp = key[0]; - offset = 1; - } - - /* key length at least one */ - if(len < (size_t)offset + exp + 1) - return 0; - - /* Exponent */ - *e = BN_new(); - if(!*e) return 0; - (void) BN_bin2bn(key+offset, (int)exp, *e); - offset += exp; - - /* Modulus */ - *n = BN_new(); - if(!*n) { - BN_free(*e); - return 0; - } - /* length of the buffer must match the key length! */ - (void) BN_bin2bn(key+offset, (int)(len - offset), *n); - return 1; -} - -#ifndef HAVE_OSSL_PARAM_BLD_NEW -RSA * -sldns_key_buf2rsa_raw(unsigned char* key, size_t len) -{ - BIGNUM* modulus = NULL; - BIGNUM* exponent = NULL; - RSA *rsa; - if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent)) - return NULL; - rsa = RSA_new(); - if(!rsa) { - BN_free(exponent); - BN_free(modulus); - return NULL; - } -#if OPENSSL_VERSION_NUMBER < 0x10100000 || \ - (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f) -#ifndef S_SPLINT_S - rsa->n = modulus; - rsa->e = exponent; -#endif /* splint */ - -#else /* OPENSSL_VERSION_NUMBER */ - if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { - BN_free(exponent); - BN_free(modulus); - RSA_free(rsa); - return NULL; - } -#endif - - return rsa; -} -#endif /* HAVE_OSSL_PARAM_BLD_NEW */ - -EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len) -{ -#ifdef HAVE_OSSL_PARAM_BLD_NEW - EVP_PKEY* evp_key = NULL; - EVP_PKEY_CTX* ctx; - BIGNUM *n=NULL, *e=NULL; - OSSL_PARAM_BLD* param_bld; - OSSL_PARAM* params = NULL; - - if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) { - return NULL; - } - - param_bld = OSSL_PARAM_BLD_new(); - if(!param_bld) { - BN_free(n); - BN_free(e); - return NULL; - } - if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) { - OSSL_PARAM_BLD_free(param_bld); - BN_free(n); - BN_free(e); - return NULL; - } - if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) { - OSSL_PARAM_BLD_free(param_bld); - BN_free(n); - BN_free(e); - return NULL; - } - params = OSSL_PARAM_BLD_to_param(param_bld); - OSSL_PARAM_BLD_free(param_bld); - - ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); - if(!ctx) { - OSSL_PARAM_free(params); - BN_free(n); - BN_free(e); - return NULL; - } - if(EVP_PKEY_fromdata_init(ctx) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(n); - BN_free(e); - return NULL; - } - if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(n); - BN_free(e); - return NULL; - } - - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - BN_free(n); - BN_free(e); - return evp_key; -#else - RSA* rsa; - EVP_PKEY *evp_key = EVP_PKEY_new(); - if(!evp_key) { - return NULL; - } - rsa = sldns_key_buf2rsa_raw(key, len); - if(!rsa) { - EVP_PKEY_free(evp_key); - return NULL; - } - if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) { - RSA_free(rsa); - EVP_PKEY_free(evp_key); - return NULL; - } - return evp_key; -#endif -} - -#ifdef USE_GOST -EVP_PKEY* -sldns_gost2pkey_raw(unsigned char* key, size_t keylen) -{ - /* prefix header for X509 encoding */ - uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, - 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, - 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, - 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; - unsigned char encoded[37+64]; - const unsigned char* pp; - if(keylen != 64) { - /* key wrong size */ - return NULL; - } - - /* create evp_key */ - memmove(encoded, asn, 37); - memmove(encoded+37, key, 64); - pp = (unsigned char*)&encoded[0]; - - return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); -} -#endif /* USE_GOST */ - -#ifdef USE_ECDSA -EVP_PKEY* -sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) -{ -#ifdef HAVE_OSSL_PARAM_BLD_NEW - unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ - EVP_PKEY *evp_key = NULL; - EVP_PKEY_CTX* ctx; - OSSL_PARAM_BLD* param_bld; - OSSL_PARAM* params = NULL; - char* group = NULL; - - /* check length, which uncompressed must be 2 bignums */ - if(algo == LDNS_ECDSAP256SHA256) { - if(keylen != 2*256/8) return NULL; - group = "prime256v1"; - } else if(algo == LDNS_ECDSAP384SHA384) { - if(keylen != 2*384/8) return NULL; - group = "P-384"; - } else { - return NULL; - } - if(keylen+1 > sizeof(buf)) { /* sanity check */ - return NULL; - } - /* prepend the 0x04 for uncompressed format */ - buf[0] = POINT_CONVERSION_UNCOMPRESSED; - memmove(buf+1, key, keylen); - - param_bld = OSSL_PARAM_BLD_new(); - if(!param_bld) { - return NULL; - } - if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) || - !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) { - OSSL_PARAM_BLD_free(param_bld); - return NULL; - } - params = OSSL_PARAM_BLD_to_param(param_bld); - OSSL_PARAM_BLD_free(param_bld); - - ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); - if(!ctx) { - OSSL_PARAM_free(params); - return NULL; - } - if(EVP_PKEY_fromdata_init(ctx) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - return NULL; - } - if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - return NULL; - } - EVP_PKEY_CTX_free(ctx); - OSSL_PARAM_free(params); - return evp_key; -#else - unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ - const unsigned char* pp = buf; - EVP_PKEY *evp_key; - EC_KEY *ec; - /* check length, which uncompressed must be 2 bignums */ - if(algo == LDNS_ECDSAP256SHA256) { - if(keylen != 2*256/8) return NULL; - ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - } else if(algo == LDNS_ECDSAP384SHA384) { - if(keylen != 2*384/8) return NULL; - ec = EC_KEY_new_by_curve_name(NID_secp384r1); - } else ec = NULL; - if(!ec) return NULL; - if(keylen+1 > sizeof(buf)) { /* sanity check */ - EC_KEY_free(ec); - return NULL; - } - /* prepend the 0x02 (from docs) (or actually 0x04 from implementation - * of openssl) for uncompressed data */ - buf[0] = POINT_CONVERSION_UNCOMPRESSED; - memmove(buf+1, key, keylen); - if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { - EC_KEY_free(ec); - return NULL; - } - evp_key = EVP_PKEY_new(); - if(!evp_key) { - EC_KEY_free(ec); - return NULL; - } - if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { - EVP_PKEY_free(evp_key); - EC_KEY_free(ec); - return NULL; - } - return evp_key; -#endif /* HAVE_OSSL_PARAM_BLD_NEW */ -} -#endif /* USE_ECDSA */ - -#ifdef USE_ED25519 -EVP_PKEY* -sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) -{ - /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */ - uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, - 0x70, 0x03, 0x21, 0x00}; - int pre_len = 12; - uint8_t buf[256]; - EVP_PKEY *evp_key; - /* pp gets modified by d2i() */ - const unsigned char* pp = (unsigned char*)buf; - if(keylen != 32 || keylen + pre_len > sizeof(buf)) - return NULL; /* wrong length */ - memmove(buf, pre, pre_len); - memmove(buf+pre_len, key, keylen); - evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); - return evp_key; -} -#endif /* USE_ED25519 */ - -#ifdef USE_ED448 -EVP_PKEY* -sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen) -{ - /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */ - uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, - 0x71, 0x03, 0x3a, 0x00}; - int pre_len = 12; - uint8_t buf[256]; - EVP_PKEY *evp_key; - /* pp gets modified by d2i() */ - const unsigned char* pp = (unsigned char*)buf; - if(keylen != 57 || keylen + pre_len > sizeof(buf)) - return NULL; /* wrong length */ - memmove(buf, pre, pre_len); - memmove(buf+pre_len, key, keylen); - evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); - return evp_key; -} -#endif /* USE_ED448 */ - -int -sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, - const EVP_MD* md) -{ - EVP_MD_CTX* ctx; - ctx = EVP_MD_CTX_create(); - if(!ctx) - return 0; - if(!EVP_DigestInit_ex(ctx, md, NULL) || - !EVP_DigestUpdate(ctx, data, len) || - !EVP_DigestFinal_ex(ctx, dest, NULL)) { - EVP_MD_CTX_destroy(ctx); - return 0; - } - EVP_MD_CTX_destroy(ctx); - return 1; -} -#endif /* HAVE_SSL */ diff --git a/crates/libunbound-sys/unbound/sldns/keyraw.h b/crates/libunbound-sys/unbound/sldns/keyraw.h deleted file mode 100644 index b1f19740..00000000 --- a/crates/libunbound-sys/unbound/sldns/keyraw.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * keyraw.h -- raw key and signature access and conversion - * - * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. - * - */ - -/** - * \file - * - * raw key and signature access and conversion - * - * Since those functions heavily rely op cryptographic operations, - * this module is dependent on openssl. - * - */ - -#ifndef LDNS_KEYRAW_H -#define LDNS_KEYRAW_H - -#ifdef __cplusplus -extern "C" { -#endif -#if LDNS_BUILD_CONFIG_HAVE_SSL -# include -# include -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ - -/** - * get the length of the keydata in bits - * \param[in] keydata the raw key data - * \param[in] len the length of the keydata - * \param[in] alg the cryptographic algorithm this is a key for - * \return the keysize in bits, or 0 on error - */ -size_t sldns_rr_dnskey_key_size_raw(const unsigned char *keydata, - const size_t len, int alg); - -/** - * Calculates keytag of DNSSEC key, operates on wireformat rdata. - * \param[in] key the key as uncompressed wireformat rdata. - * \param[in] keysize length of key data. - * \return the keytag - */ -uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize); - -#if LDNS_BUILD_CONFIG_HAVE_SSL -/** - * Get the PKEY id for GOST, loads GOST into openssl as a side effect. - * Only available if GOST is compiled into the library and openssl. - * \return the gost id for EVP_CTX creation. - */ -int sldns_key_EVP_load_gost_id(void); - -/** Release the engine reference held for the GOST engine. */ -void sldns_key_EVP_unload_gost(void); - -#ifndef HAVE_OSSL_PARAM_BLD_NEW -/** - * Like sldns_key_buf2dsa, but uses raw buffer. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return a DSA * structure with the key material - */ -DSA *sldns_key_buf2dsa_raw(unsigned char* key, size_t len); -#endif - -/** - * Converts a holding buffer with DSA key material to EVP PKEY in openssl. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return the key or NULL on error. - */ -EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len); - -/** - * Converts a holding buffer with key material to EVP PKEY in openssl. - * Only available if ldns was compiled with GOST. - * \param[in] key data to convert - * \param[in] keylen length of the key data - * \return the key or NULL on error. - */ -EVP_PKEY* sldns_gost2pkey_raw(unsigned char* key, size_t keylen); - -/** - * Converts a holding buffer with key material to EVP PKEY in openssl. - * Only available if ldns was compiled with ECDSA. - * \param[in] key data to convert - * \param[in] keylen length of the key data - * \param[in] algo precise algorithm to initialize ECC group values. - * \return the key or NULL on error. - */ -EVP_PKEY* sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); - -#ifndef HAVE_OSSL_PARAM_BLD_NEW -/** - * Like sldns_key_buf2rsa, but uses raw buffer. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return a RSA * structure with the key material - */ -RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len); -#endif - -/** - * Converts a holding buffer with RSA key material to EVP PKEY in openssl. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return the key or NULL on error. - */ -EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len); - -/** - * Converts a holding buffer with key material to EVP PKEY in openssl. - * Only available if ldns was compiled with ED25519. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return the key or NULL on error. - */ -EVP_PKEY* sldns_ed255192pkey_raw(const unsigned char* key, size_t len); - -/** - * Converts a holding buffer with key material to EVP PKEY in openssl. - * Only available if ldns was compiled with ED448. - * \param[in] key the uncompressed wireformat of the key. - * \param[in] len length of key data - * \return the key or NULL on error. - */ -EVP_PKEY* sldns_ed4482pkey_raw(const unsigned char* key, size_t len); - -/** - * Utility function to calculate hash using generic EVP_MD pointer. - * \param[in] data the data to hash. - * \param[in] len length of data. - * \param[out] dest the destination of the hash, must be large enough. - * \param[in] md the message digest to use. - * \return true if worked, false on failure. - */ -int sldns_digest_evp(unsigned char* data, unsigned int len, - unsigned char* dest, const EVP_MD* md); - -#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_KEYRAW_H */ diff --git a/crates/libunbound-sys/unbound/sldns/parse.c b/crates/libunbound-sys/unbound/sldns/parse.c deleted file mode 100644 index 8ea08466..00000000 --- a/crates/libunbound-sys/unbound/sldns/parse.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * a generic (simple) parser. Use to parse rr's, private key - * information and /etc/resolv.conf files - * - * a Net::DNS like library for C - * LibDNS Team @ NLnet Labs - * (c) NLnet Labs, 2005-2006 - * See the file LICENSE for the license - */ -#include "config.h" -#include "sldns/parse.h" -#include "sldns/parseutil.h" -#include "sldns/sbuffer.h" - -#include -#include - -sldns_lookup_table sldns_directive_types[] = { - { LDNS_DIR_TTL, "$TTL" }, - { LDNS_DIR_ORIGIN, "$ORIGIN" }, - { LDNS_DIR_INCLUDE, "$INCLUDE" }, - { 0, NULL } -}; - -/* add max_limit here? */ -ssize_t -sldns_fget_token(FILE *f, char *token, const char *delim, size_t limit) -{ - return sldns_fget_token_l(f, token, delim, limit, NULL); -} - -ssize_t -sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) -{ - int c, prev_c; - int p; /* 0 -> no parentheses seen, >0 nr of ( seen */ - int com, quoted, only_blank; - char *t; - size_t i; - const char *d; - const char *del; - - /* standard delimiters */ - if (!delim) { - /* from isspace(3) */ - del = LDNS_PARSE_NORMAL; - } else { - del = delim; - } - - p = 0; - i = 0; - com = 0; - quoted = 0; - prev_c = 0; - only_blank = 1; /* Assume we got only until now */ - t = token; - if (del[0] == '"') { - quoted = 1; - } - while ((c = getc(f)) != EOF) { - if (c == '\r') /* carriage return */ - c = ' '; - if (c == '(' && prev_c != '\\' && !quoted) { - /* this only counts for non-comments */ - if (com == 0) { - p++; - } - prev_c = c; - continue; - } - - if (c == ')' && prev_c != '\\' && !quoted) { - /* this only counts for non-comments */ - if (com == 0) { - p--; - } - prev_c = c; - continue; - } - - if (p < 0) { - /* more ) then ( - close off the string */ - *t = '\0'; - return 0; - } - - /* do something with comments ; */ - if (c == ';' && quoted == 0) { - if (prev_c != '\\') { - com = 1; - } - } - if (c == '\"' && com == 0 && prev_c != '\\') { - quoted = 1 - quoted; - } - - if (c == '\n' && com != 0) { - /* comments */ - com = 0; - *t = ' '; - if (line_nr) { - *line_nr = *line_nr + 1; - } - if (only_blank && i > 0) { - /* Got only so far. Reset and try - * again with the next line. - */ - i = 0; - t = token; - } - if (p == 0) { - /* If p != 0 then the next line is a continuation. So - * we assume that the next line starts with a blank only - * if it is actually a new line. - */ - only_blank = 1; /* Assume next line starts with - * . - */ - } - if (p == 0 && i > 0) { - goto tokenread; - } else { - prev_c = c; - continue; - } - } - - if (com == 1) { - *t = ' '; - prev_c = c; - continue; - } - - if (c == '\n' && p != 0 && t > token) { - /* in parentheses */ - if (line_nr) { - *line_nr = *line_nr + 1; - } - if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { - *t = '\0'; - return -1; - } - *t++ = ' '; - prev_c = c; - continue; - } - - /* check if we hit the delim */ - for (d = del; *d; d++) { - if (c == *d) - break; - } - - if (c == *d && i > 0 && prev_c != '\\' && p == 0) { - if (c == '\n' && line_nr) { - *line_nr = *line_nr + 1; - } - if (only_blank) { - /* Got only so far. Reset and - * try again with the next line. - */ - i = 0; - t = token; - only_blank = 1; - prev_c = c; - continue; - } - goto tokenread; - } - if (c != ' ' && c != '\t') { - /* Found something that is not */ - only_blank= 0; - } - if (c != '\0' && c != '\n') { - i++; - } - /* is there space for the character and the zero after it */ - if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { - *t = '\0'; - return -1; - } - if (c != '\0' && c != '\n') { - *t++ = c; - } - if (c == '\n') { - if (line_nr) { - *line_nr = *line_nr + 1; - } - only_blank = 1; /* Assume next line starts with - * . - */ - } - if (c == '\\' && prev_c == '\\') - prev_c = 0; - else prev_c = c; - } - *t = '\0'; - if (c == EOF) { - return (ssize_t)i; - } - - if (i == 0) { - /* nothing read */ - return -1; - } - if (p != 0) { - return -1; - } - return (ssize_t)i; - -tokenread: - if(*del == '"') - /* do not skip over quotes after the string, they are part - * of the next string. But skip over whitespace (if needed)*/ - sldns_fskipcs_l(f, del+1, line_nr); - else sldns_fskipcs_l(f, del, line_nr); - *t = '\0'; - if (p != 0) { - return -1; - } - - return (ssize_t)i; -} - -ssize_t -sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, - const char *d_del, size_t data_limit) -{ - return sldns_fget_keyword_data_l(f, keyword, k_del, data, d_del, - data_limit, NULL); -} - -ssize_t -sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, - const char *d_del, size_t data_limit, int *line_nr) -{ - /* we assume: keyword|sep|data */ - char *fkeyword; - ssize_t i; - - if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) - return -1; - fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN); - if(!fkeyword) - return -1; - - i = sldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN); - if(i==0 || i==-1) { - free(fkeyword); - return -1; - } - - /* case??? i instead of strlen? */ - if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) { - /* whee! */ - /* printf("%s\n%s\n", "Matching keyword", fkeyword); */ - i = sldns_fget_token_l(f, data, d_del, data_limit, line_nr); - free(fkeyword); - return i; - } else { - /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/ - free(fkeyword); - return -1; - } -} - -int -sldns_bgetc(sldns_buffer *buffer) -{ - if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { - sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer)); - /* sldns_buffer_rewind(buffer);*/ - return EOF; - } - return (int)sldns_buffer_read_u8(buffer); -} - -ssize_t -sldns_bget_token(sldns_buffer *b, char *token, const char *delim, size_t limit) -{ - return sldns_bget_token_par(b, token, delim, limit, NULL, NULL); -} - -ssize_t -sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim, - size_t limit, int* par, const char* skipw) -{ - int c, lc; - int p; /* 0 -> no parentheses seen, >0 nr of ( seen */ - int com, quoted; - char *t; - size_t i; - const char *d; - const char *del; - - /* standard delimiters */ - if (!delim) { - /* from isspace(3) */ - del = LDNS_PARSE_NORMAL; - } else { - del = delim; - } - - p = (par?*par:0); - i = 0; - com = 0; - quoted = 0; - t = token; - lc = 0; - if (del[0] == '"') { - quoted = 1; - } - - while ((c = sldns_bgetc(b)) != EOF) { - if (c == '\r') /* carriage return */ - c = ' '; - if (c == '(' && lc != '\\' && !quoted) { - /* this only counts for non-comments */ - if (com == 0) { - if(par) (*par)++; - p++; - } - lc = c; - continue; - } - - if (c == ')' && lc != '\\' && !quoted) { - /* this only counts for non-comments */ - if (com == 0) { - if(par) (*par)--; - p--; - } - lc = c; - continue; - } - - if (p < 0) { - /* more ) then ( */ - *t = '\0'; - return 0; - } - - /* do something with comments ; */ - if (c == ';' && quoted == 0) { - if (lc != '\\') { - com = 1; - } - } - if (c == '"' && com == 0 && lc != '\\') { - quoted = 1 - quoted; - } - - if (c == '\n' && com != 0) { - /* comments */ - com = 0; - *t = ' '; - lc = c; - continue; - } - - if (com == 1) { - *t = ' '; - lc = c; - continue; - } - - if (c == '\n' && p != 0) { - /* in parentheses */ - /* do not write ' ' if we want to skip spaces */ - if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) { - /* check for space for the space character and a zero delimiter after that. */ - if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { - *t = '\0'; - return -1; - } - *t++ = ' '; - } - lc = c; - continue; - } - - /* check to skip whitespace at start, but also after ( */ - if(skipw && i==0 && !com && !quoted && lc != '\\') { - if(strchr(skipw, c)) { - lc = c; - continue; - } - } - - /* check if we hit the delim */ - for (d = del; *d; d++) { - /* we can only exit if no parens or user tracks them */ - if (c == *d && lc != '\\' && (p == 0 || par)) { - goto tokenread; - } - } - - i++; - if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) { - *t = '\0'; - return -1; - } - *t++ = c; - - if (c == '\\' && lc == '\\') { - lc = 0; - } else { - lc = c; - } - } - *t = '\0'; - if (i == 0) { - /* nothing read */ - return -1; - } - if (!par && p != 0) { - return -1; - } - return (ssize_t)i; - -tokenread: - if(*del == '"') - /* do not skip over quotes after the string, they are part - * of the next string. But skip over whitespace (if needed)*/ - sldns_bskipcs(b, del+1); - else sldns_bskipcs(b, del); - *t = '\0'; - - if (!par && p != 0) { - return -1; - } - return (ssize_t)i; -} - - -void -sldns_bskipcs(sldns_buffer *buffer, const char *s) -{ - int found; - char c; - const char *d; - - while(sldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) { - c = (char) sldns_buffer_read_u8_at(buffer, buffer->_position); - found = 0; - for (d = s; *d; d++) { - if (*d == c) { - found = 1; - } - } - if (found && buffer->_limit > buffer->_position) { - buffer->_position += sizeof(char); - } else { - return; - } - } -} - -void -sldns_fskipcs(FILE *fp, const char *s) -{ - sldns_fskipcs_l(fp, s, NULL); -} - -void -sldns_fskipcs_l(FILE *fp, const char *s, int *line_nr) -{ - int found; - int c; - const char *d; - - while ((c = fgetc(fp)) != EOF) { - if (line_nr && c == '\n') { - *line_nr = *line_nr + 1; - } - found = 0; - for (d = s; *d; d++) { - if (*d == c) { - found = 1; - } - } - if (!found) { - /* with getc, we've read too far */ - ungetc(c, fp); - return; - } - } -} - -ssize_t -sldns_bget_keyword_data(sldns_buffer *b, const char *keyword, const char *k_del, char -*data, const char *d_del, size_t data_limit) -{ - /* we assume: keyword|sep|data */ - char *fkeyword; - ssize_t i; - - if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) - return -1; - fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN); - if(!fkeyword) - return -1; /* out of memory */ - - i = sldns_bget_token(b, fkeyword, k_del, data_limit); - if(i==0 || i==-1) { - free(fkeyword); - return -1; /* nothing read */ - } - - /* case??? */ - if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) { - free(fkeyword); - /* whee, the match! */ - /* retrieve it's data */ - i = sldns_bget_token(b, data, d_del, 0); - return i; - } else { - free(fkeyword); - return -1; - } -} - diff --git a/crates/libunbound-sys/unbound/sldns/parse.h b/crates/libunbound-sys/unbound/sldns/parse.h deleted file mode 100644 index fa8f51a9..00000000 --- a/crates/libunbound-sys/unbound/sldns/parse.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * parse.h - * - * a Net::DNS like library for C - * LibDNS Team @ NLnet Labs - * (c) NLnet Labs, 2005-2006 - * See the file LICENSE for the license - */ - -#ifndef LDNS_PARSE_H -#define LDNS_PARSE_H - -struct sldns_buffer; - -#ifdef __cplusplus -extern "C" { -#endif - -#define LDNS_PARSE_SKIP_SPACE "\f\n\r\v" -#define LDNS_PARSE_NORMAL " \f\n\r\t\v" -#define LDNS_PARSE_NO_NL " \t" -#define LDNS_MAX_LINELEN 10230 -#define LDNS_MAX_KEYWORDLEN 32 - - -/** - * \file - * - * Contains some low-level parsing functions, mostly used in the _frm_str - * family of functions. - */ - -/** - * different type of directives in zone files - * We now deal with $TTL, $ORIGIN and $INCLUDE. - * The latter is not implemented in ldns (yet) - */ -enum sldns_enum_directive -{ - LDNS_DIR_TTL, - LDNS_DIR_ORIGIN, - LDNS_DIR_INCLUDE -}; -typedef enum sldns_enum_directive sldns_directive; - -/** - * returns a token/char from the stream F. - * This function deals with ( and ) in the stream, - * and ignores them when encountered - * \param[in] *f the file to read from - * \param[out] *token the read token is put here - * \param[in] *delim chars at which the parsing should stop - * \param[in] *limit how much to read. If 0 the builtin maximum is used - * \return 0 on error of EOF of the stream F. Otherwise return the length of what is read - */ -ssize_t sldns_fget_token(FILE *f, char *token, const char *delim, size_t limit); - -/** - * returns a token/char from the stream F. - * This function deals with ( and ) in the stream, - * and ignores when it finds them. - * \param[in] *f the file to read from - * \param[out] *token the token is put here - * \param[in] *delim chars at which the parsing should stop - * \param[in] *limit how much to read. If 0 use builtin maximum - * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) - * \return 0 on error of EOF of F otherwise return the length of what is read - */ -ssize_t sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr); - -/** - * returns a token/char from the buffer b. - * This function deals with ( and ) in the buffer, - * and ignores when it finds them. - * \param[in] *b the buffer to read from - * \param[out] *token the token is put here - * \param[in] *delim chars at which the parsing should stop - * \param[in] *limit how much to read. If 0 the builtin maximum is used - * \param[in] *par if you pass nonNULL, set to 0 on first call, the parenthesis - * state is stored in it, for use on next call. User must check it is back - * to zero after last bget in string (for parse error). If you pass NULL, - * the entire parenthesized string is read in. - * \param[in] skipw string with whitespace to skip before the start of the - * token, like " ", or " \t", or NULL for none. - * \returns 0 on error of EOF of b. Otherwise return the length of what is read - */ -ssize_t sldns_bget_token_par(struct sldns_buffer *b, char *token, const char *delim, size_t limit, int* par, const char* skipw); - -/** - * returns a token/char from the buffer b. - * This function deals with ( and ) in the buffer, - * and ignores when it finds them. - * \param[in] *b the buffer to read from - * \param[out] *token the token is put here - * \param[in] *delim chars at which the parsing should stop - * \param[in] *limit how much to read. If 0 the builtin maximum is used - * \returns 0 on error of EOF of b. Otherwise return the length of what is read - */ -ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim, size_t limit); - -/* - * searches for keyword and delim in a file. Gives everything back - * after the keyword + k_del until we hit d_del - * \param[in] f file pointer to read from - * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimiter - * \param[out] data the data found - * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer - * \return the number of character read - */ -ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); - -/* - * searches for keyword and delim. Gives everything back - * after the keyword + k_del until we hit d_del - * \param[in] f file pointer to read from - * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimiter - * \param[out] data the data found - * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer - * \param[in] line_nr pointer to an integer containing the current line number (for -debugging purposes) - * \return the number of character read - */ -ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr); - -/* - * searches for keyword and delim in a buffer. Gives everything back - * after the keyword + k_del until we hit d_del - * \param[in] b buffer pointer to read from - * \param[in] keyword keyword to look for - * \param[in] k_del keyword delimiter - * \param[out] data the data found - * \param[in] d_del the data delimiter - * \param[in] data_limit maximum size the the data buffer - * \return the number of character read - */ -ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); - -/** - * returns the next character from a buffer. Advances the position pointer with 1. - * When end of buffer is reached returns EOF. This is the buffer's equivalent - * for getc(). - * \param[in] *buffer buffer to read from - * \return EOF on failure otherwise return the character - */ -int sldns_bgetc(struct sldns_buffer *buffer); - -/** - * skips all of the characters in the given string in the buffer, moving - * the position to the first character that is not in *s. - * \param[in] *buffer buffer to use - * \param[in] *s characters to skip - */ -void sldns_bskipcs(struct sldns_buffer *buffer, const char *s); - -/** - * skips all of the characters in the given string in the fp, moving - * the position to the first character that is not in *s. - * \param[in] *fp file to use - * \param[in] *s characters to skip - */ -void sldns_fskipcs(FILE *fp, const char *s); - - -/** - * skips all of the characters in the given string in the fp, moving - * the position to the first character that is not in *s. - * \param[in] *fp file to use - * \param[in] *s characters to skip - * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) - */ -void sldns_fskipcs_l(FILE *fp, const char *s, int *line_nr); - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_PARSE_H */ diff --git a/crates/libunbound-sys/unbound/sldns/parseutil.c b/crates/libunbound-sys/unbound/sldns/parseutil.c deleted file mode 100644 index dd1f3348..00000000 --- a/crates/libunbound-sys/unbound/sldns/parseutil.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * parseutil.c - parse utilities for string and wire conversion - * - * (c) NLnet Labs, 2004-2006 - * - * See the file LICENSE for the license - */ -/** - * \file - * - * Utility functions for parsing, base32(DNS variant) and base64 encoding - * and decoding, Hex, Time units, Escape codes. - */ - -#include "config.h" -#include "sldns/parseutil.h" -#include -#include -#include - -sldns_lookup_table * -sldns_lookup_by_name(sldns_lookup_table *table, const char *name) -{ - while (table->name != NULL) { - if (strcasecmp(name, table->name) == 0) - return table; - table++; - } - return NULL; -} - -sldns_lookup_table * -sldns_lookup_by_id(sldns_lookup_table *table, int id) -{ - while (table->name != NULL) { - if (table->id == id) - return table; - table++; - } - return NULL; -} - -/* Number of days per month (except for February in leap years). */ -static const int mdays[] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -#define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) -#define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) - -static int -is_leap_year(int year) -{ - return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 - || LDNS_MOD(year, 400) == 0); -} - -static int -leap_days(int y1, int y2) -{ - --y1; - --y2; - return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - - (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + - (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); -} - -/* - * Code adapted from Python 2.4.1 sources (Lib/calendar.py). - */ -time_t -sldns_mktime_from_utc(const struct tm *tm) -{ - int year = 1900 + tm->tm_year; - time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); - time_t hours; - time_t minutes; - time_t seconds; - int i; - - for (i = 0; i < tm->tm_mon; ++i) { - days += mdays[i]; - } - if (tm->tm_mon > 1 && is_leap_year(year)) { - ++days; - } - days += tm->tm_mday - 1; - - hours = days * 24 + tm->tm_hour; - minutes = hours * 60 + tm->tm_min; - seconds = minutes * 60 + tm->tm_sec; - - return seconds; -} - -#if SIZEOF_TIME_T <= 4 - -static void -sldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) -{ - int year = 1970; - int new_year; - - while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { - new_year = year + (int) LDNS_DIV(days, 365); - days -= (new_year - year) * 365; - days -= leap_days(year, new_year); - year = new_year; - } - result->tm_year = year; - result->tm_yday = (int) days; -} - -/* Number of days per month in a leap year. */ -static const int leap_year_mdays[] = { - 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -static void -sldns_mon_and_mday_from_year_and_yday(struct tm *result) -{ - int idays = result->tm_yday; - const int *mon_lengths = is_leap_year(result->tm_year) ? - leap_year_mdays : mdays; - - result->tm_mon = 0; - while (idays >= mon_lengths[result->tm_mon]) { - idays -= mon_lengths[result->tm_mon++]; - } - result->tm_mday = idays + 1; -} - -static void -sldns_wday_from_year_and_yday(struct tm *result) -{ - result->tm_wday = 4 /* 1-1-1970 was a thursday */ - + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) - + leap_days(1970, result->tm_year) - + result->tm_yday; - result->tm_wday = LDNS_MOD(result->tm_wday, 7); - if (result->tm_wday < 0) { - result->tm_wday += 7; - } -} - -static struct tm * -sldns_gmtime64_r(int64_t clock, struct tm *result) -{ - result->tm_isdst = 0; - result->tm_sec = (int) LDNS_MOD(clock, 60); - clock = LDNS_DIV(clock, 60); - result->tm_min = (int) LDNS_MOD(clock, 60); - clock = LDNS_DIV(clock, 60); - result->tm_hour = (int) LDNS_MOD(clock, 24); - clock = LDNS_DIV(clock, 24); - - sldns_year_and_yday_from_days_since_epoch(clock, result); - sldns_mon_and_mday_from_year_and_yday(result); - sldns_wday_from_year_and_yday(result); - result->tm_year -= 1900; - - return result; -} - -#endif /* SIZEOF_TIME_T <= 4 */ - -static int64_t -sldns_serial_arithmetics_time(int32_t time, time_t now) -{ - int32_t offset = (int32_t)((uint32_t) time - (uint32_t) now); - return (int64_t) now + offset; -} - -struct tm * -sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result) -{ -#if SIZEOF_TIME_T <= 4 - int64_t secs_since_epoch = sldns_serial_arithmetics_time(time, now); - return sldns_gmtime64_r(secs_since_epoch, result); -#else - time_t secs_since_epoch = sldns_serial_arithmetics_time(time, now); - return gmtime_r(&secs_since_epoch, result); -#endif -} - -int -sldns_hexdigit_to_int(char ch) -{ - switch (ch) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: - return -1; - } -} - -uint32_t -sldns_str2period(const char *nptr, const char **endptr, int* overflow) -{ - int sign = 0; - uint32_t i = 0; - uint32_t seconds = 0; - const uint32_t maxint = 0xffffffff; - *overflow = 0; - - for(*endptr = nptr; **endptr; (*endptr)++) { - switch (**endptr) { - case ' ': - case '\t': - break; - case '-': - if(sign == 0) { - sign = -1; - } else { - return seconds; - } - break; - case '+': - if(sign == 0) { - sign = 1; - } else { - return seconds; - } - break; - case 's': - case 'S': - if(seconds > maxint-i) { - *overflow = 1; - return 0; - } - seconds += i; - i = 0; - break; - case 'm': - case 'M': - if(i > maxint/60 || seconds > maxint-(i*60)) { - *overflow = 1; - return 0; - } - seconds += i * 60; - i = 0; - break; - case 'h': - case 'H': - if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) { - *overflow = 1; - return 0; - } - seconds += i * 60 * 60; - i = 0; - break; - case 'd': - case 'D': - if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) { - *overflow = 1; - return 0; - } - seconds += i * 60 * 60 * 24; - i = 0; - break; - case 'w': - case 'W': - if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) { - *overflow = 1; - return 0; - } - seconds += i * 60 * 60 * 24 * 7; - i = 0; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) { - *overflow = 1; - return 0; - } - i *= 10; - i += (**endptr - '0'); - break; - default: - if(seconds > maxint-i) { - *overflow = 1; - return 0; - } - seconds += i; - /* disregard signedness */ - return seconds; - } - } - if(seconds > maxint-i) { - *overflow = 1; - return 0; - } - seconds += i; - /* disregard signedness */ - return seconds; -} - -int -sldns_parse_escape(uint8_t *ch_p, const char** str_p) -{ - uint16_t val; - - if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) && - (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) && - (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) { - - val = (uint16_t)(((*str_p)[0] - '0') * 100 + - ((*str_p)[1] - '0') * 10 + - ((*str_p)[2] - '0')); - - if (val > 255) { - goto error; - } - *ch_p = (uint8_t)val; - *str_p += 3; - return 1; - - } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) { - - *ch_p = (uint8_t)*(*str_p)++; - return 1; - } -error: - *str_p = NULL; - return 0; /* LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE */ -} - -/** parse one character, with escape codes */ -int -sldns_parse_char(uint8_t *ch_p, const char** str_p) -{ - switch (**str_p) { - - case '\0': return 0; - - case '\\': *str_p += 1; - return sldns_parse_escape(ch_p, str_p); - - default: *ch_p = (uint8_t)*(*str_p)++; - return 1; - } -} - -size_t sldns_b32_ntop_calculate_size(size_t src_data_length) -{ - return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8; -} - -size_t sldns_b32_ntop_calculate_size_no_padding(size_t src_data_length) -{ - return ((src_data_length + 3) * 8 / 5) - 4; -} - -static int -sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz, - int extended_hex, int add_padding) -{ - size_t ret_sz; - const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv" - : "abcdefghijklmnopqrstuvwxyz234567"; - - size_t c = 0; /* c is used to carry partial base32 character over - * byte boundaries for sizes with a remainder. - * (i.e. src_sz % 5 != 0) - */ - - ret_sz = add_padding ? sldns_b32_ntop_calculate_size(src_sz) - : sldns_b32_ntop_calculate_size_no_padding(src_sz); - - /* Do we have enough space? */ - if (dst_sz < ret_sz + 1) - return -1; - - /* We know the size; terminate the string */ - dst[ret_sz] = '\0'; - - /* First process all chunks of five */ - while (src_sz >= 5) { - /* 00000... ........ ........ ........ ........ */ - dst[0] = b32[(src[0] ) >> 3]; - - /* .....111 11...... ........ ........ ........ */ - dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6]; - - /* ........ ..22222. ........ ........ ........ */ - dst[2] = b32[(src[1] & 0x3e) >> 1]; - - /* ........ .......3 3333.... ........ ........ */ - dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4]; - - /* ........ ........ ....4444 4....... ........ */ - dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7]; - - /* ........ ........ ........ .55555.. ........ */ - dst[5] = b32[(src[3] & 0x7c) >> 2]; - - /* ........ ........ ........ ......66 666..... */ - dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5]; - - /* ........ ........ ........ ........ ...77777 */ - dst[7] = b32[(src[4] & 0x1f) ]; - - src_sz -= 5; - src += 5; - dst += 8; - } - /* Process what remains */ - switch (src_sz) { - case 4: /* ........ ........ ........ ......66 666..... */ - dst[6] = b32[(src[3] & 0x03) << 3]; - - /* ........ ........ ........ .55555.. ........ */ - dst[5] = b32[(src[3] & 0x7c) >> 2]; - - /* ........ ........ ....4444 4....... ........ */ - c = src[3] >> 7 ; - /* fallthrough */ - case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; - - /* ........ .......3 3333.... ........ ........ */ - c = src[2] >> 4 ; - /* fallthrough */ - case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; - - /* ........ ..22222. ........ ........ ........ */ - dst[2] = b32[(src[1] & 0x3e) >> 1]; - - /* .....111 11...... ........ ........ ........ */ - c = src[1] >> 6 ; - /* fallthrough */ - case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; - - /* 00000... ........ ........ ........ ........ */ - dst[0] = b32[ src[0] >> 3]; - } - /* Add padding */ - if (add_padding) { - switch (src_sz) { - case 1: dst[2] = '='; - dst[3] = '='; - /* fallthrough */ - case 2: dst[4] = '='; - /* fallthrough */ - case 3: dst[5] = '='; - dst[6] = '='; - /* fallthrough */ - case 4: dst[7] = '='; - } - } - return (int)ret_sz; -} - -int -sldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) -{ - return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 0, 1); -} - -int -sldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, - char* dst, size_t dst_sz) -{ - return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 1, 1); -} - -size_t sldns_b32_pton_calculate_size(size_t src_text_length) -{ - return src_text_length * 5 / 8; -} - -static int -sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz, - int extended_hex, int check_padding) -{ - size_t i = 0; - char ch = '\0'; - uint8_t buf[8]; - uint8_t* start = dst; - - while (src_sz) { - /* Collect 8 characters in buf (if possible) */ - for (i = 0; i < 8; i++) { - - do { - ch = *src++; - --src_sz; - - } while (isspace((unsigned char)ch) && src_sz > 0); - - if (ch == '=' || ch == '\0') - break; - - else if (extended_hex) - - if (ch >= '0' && ch <= '9') - buf[i] = (uint8_t)ch - '0'; - else if (ch >= 'a' && ch <= 'v') - buf[i] = (uint8_t)ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'V') - buf[i] = (uint8_t)ch - 'A' + 10; - else - return -1; - - else if (ch >= 'a' && ch <= 'z') - buf[i] = (uint8_t)ch - 'a'; - else if (ch >= 'A' && ch <= 'Z') - buf[i] = (uint8_t)ch - 'A'; - else if (ch >= '2' && ch <= '7') - buf[i] = (uint8_t)ch - '2' + 26; - else - return -1; - } - /* Less that 8 characters. We're done. */ - if (i < 8) - break; - - /* Enough space available at the destination? */ - if (dst_sz < 5) - return -1; - - /* 00000... ........ ........ ........ ........ */ - /* .....111 11...... ........ ........ ........ */ - dst[0] = buf[0] << 3 | buf[1] >> 2; - - /* .....111 11...... ........ ........ ........ */ - /* ........ ..22222. ........ ........ ........ */ - /* ........ .......3 3333.... ........ ........ */ - dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; - - /* ........ .......3 3333.... ........ ........ */ - /* ........ ........ ....4444 4....... ........ */ - dst[2] = buf[3] << 4 | buf[4] >> 1; - - /* ........ ........ ....4444 4....... ........ */ - /* ........ ........ ........ .55555.. ........ */ - /* ........ ........ ........ ......66 666..... */ - dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; - - /* ........ ........ ........ ......66 666..... */ - /* ........ ........ ........ ........ ...77777 */ - dst[4] = buf[6] << 5 | buf[7]; - - dst += 5; - dst_sz -= 5; - } - /* Not ending on a eight byte boundary? */ - if (i > 0 && i < 8) { - - /* Enough space available at the destination? */ - if (dst_sz < (i + 1) / 2) - return -1; - - switch (i) { - case 7: /* ........ ........ ........ ......66 666..... */ - /* ........ ........ ........ .55555.. ........ */ - /* ........ ........ ....4444 4....... ........ */ - dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; - /* fallthrough */ - - case 5: /* ........ ........ ....4444 4....... ........ */ - /* ........ .......3 3333.... ........ ........ */ - dst[2] = buf[3] << 4 | buf[4] >> 1; - /* fallthrough */ - - case 4: /* ........ .......3 3333.... ........ ........ */ - /* ........ ..22222. ........ ........ ........ */ - /* .....111 11...... ........ ........ ........ */ - dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; - /* fallthrough */ - - case 2: /* .....111 11...... ........ ........ ........ */ - /* 00000... ........ ........ ........ ........ */ - dst[0] = buf[0] << 3 | buf[1] >> 2; - - break; - - default: - return -1; - } - dst += (i + 1) / 2; - - if (check_padding) { - /* Check remaining padding characters */ - if (ch != '=') - return -1; - - /* One down, 8 - i - 1 more to come... */ - for (i = 8 - i - 1; i > 0; i--) { - - do { - if (src_sz == 0) - return -1; - ch = *src++; - src_sz--; - - } while (isspace((unsigned char)ch)); - - if (ch != '=') - return -1; - } - } - } - return dst - start; -} - -int -sldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) -{ - return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 0, 1); -} - -int -sldns_b32_pton_extended_hex(const char* src, size_t src_sz, - uint8_t* dst, size_t dst_sz) -{ - return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 1, 1); -} - -size_t sldns_b64_ntop_calculate_size(size_t srcsize) -{ - return ((((srcsize + 2) / 3) * 4) + 1); -} - -/* RFC 1521, section 5.2. - * - * The encoding process represents 24-bit groups of input bits as output - * strings of 4 encoded characters. Proceeding from left to right, a - * 24-bit input group is formed by concatenating 3 8-bit input groups. - * These 24 bits are then treated as 4 concatenated 6-bit groups, each - * of which is translated into a single digit in the base64 alphabet. - * - * This routine does not insert spaces or linebreaks after 76 characters. - */ -static int sldns_b64_ntop_base(uint8_t const *src, size_t srclength, - char *target, size_t targsize, int base64url, int padding) -{ - char* b64; - const char pad64 = '='; - size_t i = 0, o = 0; - if(base64url) - b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" - "456789-_"; - else - b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" - "456789+/"; - if(targsize < sldns_b64_ntop_calculate_size(srclength)) - return -1; - /* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */ - while(i+3 <= srclength) { - if(o+4 > targsize) return -1; - target[o] = b64[src[i] >> 2]; - target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ]; - target[o+2] = b64[ ((src[i+1]&0x0f)<<2) | (src[i+2]>>6) ]; - target[o+3] = b64[ (src[i+2]&0x3f) ]; - i += 3; - o += 4; - } - /* remainder */ - switch(srclength - i) { - case 2: - /* two at end, converted into A B C = */ - target[o] = b64[src[i] >> 2]; - target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ]; - target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ]; - if(padding) { - target[o+3] = pad64; - /* i += 2; */ - o += 4; - } else { - o += 3; - } - break; - case 1: - /* one at end, converted into A B = = */ - target[o] = b64[src[i] >> 2]; - target[o+1] = b64[ ((src[i]&0x03)<<4) ]; - if(padding) { - target[o+2] = pad64; - target[o+3] = pad64; - /* i += 1; */ - o += 4; - } else { - o += 2; - } - break; - case 0: - default: - /* nothing */ - break; - } - /* assert: i == srclength */ - if(o+1 > targsize) return -1; - target[o] = 0; - return (int)o; -} - -int sldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, - size_t targsize) -{ - return sldns_b64_ntop_base(src, srclength, target, targsize, - 0 /* no base64url */, 1 /* padding */); -} - -int sldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target, - size_t targsize) -{ - return sldns_b64_ntop_base(src, srclength, target, targsize, - 1 /* base64url */, 0 /* no padding */); -} - -size_t sldns_b64_pton_calculate_size(size_t srcsize) -{ - return (((((srcsize + 3) / 4) * 3)) + 1); -} - -/* padding not required if srcsize is set */ -static int sldns_b64_pton_base(char const *src, size_t srcsize, uint8_t *target, - size_t targsize, int base64url) -{ - const uint8_t pad64 = 64; /* is 64th in the b64 array */ - const char* s = src; - uint8_t in[4]; - size_t o = 0, incount = 0; - int check_padding = (srcsize) ? 0 : 1; - - while(*s && (check_padding || srcsize)) { - /* skip any character that is not base64 */ - /* conceptually we do: - const char* b64 = pad'=' is appended to array - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - const char* d = strchr(b64, *s++); - and use d-b64; - */ - char d = *s++; - srcsize--; - if(d <= 'Z' && d >= 'A') - d -= 'A'; - else if(d <= 'z' && d >= 'a') - d = d - 'a' + 26; - else if(d <= '9' && d >= '0') - d = d - '0' + 52; - else if(!base64url && d == '+') - d = 62; - else if(base64url && d == '-') - d = 62; - else if(!base64url && d == '/') - d = 63; - else if(base64url && d == '_') - d = 63; - else if(d == '=') { - if(!check_padding) - continue; - d = 64; - } else continue; - - in[incount++] = (uint8_t)d; - /* work on block of 4, unless padding is not used and there are - * less than 4 chars left */ - if(incount != 4 && (check_padding || srcsize)) - continue; - assert(!check_padding || incount==4); - /* process whole block of 4 characters into 3 output bytes */ - if((incount == 2 || - (incount == 4 && in[3] == pad64 && in[2] == pad64))) { /* A B = = */ - if(o+1 > targsize) - return -1; - target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); - o += 1; - break; /* we are done */ - } else if(incount == 3 || - (incount == 4 && in[3] == pad64)) { /* A B C = */ - if(o+2 > targsize) - return -1; - target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); - target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2); - o += 2; - break; /* we are done */ - } else { - if(incount != 4 || o+3 > targsize) - return -1; - /* write xxxxxxyy yyyyzzzz zzwwwwww */ - target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); - target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2); - target[o+2]= ((in[2]&0x03)<<6) | in[3]; - o += 3; - } - incount = 0; - } - return (int)o; -} - -int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) -{ - return sldns_b64_pton_base(src, 0, target, targsize, 0); -} - -int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, - size_t targsize) -{ - if(!srcsize) { - return 0; - } - return sldns_b64_pton_base(src, srcsize, target, targsize, 1); -} - -int sldns_b64_contains_nonurl(char const *src, size_t srcsize) -{ - const char* s = src; - while(*s && srcsize) { - char d = *s++; - srcsize--; - /* the '+' and the '/' and padding '=' is not allowed in b64 - * url encoding */ - if(d == '+' || d == '/' || d == '=') { - return 1; - } - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/sldns/parseutil.h b/crates/libunbound-sys/unbound/sldns/parseutil.h deleted file mode 100644 index 683f34e2..00000000 --- a/crates/libunbound-sys/unbound/sldns/parseutil.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * parseutil.h - parse utilities for string and wire conversion - * - * (c) NLnet Labs, 2004 - * - * See the file LICENSE for the license - */ -/** - * \file - * - * Utility functions for parsing, base32(DNS variant) and base64 encoding - * and decoding, Hex, Time units, Escape codes. - */ - -#ifndef LDNS_PARSEUTIL_H -#define LDNS_PARSEUTIL_H -struct tm; - -/** - * A general purpose lookup table - * - * Lookup tables are arrays of (id, name) pairs, - * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", - * and vice versa. The lookup tables themselves are defined wherever needed, - * for instance in host2str.c - */ -struct sldns_struct_lookup_table { - int id; - const char *name; -}; -typedef struct sldns_struct_lookup_table sldns_lookup_table; - -/** - * Looks up the table entry by name, returns NULL if not found. - * \param[in] table the lookup table to search in - * \param[in] name what to search for - * \return the item found - */ -sldns_lookup_table *sldns_lookup_by_name(sldns_lookup_table table[], - const char *name); -/** - * Looks up the table entry by id, returns NULL if not found. - * \param[in] table the lookup table to search in - * \param[in] id what to search for - * \return the item found - */ -sldns_lookup_table *sldns_lookup_by_id(sldns_lookup_table table[], int id); - -/** - * Convert TM to seconds since epoch (midnight, January 1st, 1970). - * Like timegm(3), which is not always available. - * \param[in] tm a struct tm* with the date - * \return the seconds since epoch - */ -time_t sldns_mktime_from_utc(const struct tm *tm); - -/** - * The function interprets time as the number of seconds since epoch - * with respect to now using serial arithmetics (rfc1982). - * That number of seconds is then converted to broken-out time information. - * This is especially useful when converting the inception and expiration - * fields of RRSIG records. - * - * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) - * to be interpreted as a serial arithmetics number relative to now. - * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) - * to which the time value is compared to determine the final value. - * \param[out] result the struct with the broken-out time information - * \return result on success or NULL on error - */ -struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result); - -/** - * converts a ttl value (like 5d2h) to a long. - * \param[in] nptr the start of the string - * \param[out] endptr points to the last char in case of error - * \param[out] overflow returns if the string causes integer overflow error, - * the number is too big, string of digits too long. - * \return the convert duration value - */ -uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow); - -/** - * Returns the int value of the given (hex) digit - * \param[in] ch the hex char to convert - * \return the converted decimal value - */ -int sldns_hexdigit_to_int(char ch); - -/** - * calculates the size needed to store the result of b64_ntop - */ -size_t sldns_b64_ntop_calculate_size(size_t srcsize); - -int sldns_b64_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -int sldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target, - size_t targsize); - -/** - * calculates the size needed to store the result of sldns_b64_pton - */ -size_t sldns_b64_pton_calculate_size(size_t srcsize); -int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize); -int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, - size_t targsize); -int sldns_b64_contains_nonurl(char const *src, size_t srcsize); - -/** - * calculates the size needed to store the result of b32_ntop - */ -size_t sldns_b32_ntop_calculate_size(size_t src_data_length); - -size_t sldns_b32_ntop_calculate_size_no_padding(size_t src_data_length); - -int sldns_b32_ntop(const uint8_t* src_data, size_t src_data_length, - char* target_text_buffer, size_t target_text_buffer_size); - -int sldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, - char* target_text_buffer, size_t target_text_buffer_size); - -/** - * calculates the size needed to store the result of b32_pton - */ -size_t sldns_b32_pton_calculate_size(size_t src_text_length); - -int sldns_b32_pton(const char* src_text, size_t src_text_length, - uint8_t* target_data_buffer, size_t target_data_buffer_size); - -int sldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length, - uint8_t* target_data_buffer, size_t target_data_buffer_size); - -/* - * Checks whether the escaped value at **s is an octal value or - * a 'normally' escaped character (and not eos) - * - * @param ch_p: the parsed character - * @param str_p: the string. moved along for characters read. - * The string pointer at *s is increased by either 0 (on error), 1 (on - * normal escapes), or 3 (on octals) - * - * @return 0 on error - */ -int sldns_parse_escape(uint8_t *ch_p, const char** str_p); - -/** - * Parse one character, with escape codes, - * @param ch_p: the parsed character - * @param str_p: the string. moved along for characters read. - * @return 0 on error - */ -int sldns_parse_char(uint8_t *ch_p, const char** str_p); - -#endif /* LDNS_PARSEUTIL_H */ diff --git a/crates/libunbound-sys/unbound/sldns/pkthdr.h b/crates/libunbound-sys/unbound/sldns/pkthdr.h deleted file mode 100644 index c32e7d28..00000000 --- a/crates/libunbound-sys/unbound/sldns/pkthdr.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * pkthdr.h - packet header from wire conversion routines - * - * a Net::DNS like library for C - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -/** - * \file - * - * Contains functions that translate dns data from the wire format (as sent - * by servers and clients) to the internal structures for the packet header. - */ - -#ifndef LDNS_PKTHDR_H -#define LDNS_PKTHDR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* The length of the header */ -#define LDNS_HEADER_SIZE 12 - -/* First octet of flags */ -#define LDNS_RD_MASK 0x01U -#define LDNS_RD_SHIFT 0 -#define LDNS_RD_WIRE(wirebuf) (*(wirebuf+2) & LDNS_RD_MASK) -#define LDNS_RD_SET(wirebuf) (*(wirebuf+2) |= LDNS_RD_MASK) -#define LDNS_RD_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_RD_MASK) - -#define LDNS_TC_MASK 0x02U -#define LDNS_TC_SHIFT 1 -#define LDNS_TC_WIRE(wirebuf) (*(wirebuf+2) & LDNS_TC_MASK) -#define LDNS_TC_SET(wirebuf) (*(wirebuf+2) |= LDNS_TC_MASK) -#define LDNS_TC_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_TC_MASK) - -#define LDNS_AA_MASK 0x04U -#define LDNS_AA_SHIFT 2 -#define LDNS_AA_WIRE(wirebuf) (*(wirebuf+2) & LDNS_AA_MASK) -#define LDNS_AA_SET(wirebuf) (*(wirebuf+2) |= LDNS_AA_MASK) -#define LDNS_AA_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_AA_MASK) - -#define LDNS_OPCODE_MASK 0x78U -#define LDNS_OPCODE_SHIFT 3 -#define LDNS_OPCODE_WIRE(wirebuf) ((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT) -#define LDNS_OPCODE_SET(wirebuf, opcode) \ - (*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT)) - -#define LDNS_QR_MASK 0x80U -#define LDNS_QR_SHIFT 7 -#define LDNS_QR_WIRE(wirebuf) (*(wirebuf+2) & LDNS_QR_MASK) -#define LDNS_QR_SET(wirebuf) (*(wirebuf+2) |= LDNS_QR_MASK) -#define LDNS_QR_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_QR_MASK) - -/* Second octet of flags */ -#define LDNS_RCODE_MASK 0x0fU -#define LDNS_RCODE_SHIFT 0 -#define LDNS_RCODE_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RCODE_MASK) -#define LDNS_RCODE_SET(wirebuf, rcode) \ - (*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode)) - -#define LDNS_CD_MASK 0x10U -#define LDNS_CD_SHIFT 4 -#define LDNS_CD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_CD_MASK) -#define LDNS_CD_SET(wirebuf) (*(wirebuf+3) |= LDNS_CD_MASK) -#define LDNS_CD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_CD_MASK) - -#define LDNS_AD_MASK 0x20U -#define LDNS_AD_SHIFT 5 -#define LDNS_AD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_AD_MASK) -#define LDNS_AD_SET(wirebuf) (*(wirebuf+3) |= LDNS_AD_MASK) -#define LDNS_AD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_AD_MASK) - -#define LDNS_Z_MASK 0x40U -#define LDNS_Z_SHIFT 6 -#define LDNS_Z_WIRE(wirebuf) (*(wirebuf+3) & LDNS_Z_MASK) -#define LDNS_Z_SET(wirebuf) (*(wirebuf+3) |= LDNS_Z_MASK) -#define LDNS_Z_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_Z_MASK) - -#define LDNS_RA_MASK 0x80U -#define LDNS_RA_SHIFT 7 -#define LDNS_RA_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RA_MASK) -#define LDNS_RA_SET(wirebuf) (*(wirebuf+3) |= LDNS_RA_MASK) -#define LDNS_RA_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_RA_MASK) - -/* Query ID */ -#define LDNS_ID_WIRE(wirebuf) (sldns_read_uint16(wirebuf)) -#define LDNS_ID_SET(wirebuf, id) (sldns_write_uint16(wirebuf, id)) - -/* Counter of the question section */ -#define LDNS_QDCOUNT_OFF 4 -/* -#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) -*/ -#define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) -#define LDNS_QDCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_QDCOUNT_OFF, i)) - -/* Counter of the answer section */ -#define LDNS_ANCOUNT_OFF 6 -#define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) -#define LDNS_ANCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ANCOUNT_OFF, i)) - -/* Counter of the authority section */ -#define LDNS_NSCOUNT_OFF 8 -#define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) -#define LDNS_NSCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_NSCOUNT_OFF, i)) - -/* Counter of the additional section */ -#define LDNS_ARCOUNT_OFF 10 -#define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) -#define LDNS_ARCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ARCOUNT_OFF, i)) - -/** - * The sections of a packet - */ -enum sldns_enum_pkt_section { - LDNS_SECTION_QUESTION = 0, - LDNS_SECTION_ANSWER = 1, - LDNS_SECTION_AUTHORITY = 2, - LDNS_SECTION_ADDITIONAL = 3, - /** bogus section, if not interested */ - LDNS_SECTION_ANY = 4, - /** used to get all non-question rrs from a packet */ - LDNS_SECTION_ANY_NOQUESTION = 5 -}; -typedef enum sldns_enum_pkt_section sldns_pkt_section; - -/* opcodes for pkt's */ -enum sldns_enum_pkt_opcode { - LDNS_PACKET_QUERY = 0, - LDNS_PACKET_IQUERY = 1, - LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */ - LDNS_PACKET_NOTIFY = 4, - LDNS_PACKET_UPDATE = 5 -}; -typedef enum sldns_enum_pkt_opcode sldns_pkt_opcode; - -/* rcodes for pkts */ -enum sldns_enum_pkt_rcode { - LDNS_RCODE_NOERROR = 0, - LDNS_RCODE_FORMERR = 1, - LDNS_RCODE_SERVFAIL = 2, - LDNS_RCODE_NXDOMAIN = 3, - LDNS_RCODE_NOTIMPL = 4, - LDNS_RCODE_REFUSED = 5, - LDNS_RCODE_YXDOMAIN = 6, - LDNS_RCODE_YXRRSET = 7, - LDNS_RCODE_NXRRSET = 8, - LDNS_RCODE_NOTAUTH = 9, - LDNS_RCODE_NOTZONE = 10 -}; -typedef enum sldns_enum_pkt_rcode sldns_pkt_rcode; - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_PKTHDR_H */ diff --git a/crates/libunbound-sys/unbound/sldns/rrdef.c b/crates/libunbound-sys/unbound/sldns/rrdef.c deleted file mode 100644 index e81ebb1f..00000000 --- a/crates/libunbound-sys/unbound/sldns/rrdef.c +++ /dev/null @@ -1,760 +0,0 @@ -/* rrdef.c - * - * access functions to rr definitions list. - * a Net::DNS like library for C - * LibDNS Team @ NLnet Labs - * - * (c) NLnet Labs, 2004-2006 - * See the file LICENSE for the license - */ -/** - * \file - * - * Defines resource record types and constants. - */ -#include "config.h" -#include "sldns/rrdef.h" -#include "sldns/parseutil.h" - -/* classes */ -static sldns_lookup_table sldns_rr_classes_data[] = { - { LDNS_RR_CLASS_IN, "IN" }, - { LDNS_RR_CLASS_CH, "CH" }, - { LDNS_RR_CLASS_HS, "HS" }, - { LDNS_RR_CLASS_NONE, "NONE" }, - { LDNS_RR_CLASS_ANY, "ANY" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_rr_classes = sldns_rr_classes_data; - -/* types */ -static const sldns_rdf_type type_0_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN }; -static const sldns_rdf_type type_a_wireformat[] = { LDNS_RDF_TYPE_A }; -static const sldns_rdf_type type_ns_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_md_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_mf_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_cname_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_soa_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_INT32, - LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, - LDNS_RDF_TYPE_PERIOD -}; -static const sldns_rdf_type type_mb_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_mg_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_mr_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_wks_wireformat[] = { - LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_WKS -}; -static const sldns_rdf_type type_ptr_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_hinfo_wireformat[] = { - LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR -}; -static const sldns_rdf_type type_minfo_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_mx_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_rp_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_afsdb_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_x25_wireformat[] = { LDNS_RDF_TYPE_STR }; -static const sldns_rdf_type type_isdn_wireformat[] = { - LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR -}; -static const sldns_rdf_type type_rt_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_nsap_wireformat[] = { - LDNS_RDF_TYPE_NSAP -}; -static const sldns_rdf_type type_nsap_ptr_wireformat[] = { - LDNS_RDF_TYPE_STR -}; -static const sldns_rdf_type type_sig_wireformat[] = { - LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32, - LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_key_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_px_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_gpos_wireformat[] = { - LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR -}; -static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA }; -static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC }; -static const sldns_rdf_type type_nxt_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_UNKNOWN -}; -static const sldns_rdf_type type_eid_wireformat[] = { - LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_nimloc_wireformat[] = { - LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_srv_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_atma_wireformat[] = { - LDNS_RDF_TYPE_ATMA -}; -static const sldns_rdf_type type_naptr_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_kx_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_cert_wireformat[] = { - LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_a6_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN }; -static const sldns_rdf_type type_dname_wireformat[] = { LDNS_RDF_TYPE_DNAME }; -static const sldns_rdf_type type_sink_wireformat[] = { LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_apl_wireformat[] = { - LDNS_RDF_TYPE_APL -}; -static const sldns_rdf_type type_ds_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_sshfp_wireformat[] = { - LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_ipseckey_wireformat[] = { - LDNS_RDF_TYPE_IPSECKEY -}; -static const sldns_rdf_type type_rrsig_wireformat[] = { - LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32, - LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_nsec_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_NSEC -}; -static const sldns_rdf_type type_dhcid_wireformat[] = { - LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_talink_wireformat[] = { - LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_openpgpkey_wireformat[] = { - LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_csync_wireformat[] = { - LDNS_RDF_TYPE_INT32, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC -}; -static const sldns_rdf_type type_zonemd_wireformat[] = { - LDNS_RDF_TYPE_INT32, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_svcb_wireformat[] = { - LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME -}; -/* nsec3 is some vars, followed by same type of data of nsec */ -static const sldns_rdf_type type_nsec3_wireformat[] = { -/* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ - LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC3_SALT, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC -}; - -static const sldns_rdf_type type_nsec3param_wireformat[] = { -/* LDNS_RDF_TYPE_NSEC3_PARAMS_VARS*/ - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_NSEC3_SALT -}; - -static const sldns_rdf_type type_dnskey_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_ALG, - LDNS_RDF_TYPE_B64 -}; -static const sldns_rdf_type type_tkey_wireformat[] = { - LDNS_RDF_TYPE_DNAME, - LDNS_RDF_TYPE_TIME, - LDNS_RDF_TYPE_TIME, - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_TSIGERROR, - LDNS_RDF_TYPE_INT16_DATA, - LDNS_RDF_TYPE_INT16_DATA, -}; -static const sldns_rdf_type type_tsig_wireformat[] = { - LDNS_RDF_TYPE_DNAME, - LDNS_RDF_TYPE_TSIGTIME, - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_INT16_DATA, - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_TSIGERROR, - LDNS_RDF_TYPE_INT16_DATA -}; -static const sldns_rdf_type type_tlsa_wireformat[] = { - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_HEX -}; -static const sldns_rdf_type type_hip_wireformat[] = { - LDNS_RDF_TYPE_HIP -}; -static const sldns_rdf_type type_nid_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_ILNP64 -}; -static const sldns_rdf_type type_l32_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_A -}; -static const sldns_rdf_type type_l64_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_ILNP64 -}; -static const sldns_rdf_type type_lp_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_DNAME -}; -static const sldns_rdf_type type_eui48_wireformat[] = { - LDNS_RDF_TYPE_EUI48 -}; -static const sldns_rdf_type type_eui64_wireformat[] = { - LDNS_RDF_TYPE_EUI64 -}; -static const sldns_rdf_type type_uri_wireformat[] = { - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_INT16, - LDNS_RDF_TYPE_LONG_STR -}; -static const sldns_rdf_type type_caa_wireformat[] = { - LDNS_RDF_TYPE_INT8, - LDNS_RDF_TYPE_TAG, - LDNS_RDF_TYPE_LONG_STR -}; - -/* All RR's defined in 1035 are well known and can thus - * be compressed. See RFC3597. These RR's are: - * CNAME HINFO MB MD MF MG MINFO MR MX NULL NS PTR SOA TXT - */ -static sldns_rr_descriptor rdata_field_descriptors[] = { - /* 0 */ - {(enum sldns_enum_rr_type)0, NULL, 0, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 1 */ - {LDNS_RR_TYPE_A, "A", 1, 1, type_a_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 2 */ - {LDNS_RR_TYPE_NS, "NS", 1, 1, type_ns_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 3 */ - {LDNS_RR_TYPE_MD, "MD", 1, 1, type_md_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 4 */ - {LDNS_RR_TYPE_MF, "MF", 1, 1, type_mf_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 5 */ - {LDNS_RR_TYPE_CNAME, "CNAME", 1, 1, type_cname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 6 */ - {LDNS_RR_TYPE_SOA, "SOA", 7, 7, type_soa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 }, - /* 7 */ - {LDNS_RR_TYPE_MB, "MB", 1, 1, type_mb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 8 */ - {LDNS_RR_TYPE_MG, "MG", 1, 1, type_mg_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 9 */ - {LDNS_RR_TYPE_MR, "MR", 1, 1, type_mr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 10 */ - {LDNS_RR_TYPE_NULL, "NULL", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 11 */ - {LDNS_RR_TYPE_WKS, "WKS", 2, 2, type_wks_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 12 */ - {LDNS_RR_TYPE_PTR, "PTR", 1, 1, type_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 13 */ - {LDNS_RR_TYPE_HINFO, "HINFO", 2, 2, type_hinfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 14 */ - {LDNS_RR_TYPE_MINFO, "MINFO", 2, 2, type_minfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 }, - /* 15 */ - {LDNS_RR_TYPE_MX, "MX", 2, 2, type_mx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, - /* 16 */ - {LDNS_RR_TYPE_TXT, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, - /* 17 */ - {LDNS_RR_TYPE_RP, "RP", 2, 2, type_rp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, - /* 18 */ - {LDNS_RR_TYPE_AFSDB, "AFSDB", 2, 2, type_afsdb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 19 */ - {LDNS_RR_TYPE_X25, "X25", 1, 1, type_x25_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 20 */ - {LDNS_RR_TYPE_ISDN, "ISDN", 1, 2, type_isdn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 21 */ - {LDNS_RR_TYPE_RT, "RT", 2, 2, type_rt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 22 */ - {LDNS_RR_TYPE_NSAP, "NSAP", 1, 1, type_nsap_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 23 */ - {LDNS_RR_TYPE_NSAP_PTR, "NSAP-PTR", 1, 1, type_nsap_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 24 */ - {LDNS_RR_TYPE_SIG, "SIG", 9, 9, type_sig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 25 */ - {LDNS_RR_TYPE_KEY, "KEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 26 */ - {LDNS_RR_TYPE_PX, "PX", 3, 3, type_px_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, - /* 27 */ - {LDNS_RR_TYPE_GPOS, "GPOS", 3, 3, type_gpos_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 28 */ - {LDNS_RR_TYPE_AAAA, "AAAA", 1, 1, type_aaaa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 29 */ - {LDNS_RR_TYPE_LOC, "LOC", 1, 1, type_loc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 30 */ - {LDNS_RR_TYPE_NXT, "NXT", 2, 2, type_nxt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 31 */ - {LDNS_RR_TYPE_EID, "EID", 1, 1, type_eid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 32 */ - {LDNS_RR_TYPE_NIMLOC, "NIMLOC", 1, 1, type_nimloc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 33 */ - {LDNS_RR_TYPE_SRV, "SRV", 4, 4, type_srv_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 34 */ - {LDNS_RR_TYPE_ATMA, "ATMA", 1, 1, type_atma_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 35 */ - {LDNS_RR_TYPE_NAPTR, "NAPTR", 6, 6, type_naptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 36 */ - {LDNS_RR_TYPE_KX, "KX", 2, 2, type_kx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 37 */ - {LDNS_RR_TYPE_CERT, "CERT", 4, 4, type_cert_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 38 */ - {LDNS_RR_TYPE_A6, "A6", 1, 1, type_a6_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 39 */ - {LDNS_RR_TYPE_DNAME, "DNAME", 1, 1, type_dname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 40 */ - {LDNS_RR_TYPE_SINK, "SINK", 1, 1, type_sink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 41 */ - {LDNS_RR_TYPE_OPT, "OPT", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 42 */ - {LDNS_RR_TYPE_APL, "APL", 0, 0, type_apl_wireformat, LDNS_RDF_TYPE_APL, LDNS_RR_NO_COMPRESS, 0 }, - /* 43 */ - {LDNS_RR_TYPE_DS, "DS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 44 */ - {LDNS_RR_TYPE_SSHFP, "SSHFP", 3, 3, type_sshfp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 45 */ - {LDNS_RR_TYPE_IPSECKEY, "IPSECKEY", 1, 1, type_ipseckey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 46 */ - {LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 47 */ - {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* 48 */ - {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 49 */ - {LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 50 */ - {LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 51 */ - {LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 52 */ - {LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 53 */ - {LDNS_RR_TYPE_SMIMEA, "SMIMEA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 54 */ -{(enum sldns_enum_rr_type)0, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 55 - * Hip ends with 0 or more Rendezvous Servers represented as dname's. - * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field - * set to 0. - */ - {LDNS_RR_TYPE_HIP, "HIP", 1, 1, type_hip_wireformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 }, - -#ifdef DRAFT_RRTYPES - /* 56 */ - {LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, - /* 57 */ - {LDNS_RR_TYPE_RKEY, "RKEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#else -{(enum sldns_enum_rr_type)0, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#endif - /* 58 */ - {LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, - - /* 59 */ - {LDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 60 */ - {LDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 61 */ -{LDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 62 */ - {LDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 63 */ - {LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 64 */ - {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 }, - /* 65 */ - {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 }, -{(enum sldns_enum_rr_type)0, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE70", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE71", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE72", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE73", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE74", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE75", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE76", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE77", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE78", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE79", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE80", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE81", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE82", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE83", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE84", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE85", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE86", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE87", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE88", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE89", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE90", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE91", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE92", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE93", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE94", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE95", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - - /* 99 */ - {LDNS_RR_TYPE_SPF, "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, - - /* UINFO [IANA-Reserved] */ -{(enum sldns_enum_rr_type)0, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* UID [IANA-Reserved] */ -{(enum sldns_enum_rr_type)0, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* GID [IANA-Reserved] */ -{(enum sldns_enum_rr_type)0, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* UNSPEC [IANA-Reserved] */ -{(enum sldns_enum_rr_type)0, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - - /* 104 */ - {LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 105 */ - {LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 106 */ - {LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 107 */ - {LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - - /* 108 */ - {LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 109 */ - {LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - -{(enum sldns_enum_rr_type)0, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE113", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE114", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE115", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE116", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE117", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE118", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE119", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE120", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE121", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE122", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE123", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE124", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE125", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE126", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE127", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE128", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE129", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE130", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE131", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE132", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE133", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE134", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE135", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE136", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE137", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE138", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE139", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE140", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE141", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE142", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE143", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE144", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE145", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE146", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE147", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE148", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE149", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE150", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE151", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE152", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE153", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE154", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE155", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE156", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE157", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE158", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE159", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE160", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE161", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE162", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE163", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE164", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE165", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE166", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE167", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE168", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE169", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE170", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE171", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE172", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE173", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE174", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE175", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE176", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE177", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE178", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE179", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE180", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE181", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE182", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE183", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE184", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE185", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE186", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE187", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE188", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE189", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE190", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE191", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE192", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE193", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE194", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE195", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE196", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE197", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE198", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE199", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE200", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE201", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE202", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE203", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE204", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE205", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE206", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE207", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE208", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE209", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE210", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE211", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE212", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE213", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE214", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE215", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE216", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE217", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE218", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE219", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE220", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE221", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE222", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE223", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE224", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE225", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE226", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE227", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE228", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE229", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE230", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE231", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE232", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE233", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE234", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE235", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE236", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE237", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE238", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE239", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE240", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE241", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE242", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE243", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE244", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE245", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE246", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE247", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE248", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - - /* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one. - * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9. - */ - /* 249 */ - {LDNS_RR_TYPE_TKEY, "TKEY", 7, 7, type_tkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - /* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one. - * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9. - */ - /* 250 */ - {LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, - - /* IXFR: A request for a transfer of an incremental zone transfer */ -{LDNS_RR_TYPE_IXFR, "IXFR", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* AXFR: A request for a transfer of an entire zone */ -{LDNS_RR_TYPE_AXFR, "AXFR", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* MAILB: A request for mailbox-related records (MB, MG or MR) */ -{LDNS_RR_TYPE_MAILB, "MAILB", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* MAILA: A request for mail agent RRs (Obsolete - see MX) */ -{LDNS_RR_TYPE_MAILA, "MAILA", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* ANY: A request for all (available) records */ -{LDNS_RR_TYPE_ANY, "ANY", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - - /* 256 */ - {LDNS_RR_TYPE_URI, "URI", 3, 3, type_uri_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, - /* 257 */ - {LDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#ifdef DRAFT_RRTYPES - /* 258 */ - {LDNS_RR_TYPE_AVC, "AVC", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, -#else -{(enum sldns_enum_rr_type)0, "TYPE258", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#endif - -/* split in array, no longer contiguous */ - -#ifdef DRAFT_RRTYPES - /* 32768 */ - {LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#else -{(enum sldns_enum_rr_type)0, "TYPE32768", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#endif - /* 32769 */ - {LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 } -}; - -/** - * \def LDNS_RDATA_FIELD_DESCRIPTORS_COUNT - * computes the number of rdata fields - */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \ - (sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0])) - -const sldns_rr_descriptor * -sldns_rr_descript(uint16_t type) -{ - size_t i; - if (type < LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) { - return &rdata_field_descriptors[type]; - } else { - /* because not all array index equals type code */ - for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON; - i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; - i++) { - if (rdata_field_descriptors[i]._type == type) { - return &rdata_field_descriptors[i]; - } - } - return &rdata_field_descriptors[0]; - } -} - -size_t -sldns_rr_descriptor_minimum(const sldns_rr_descriptor *descriptor) -{ - if (descriptor) { - return descriptor->_minimum; - } else { - return 0; - } -} - -size_t -sldns_rr_descriptor_maximum(const sldns_rr_descriptor *descriptor) -{ - if (descriptor) { - if (descriptor->_variable != LDNS_RDF_TYPE_NONE) { - return 65535; /* cannot be more than 64k */ - } else { - return descriptor->_maximum; - } - } else { - return 0; - } -} - -sldns_rdf_type -sldns_rr_descriptor_field_type(const sldns_rr_descriptor *descriptor, - size_t index) -{ - assert(descriptor != NULL); - assert(index < descriptor->_maximum - || descriptor->_variable != LDNS_RDF_TYPE_NONE); - if (index < descriptor->_maximum) { - return descriptor->_wireformat[index]; - } else { - return descriptor->_variable; - } -} - -sldns_rr_type -sldns_get_rr_type_by_name(const char *name) -{ - unsigned int i; - const char *desc_name; - const sldns_rr_descriptor *desc; - - /* TYPEXX representation */ - if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) { - unsigned int a = atoi(name + 4); - if (a > LDNS_RR_TYPE_LAST) { - return (enum sldns_enum_rr_type)0; - } - return a; - } - - /* Normal types */ - for (i = 0; i < (unsigned int) LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; i++) { - desc = &rdata_field_descriptors[i]; - desc_name = desc->_name; - if(desc_name && - strlen(name) == strlen(desc_name) && - strncasecmp(name, desc_name, strlen(desc_name)) == 0) { - /* because not all array index equals type code */ - return desc->_type; - } - } - - /* special cases for query types */ - if (strlen(name) == 4 && strncasecmp(name, "IXFR", 4) == 0) { - return LDNS_RR_TYPE_IXFR; - } else if (strlen(name) == 4 && strncasecmp(name, "AXFR", 4) == 0) { - return LDNS_RR_TYPE_AXFR; - } else if (strlen(name) == 5 && strncasecmp(name, "MAILB", 5) == 0) { - return LDNS_RR_TYPE_MAILB; - } else if (strlen(name) == 5 && strncasecmp(name, "MAILA", 5) == 0) { - return LDNS_RR_TYPE_MAILA; - } else if (strlen(name) == 3 && strncasecmp(name, "ANY", 3) == 0) { - return LDNS_RR_TYPE_ANY; - } - - return (enum sldns_enum_rr_type)0; -} - -sldns_rr_class -sldns_get_rr_class_by_name(const char *name) -{ - sldns_lookup_table *lt; - - /* CLASSXX representation */ - if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) { - unsigned int a = atoi(name + 5); - if (a > LDNS_RR_CLASS_LAST) { - return (enum sldns_enum_rr_class)0; - } - return a; - } - - /* Normal types */ - lt = sldns_lookup_by_name(sldns_rr_classes, name); - if (lt) { - return lt->id; - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/sldns/rrdef.h b/crates/libunbound-sys/unbound/sldns/rrdef.h deleted file mode 100644 index f277fd67..00000000 --- a/crates/libunbound-sys/unbound/sldns/rrdef.h +++ /dev/null @@ -1,567 +0,0 @@ -/* - * rrdef.h - * - * RR definitions - * - * a Net::DNS like library for C - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -/** - * \file - * - * Defines resource record types and constants. - */ - -#ifndef LDNS_RRDEF_H -#define LDNS_RRDEF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** Maximum length of a dname label */ -#define LDNS_MAX_LABELLEN 63 -/** Maximum length of a complete dname */ -#define LDNS_MAX_DOMAINLEN 255 -/** Maximum number of pointers in 1 dname */ -#define LDNS_MAX_POINTERS 65535 -/** The bytes TTL, CLASS and length use up in an rr */ -#define LDNS_RR_OVERHEAD 10 - -#define LDNS_DNSSEC_KEYPROTO 3 -#define LDNS_KEY_ZONE_KEY 0x0100 /* set for ZSK&KSK, rfc 4034 */ -#define LDNS_KEY_SEP_KEY 0x0001 /* set for KSK, rfc 4034 */ -#define LDNS_KEY_REVOKE_KEY 0x0080 /* used to revoke KSK, rfc 5011 */ - -/* The first fields are contiguous and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 259 - -/** lookuptable for rr classes */ -extern struct sldns_struct_lookup_table* sldns_rr_classes; - -/** - * The different RR classes. - */ -enum sldns_enum_rr_class -{ - /** the Internet */ - LDNS_RR_CLASS_IN = 1, - /** Chaos class */ - LDNS_RR_CLASS_CH = 3, - /** Hesiod (Dyer 87) */ - LDNS_RR_CLASS_HS = 4, - /** None class, dynamic update */ - LDNS_RR_CLASS_NONE = 254, - /** Any class */ - LDNS_RR_CLASS_ANY = 255, - - LDNS_RR_CLASS_FIRST = 0, - LDNS_RR_CLASS_LAST = 65535, - LDNS_RR_CLASS_COUNT = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1 -}; -typedef enum sldns_enum_rr_class sldns_rr_class; - -/** - * Used to specify whether compression is allowed. - */ -enum sldns_enum_rr_compress -{ - /** compression is allowed */ - LDNS_RR_COMPRESS, - LDNS_RR_NO_COMPRESS -}; -typedef enum sldns_enum_rr_compress sldns_rr_compress; - -/** - * The different RR types. - */ -enum sldns_enum_rr_type -{ - /** a host address */ - LDNS_RR_TYPE_A = 1, - /** an authoritative name server */ - LDNS_RR_TYPE_NS = 2, - /** a mail destination (Obsolete - use MX) */ - LDNS_RR_TYPE_MD = 3, - /** a mail forwarder (Obsolete - use MX) */ - LDNS_RR_TYPE_MF = 4, - /** the canonical name for an alias */ - LDNS_RR_TYPE_CNAME = 5, - /** marks the start of a zone of authority */ - LDNS_RR_TYPE_SOA = 6, - /** a mailbox domain name (EXPERIMENTAL) */ - LDNS_RR_TYPE_MB = 7, - /** a mail group member (EXPERIMENTAL) */ - LDNS_RR_TYPE_MG = 8, - /** a mail rename domain name (EXPERIMENTAL) */ - LDNS_RR_TYPE_MR = 9, - /** a null RR (EXPERIMENTAL) */ - LDNS_RR_TYPE_NULL = 10, - /** a well known service description */ - LDNS_RR_TYPE_WKS = 11, - /** a domain name pointer */ - LDNS_RR_TYPE_PTR = 12, - /** host information */ - LDNS_RR_TYPE_HINFO = 13, - /** mailbox or mail list information */ - LDNS_RR_TYPE_MINFO = 14, - /** mail exchange */ - LDNS_RR_TYPE_MX = 15, - /** text strings */ - LDNS_RR_TYPE_TXT = 16, - /** RFC1183 */ - LDNS_RR_TYPE_RP = 17, - /** RFC1183 */ - LDNS_RR_TYPE_AFSDB = 18, - /** RFC1183 */ - LDNS_RR_TYPE_X25 = 19, - /** RFC1183 */ - LDNS_RR_TYPE_ISDN = 20, - /** RFC1183 */ - LDNS_RR_TYPE_RT = 21, - /** RFC1706 */ - LDNS_RR_TYPE_NSAP = 22, - /** RFC1348 */ - LDNS_RR_TYPE_NSAP_PTR = 23, - /** 2535typecode */ - LDNS_RR_TYPE_SIG = 24, - /** 2535typecode */ - LDNS_RR_TYPE_KEY = 25, - /** RFC2163 */ - LDNS_RR_TYPE_PX = 26, - /** RFC1712 */ - LDNS_RR_TYPE_GPOS = 27, - /** ipv6 address */ - LDNS_RR_TYPE_AAAA = 28, - /** LOC record RFC1876 */ - LDNS_RR_TYPE_LOC = 29, - /** 2535typecode */ - LDNS_RR_TYPE_NXT = 30, - /** draft-ietf-nimrod-dns-01.txt */ - LDNS_RR_TYPE_EID = 31, - /** draft-ietf-nimrod-dns-01.txt */ - LDNS_RR_TYPE_NIMLOC = 32, - /** SRV record RFC2782 */ - LDNS_RR_TYPE_SRV = 33, - /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */ - LDNS_RR_TYPE_ATMA = 34, - /** RFC2915 */ - LDNS_RR_TYPE_NAPTR = 35, - /** RFC2230 */ - LDNS_RR_TYPE_KX = 36, - /** RFC2538 */ - LDNS_RR_TYPE_CERT = 37, - /** RFC2874 */ - LDNS_RR_TYPE_A6 = 38, - /** RFC2672 */ - LDNS_RR_TYPE_DNAME = 39, - /** dnsind-kitchen-sink-02.txt */ - LDNS_RR_TYPE_SINK = 40, - /** Pseudo OPT record... */ - LDNS_RR_TYPE_OPT = 41, - /** RFC3123 */ - LDNS_RR_TYPE_APL = 42, - /** RFC4034, RFC3658 */ - LDNS_RR_TYPE_DS = 43, - /** SSH Key Fingerprint */ - LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */ - /** IPsec Key */ - LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */ - /** DNSSEC */ - LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */ - LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */ - LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */ - - LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */ - /* NSEC3 */ - LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */ - LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ - LDNS_RR_TYPE_NSEC3PARAMS = 51, - LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */ - LDNS_RR_TYPE_SMIMEA = 53, /* RFC 8162 */ - LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */ - - /** draft-reid-dnsext-zs */ - LDNS_RR_TYPE_NINFO = 56, - /** draft-reid-dnsext-rkey */ - LDNS_RR_TYPE_RKEY = 57, - /** draft-ietf-dnsop-trust-history */ - LDNS_RR_TYPE_TALINK = 58, - LDNS_RR_TYPE_CDS = 59, /** RFC 7344 */ - LDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ - LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ - LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ - LDNS_RR_TYPE_ZONEMD = 63, /* draft-ietf-dnsop-dns-zone-digest-12 */ - LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */ - LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */ - - LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ - - LDNS_RR_TYPE_UINFO = 100, - LDNS_RR_TYPE_UID = 101, - LDNS_RR_TYPE_GID = 102, - LDNS_RR_TYPE_UNSPEC = 103, - - LDNS_RR_TYPE_NID = 104, /* RFC 6742 */ - LDNS_RR_TYPE_L32 = 105, /* RFC 6742 */ - LDNS_RR_TYPE_L64 = 106, /* RFC 6742 */ - LDNS_RR_TYPE_LP = 107, /* RFC 6742 */ - - /** draft-jabley-dnsext-eui48-eui64-rrtypes */ - LDNS_RR_TYPE_EUI48 = 108, - LDNS_RR_TYPE_EUI64 = 109, - - LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */ - LDNS_RR_TYPE_TSIG = 250, - LDNS_RR_TYPE_IXFR = 251, - LDNS_RR_TYPE_AXFR = 252, - /** A request for mailbox-related records (MB, MG or MR) */ - LDNS_RR_TYPE_MAILB = 253, - /** A request for mail agent RRs (Obsolete - see MX) */ - LDNS_RR_TYPE_MAILA = 254, - /** any type (wildcard) */ - LDNS_RR_TYPE_ANY = 255, - LDNS_RR_TYPE_URI = 256, /* RFC 7553 */ - LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */ - LDNS_RR_TYPE_AVC = 258, - - /** DNSSEC Trust Authorities */ - LDNS_RR_TYPE_TA = 32768, - /* RFC 4431, 5074, DNSSEC Lookaside Validation */ - LDNS_RR_TYPE_DLV = 32769, - - /* type codes from nsec3 experimental phase - LDNS_RR_TYPE_NSEC3 = 65324, - LDNS_RR_TYPE_NSEC3PARAMS = 65325, */ - LDNS_RR_TYPE_FIRST = 0, - LDNS_RR_TYPE_LAST = 65535, - LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1 -}; -typedef enum sldns_enum_rr_type sldns_rr_type; - -/* RDATA */ -#define LDNS_MAX_RDFLEN 65535 - -#define LDNS_RDF_SIZE_BYTE 1 -#define LDNS_RDF_SIZE_WORD 2 -#define LDNS_RDF_SIZE_DOUBLEWORD 4 -#define LDNS_RDF_SIZE_6BYTES 6 -#define LDNS_RDF_SIZE_8BYTES 8 -#define LDNS_RDF_SIZE_16BYTES 16 - -#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01 - -#define LDNS_APL_IP4 1 -#define LDNS_APL_IP6 2 -#define LDNS_APL_MASK 0x7f -#define LDNS_APL_NEGATION 0x80 - -/** - * The different types of RDATA fields. - */ -enum sldns_enum_rdf_type -{ - /** none */ - LDNS_RDF_TYPE_NONE, - /** domain name */ - LDNS_RDF_TYPE_DNAME, - /** 8 bits */ - LDNS_RDF_TYPE_INT8, - /** 16 bits */ - LDNS_RDF_TYPE_INT16, - /** 32 bits */ - LDNS_RDF_TYPE_INT32, - /** A record */ - LDNS_RDF_TYPE_A, - /** AAAA record */ - LDNS_RDF_TYPE_AAAA, - /** txt string */ - LDNS_RDF_TYPE_STR, - /** apl data */ - LDNS_RDF_TYPE_APL, - /** b32 string */ - LDNS_RDF_TYPE_B32_EXT, - /** b64 string */ - LDNS_RDF_TYPE_B64, - /** hex string */ - LDNS_RDF_TYPE_HEX, - /** nsec type codes */ - LDNS_RDF_TYPE_NSEC, - /** a RR type */ - LDNS_RDF_TYPE_TYPE, - /** a class */ - LDNS_RDF_TYPE_CLASS, - /** certificate algorithm */ - LDNS_RDF_TYPE_CERT_ALG, - /** a key algorithm */ - LDNS_RDF_TYPE_ALG, - /** unknown types */ - LDNS_RDF_TYPE_UNKNOWN, - /** time (32 bits) */ - LDNS_RDF_TYPE_TIME, - /** period */ - LDNS_RDF_TYPE_PERIOD, - /** tsig time 48 bits */ - LDNS_RDF_TYPE_TSIGTIME, - /** Represents the Public Key Algorithm, HIT and Public Key fields - for the HIP RR types. A HIP specific rdf type is used because of - the unusual layout in wireformat (see RFC 5205 Section 5) */ - LDNS_RDF_TYPE_HIP, - /** variable length any type rdata where the length - is specified by the first 2 bytes */ - LDNS_RDF_TYPE_INT16_DATA, - /** protocol and port bitmaps */ - LDNS_RDF_TYPE_SERVICE, - /** location data */ - LDNS_RDF_TYPE_LOC, - /** well known services */ - LDNS_RDF_TYPE_WKS, - /** NSAP */ - LDNS_RDF_TYPE_NSAP, - /** ATMA */ - LDNS_RDF_TYPE_ATMA, - /** IPSECKEY */ - LDNS_RDF_TYPE_IPSECKEY, - /** nsec3 hash salt */ - LDNS_RDF_TYPE_NSEC3_SALT, - /** nsec3 base32 string (with length byte on wire */ - LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, - - /** 4 shorts represented as 4 * 16 bit hex numbers - * separated by colons. For NID and L64. - */ - LDNS_RDF_TYPE_ILNP64, - - /** 6 * 8 bit hex numbers separated by dashes. For EUI48. */ - LDNS_RDF_TYPE_EUI48, - /** 8 * 8 bit hex numbers separated by dashes. For EUI64. */ - LDNS_RDF_TYPE_EUI64, - - /** A non-zero sequence of US-ASCII letters and numbers in lower case. - * For CAA. - */ - LDNS_RDF_TYPE_TAG, - - /** A encoding of the value field as specified - * [RFC1035], Section 5.1., encoded as remaining rdata. - * For CAA, URI. - */ - LDNS_RDF_TYPE_LONG_STR, - - /** TSIG extended 16bit error value */ - LDNS_RDF_TYPE_TSIGERROR, - - /* draft-ietf-dnsop-svcb-https-05: - * each SvcParam consisting of a SvcParamKey=SvcParamValue pair or - * a standalone SvcParamKey */ - LDNS_RDF_TYPE_SVCPARAM, - - /* Aliases */ - LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC, -}; -typedef enum sldns_enum_rdf_type sldns_rdf_type; - -/** - * Algorithms used in dns - */ -enum sldns_enum_algorithm -{ - LDNS_RSAMD5 = 1, /* RFC 4034,4035 */ - LDNS_DH = 2, - LDNS_DSA = 3, - LDNS_ECC = 4, - LDNS_RSASHA1 = 5, - LDNS_DSA_NSEC3 = 6, - LDNS_RSASHA1_NSEC3 = 7, - LDNS_RSASHA256 = 8, /* RFC 5702 */ - LDNS_RSASHA512 = 10, /* RFC 5702 */ - LDNS_ECC_GOST = 12, /* RFC 5933 */ - LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ - LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ - LDNS_ED25519 = 15, /* RFC 8080 */ - LDNS_ED448 = 16, /* RFC 8080 */ - LDNS_INDIRECT = 252, - LDNS_PRIVATEDNS = 253, - LDNS_PRIVATEOID = 254 -}; -typedef enum sldns_enum_algorithm sldns_algorithm; - -/** - * Hashing algorithms used in the DS record - */ -enum sldns_enum_hash -{ - LDNS_SHA1 = 1, /* RFC 4034 */ - LDNS_SHA256 = 2, /* RFC 4509 */ - LDNS_HASH_GOST = 3, /* RFC 5933 */ - LDNS_SHA384 = 4 /* RFC 6605 */ -}; -typedef enum sldns_enum_hash sldns_hash; - -/** - * algorithms used in CERT rrs - */ -enum sldns_enum_cert_algorithm -{ - LDNS_CERT_PKIX = 1, - LDNS_CERT_SPKI = 2, - LDNS_CERT_PGP = 3, - LDNS_CERT_IPKIX = 4, - LDNS_CERT_ISPKI = 5, - LDNS_CERT_IPGP = 6, - LDNS_CERT_ACPKIX = 7, - LDNS_CERT_IACPKIX = 8, - LDNS_CERT_URI = 253, - LDNS_CERT_OID = 254 -}; -typedef enum sldns_enum_cert_algorithm sldns_cert_algorithm; - -/** - * EDNS option codes - */ -enum sldns_enum_edns_option -{ - LDNS_EDNS_LLQ = 1, /* http://files.dns-sd.org/draft-sekar-dns-llq.txt */ - LDNS_EDNS_UL = 2, /* http://files.dns-sd.org/draft-sekar-dns-ul.txt */ - LDNS_EDNS_NSID = 3, /* RFC5001 */ - /* 4 draft-cheshire-edns0-owner-option */ - LDNS_EDNS_DAU = 5, /* RFC6975 */ - LDNS_EDNS_DHU = 6, /* RFC6975 */ - LDNS_EDNS_N3U = 7, /* RFC6975 */ - LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ - LDNS_EDNS_COOKIE = 10, /* RFC7873 */ - LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ - LDNS_EDNS_PADDING = 12, /* RFC7830 */ - LDNS_EDNS_EDE = 15, /* RFC8914 */ - LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */ - LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534 -}; -typedef enum sldns_enum_edns_option sldns_edns_option; - -enum sldns_enum_ede_code -{ - LDNS_EDE_NONE = -1, /* EDE undefined for internal use */ - LDNS_EDE_OTHER = 0, - LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1, - LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2, - LDNS_EDE_STALE_ANSWER = 3, - LDNS_EDE_FORGED_ANSWER = 4, - LDNS_EDE_DNSSEC_INDETERMINATE = 5, - LDNS_EDE_DNSSEC_BOGUS = 6, - LDNS_EDE_SIGNATURE_EXPIRED = 7, - LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8, - LDNS_EDE_DNSKEY_MISSING = 9, - LDNS_EDE_RRSIGS_MISSING = 10, - LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11, - LDNS_EDE_NSEC_MISSING = 12, - LDNS_EDE_CACHED_ERROR = 13, - LDNS_EDE_NOT_READY = 14, - LDNS_EDE_BLOCKED = 15, - LDNS_EDE_CENSORED = 16, - LDNS_EDE_FILTERED = 17, - LDNS_EDE_PROHIBITED = 18, - LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19, - LDNS_EDE_NOT_AUTHORITATIVE = 20, - LDNS_EDE_NOT_SUPPORTED = 21, - LDNS_EDE_NO_REACHABLE_AUTHORITY = 22, - LDNS_EDE_NETWORK_ERROR = 23, - LDNS_EDE_INVALID_DATA = 24, -}; -typedef enum sldns_enum_ede_code sldns_ede_code; - -#define LDNS_EDNS_MASK_DO_BIT 0x8000 - -/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */ -#define LDNS_TSIG_ERROR_NOERROR 0 -#define LDNS_TSIG_ERROR_BADSIG 16 -#define LDNS_TSIG_ERROR_BADKEY 17 -#define LDNS_TSIG_ERROR_BADTIME 18 -#define LDNS_TSIG_ERROR_BADMODE 19 -#define LDNS_TSIG_ERROR_BADNAME 20 -#define LDNS_TSIG_ERROR_BADALG 21 - -/** DNS Cookie extended rcode */ -#define LDNS_EXT_RCODE_BADCOOKIE 23 - -/** - * Contains all information about resource record types. - * - * This structure contains, for all rr types, the rdata fields that are defined. - */ -struct sldns_struct_rr_descriptor -{ - /** Type of the RR that is described here */ - sldns_rr_type _type; - /** Textual name of the RR type. */ - const char *_name; - /** Minimum number of rdata fields in the RRs of this type. */ - uint8_t _minimum; - /** Maximum number of rdata fields in the RRs of this type. */ - uint8_t _maximum; - /** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */ - const sldns_rdf_type *_wireformat; - /** Special rdf types */ - sldns_rdf_type _variable; - /** Specifies whether compression can be used for dnames in this RR type. */ - sldns_rr_compress _compress; - /** The number of DNAMEs in the _wireformat string, for parsing. */ - uint8_t _dname_count; -}; -typedef struct sldns_struct_rr_descriptor sldns_rr_descriptor; - -/** - * returns the resource record descriptor for the given rr type. - * - * \param[in] type the type value of the rr type - *\return the sldns_rr_descriptor for this type - */ -const sldns_rr_descriptor *sldns_rr_descript(uint16_t type); - -/** - * returns the minimum number of rdata fields of the rr type this descriptor describes. - * - * \param[in] descriptor for an rr type - * \return the minimum number of rdata fields - */ -size_t sldns_rr_descriptor_minimum(const sldns_rr_descriptor *descriptor); - -/** - * returns the maximum number of rdata fields of the rr type this descriptor describes. - * - * \param[in] descriptor for an rr type - * \return the maximum number of rdata fields - */ -size_t sldns_rr_descriptor_maximum(const sldns_rr_descriptor *descriptor); - -/** - * returns the rdf type for the given rdata field number of the rr type for the given descriptor. - * - * \param[in] descriptor for an rr type - * \param[in] field the field number - * \return the rdf type for the field - */ -sldns_rdf_type sldns_rr_descriptor_field_type(const sldns_rr_descriptor *descriptor, size_t field); - -/** - * retrieves a rrtype by looking up its name. - * \param[in] name a string with the name - * \return the type which corresponds with the name - */ -sldns_rr_type sldns_get_rr_type_by_name(const char *name); - -/** - * retrieves a class by looking up its name. - * \param[in] name string with the name - * \return the cass which corresponds with the name - */ -sldns_rr_class sldns_get_rr_class_by_name(const char *name); - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_RRDEF_H */ diff --git a/crates/libunbound-sys/unbound/sldns/sbuffer.c b/crates/libunbound-sys/unbound/sldns/sbuffer.c deleted file mode 100644 index f0f1fbd9..00000000 --- a/crates/libunbound-sys/unbound/sldns/sbuffer.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * buffer.c -- generic memory buffer . - * - * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. - * - */ -/** - * \file - * - * This file contains the definition of sldns_buffer, and functions to manipulate those. - */ -#include "config.h" -#include "sldns/sbuffer.h" -#include - -sldns_buffer * -sldns_buffer_new(size_t capacity) -{ - sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer)); - - if (!buffer) { - return NULL; - } - - buffer->_data = (uint8_t *) malloc(capacity); - if (!buffer->_data) { - free(buffer); - return NULL; - } - - buffer->_position = 0; - buffer->_limit = buffer->_capacity = capacity; - buffer->_fixed = 0; - buffer->_status_err = 0; - - sldns_buffer_invariant(buffer); - - return buffer; -} - -void -sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size) -{ - assert(data != NULL); - - buffer->_position = 0; - buffer->_limit = buffer->_capacity = size; - buffer->_fixed = 0; - if (!buffer->_fixed && buffer->_data) - free(buffer->_data); - buffer->_data = malloc(size); - if(!buffer->_data) { - buffer->_status_err = 1; - return; - } - memcpy(buffer->_data, data, size); - buffer->_status_err = 0; - - sldns_buffer_invariant(buffer); -} - -void -sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size) -{ - memset(buffer, 0, sizeof(*buffer)); - buffer->_data = data; - buffer->_capacity = buffer->_limit = size; - buffer->_fixed = 1; -} - -int -sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity) -{ - void *data; - - sldns_buffer_invariant(buffer); - assert(buffer->_position <= capacity && !buffer->_fixed); - - data = (uint8_t *) realloc(buffer->_data, capacity); - if (!data) { - buffer->_status_err = 1; - return 0; - } else { - buffer->_data = data; - buffer->_limit = buffer->_capacity = capacity; - return 1; - } -} - -int -sldns_buffer_reserve(sldns_buffer *buffer, size_t amount) -{ - sldns_buffer_invariant(buffer); - assert(!buffer->_fixed); - if (buffer->_capacity < buffer->_position + amount) { - size_t new_capacity = buffer->_capacity * 3 / 2; - - if (new_capacity < buffer->_position + amount) { - new_capacity = buffer->_position + amount; - } - if (!sldns_buffer_set_capacity(buffer, new_capacity)) { - buffer->_status_err = 1; - return 0; - } - } - buffer->_limit = buffer->_capacity; - return 1; -} - -int -sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) -{ - va_list args; - int written = 0; - size_t remaining; - - if (sldns_buffer_status_ok(buffer)) { - sldns_buffer_invariant(buffer); - assert(buffer->_limit == buffer->_capacity); - - remaining = sldns_buffer_remaining(buffer); - va_start(args, format); - written = vsnprintf((char *) sldns_buffer_current(buffer), remaining, - format, args); - va_end(args); - if (written == -1) { - buffer->_status_err = 1; - return -1; - } - buffer->_position += written; - } - return written; -} - -void -sldns_buffer_free(sldns_buffer *buffer) -{ - if (!buffer) { - return; - } - - if (!buffer->_fixed) - free(buffer->_data); - - free(buffer); -} - -void -sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from) -{ - size_t tocopy = sldns_buffer_limit(from); - - if(tocopy > sldns_buffer_capacity(result)) - tocopy = sldns_buffer_capacity(result); - sldns_buffer_clear(result); - sldns_buffer_write(result, sldns_buffer_begin(from), tocopy); - sldns_buffer_flip(result); -} diff --git a/crates/libunbound-sys/unbound/sldns/sbuffer.h b/crates/libunbound-sys/unbound/sldns/sbuffer.h deleted file mode 100644 index 1b7fe370..00000000 --- a/crates/libunbound-sys/unbound/sldns/sbuffer.h +++ /dev/null @@ -1,750 +0,0 @@ -/* - * buffer.h -- generic memory buffer. - * - * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. - * - * - * The buffer module implements a generic buffer. The API is based on - * the java.nio.Buffer interface. - */ - -#ifndef LDNS_SBUFFER_H -#define LDNS_SBUFFER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef S_SPLINT_S -# define INLINE -#else -# ifdef SWIG -# define INLINE static -# else -# define INLINE static inline -# endif -#endif - -/* - * Copy data allowing for unaligned accesses in network byte order - * (big endian). - */ -INLINE uint16_t -sldns_read_uint16(const void *src) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - return ntohs(*(const uint16_t *) src); -#else - const uint8_t *p = (const uint8_t *) src; - return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; -#endif -} - -INLINE uint32_t -sldns_read_uint32(const void *src) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - return ntohl(*(const uint32_t *) src); -#else - const uint8_t *p = (const uint8_t *) src; - return ( ((uint32_t) p[0] << 24) - | ((uint32_t) p[1] << 16) - | ((uint32_t) p[2] << 8) - | (uint32_t) p[3]); -#endif -} - -/* - * Copy data allowing for unaligned accesses in network byte order - * (big endian). - */ -INLINE void -sldns_write_uint16(void *dst, uint16_t data) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - * (uint16_t *) dst = htons(data); -#else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 8) & 0xff); - p[1] = (uint8_t) (data & 0xff); -#endif -} - -INLINE void -sldns_write_uint32(void *dst, uint32_t data) -{ -#ifdef ALLOW_UNALIGNED_ACCESSES - * (uint32_t *) dst = htonl(data); -#else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 24) & 0xff); - p[1] = (uint8_t) ((data >> 16) & 0xff); - p[2] = (uint8_t) ((data >> 8) & 0xff); - p[3] = (uint8_t) (data & 0xff); -#endif -} - - -INLINE void -sldns_write_uint48(void *dst, uint64_t data) -{ - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) ((data >> 40) & 0xff); - p[1] = (uint8_t) ((data >> 32) & 0xff); - p[2] = (uint8_t) ((data >> 24) & 0xff); - p[3] = (uint8_t) ((data >> 16) & 0xff); - p[4] = (uint8_t) ((data >> 8) & 0xff); - p[5] = (uint8_t) (data & 0xff); -} - - -/** - * \file sbuffer.h - * - * This file contains the definition of sldns_buffer, and functions to manipulate those. - */ - -/** - * implementation of buffers to ease operations - * - * sldns_buffers can contain arbitrary information, per octet. You can write - * to the current end of a buffer, read from the current position, and - * access any data within it. - */ -struct sldns_buffer -{ - /** The current position used for reading/writing */ - size_t _position; - - /** The read/write limit */ - size_t _limit; - - /** The amount of data the buffer can contain */ - size_t _capacity; - - /** The data contained in the buffer */ - uint8_t *_data; - - /** If the buffer is fixed it cannot be resized */ - unsigned _fixed : 1; - - /** The current state of the buffer. If writing to the buffer fails - * for any reason, this value is changed. This way, you can perform - * multiple writes in sequence and check for success afterwards. */ - unsigned _status_err : 1; -}; -typedef struct sldns_buffer sldns_buffer; - -#ifdef NDEBUG -INLINE void -sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer)) -{ -} -#else -INLINE void -sldns_buffer_invariant(sldns_buffer *buffer) -{ - assert(buffer != NULL); - assert(buffer->_position <= buffer->_limit); - assert(buffer->_limit <= buffer->_capacity); - assert(buffer->_data != NULL); -} -#endif - -/** - * creates a new buffer with the specified capacity. - * - * \param[in] capacity the size (in bytes) to allocate for the buffer - * \return the created buffer - */ -sldns_buffer *sldns_buffer_new(size_t capacity); - -/** - * creates a buffer with the specified data. The data IS copied - * and MEMORY allocations are done. The buffer is not fixed and can - * be resized using buffer_reserve(). - * - * \param[in] buffer pointer to the buffer to put the data in - * \param[in] data the data to encapsulate in the buffer - * \param[in] size the size of the data - */ -void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size); - -/** - * Setup a buffer with the data pointed to. No data copied, no memory allocs. - * The buffer is fixed. - * \param[in] buffer pointer to the buffer to put the data in - * \param[in] data the data to encapsulate in the buffer - * \param[in] size the size of the data - */ -void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size); - -/** - * clears the buffer and make it ready for writing. The buffer's limit - * is set to the capacity and the position is set to 0. - * \param[in] buffer the buffer to clear - */ -INLINE void sldns_buffer_clear(sldns_buffer *buffer) -{ - sldns_buffer_invariant(buffer); - - /* reset status here? */ - - buffer->_position = 0; - buffer->_limit = buffer->_capacity; -} - -/** - * makes the buffer ready for reading the data that has been written to - * the buffer. The buffer's limit is set to the current position and - * the position is set to 0. - * - * \param[in] buffer the buffer to flip - */ -INLINE void sldns_buffer_flip(sldns_buffer *buffer) -{ - sldns_buffer_invariant(buffer); - - buffer->_limit = buffer->_position; - buffer->_position = 0; -} - -/** - * make the buffer ready for re-reading the data. The buffer's - * position is reset to 0. - * \param[in] buffer the buffer to rewind - */ -INLINE void sldns_buffer_rewind(sldns_buffer *buffer) -{ - sldns_buffer_invariant(buffer); - - buffer->_position = 0; -} - -/** - * returns the current position in the buffer (as a number of bytes) - * \param[in] buffer the buffer - * \return the current position - */ -INLINE size_t -sldns_buffer_position(sldns_buffer *buffer) -{ - return buffer->_position; -} - -/** - * sets the buffer's position to MARK. The position must be less than - * or equal to the buffer's limit. - * \param[in] buffer the buffer - * \param[in] mark the mark to use - */ -INLINE void -sldns_buffer_set_position(sldns_buffer *buffer, size_t mark) -{ - assert(mark <= buffer->_limit); - buffer->_position = mark; -} - -/** - * changes the buffer's position by COUNT bytes. The position must not - * be moved behind the buffer's limit or before the beginning of the - * buffer. - * \param[in] buffer the buffer - * \param[in] count the count to use - */ -INLINE void -sldns_buffer_skip(sldns_buffer *buffer, ssize_t count) -{ - assert(buffer->_position + count <= buffer->_limit); - buffer->_position += count; -} - -/** - * returns the maximum size of the buffer - * \param[in] buffer - * \return the size - */ -INLINE size_t -sldns_buffer_limit(sldns_buffer *buffer) -{ - return buffer->_limit; -} - -/** - * changes the buffer's limit. If the buffer's position is greater - * than the new limit the position is set to the limit. - * \param[in] buffer the buffer - * \param[in] limit the new limit - */ -INLINE void -sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit) -{ - assert(limit <= buffer->_capacity); - buffer->_limit = limit; - if (buffer->_position > buffer->_limit) - buffer->_position = buffer->_limit; -} - -/** - * returns the number of bytes the buffer can hold. - * \param[in] buffer the buffer - * \return the number of bytes - */ -INLINE size_t -sldns_buffer_capacity(sldns_buffer *buffer) -{ - return buffer->_capacity; -} - -/** - * changes the buffer's capacity. The data is reallocated so any - * pointers to the data may become invalid. The buffer's limit is set - * to the buffer's new capacity. - * \param[in] buffer the buffer - * \param[in] capacity the capacity to use - * \return whether this failed or succeeded - */ -int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity); - -/** - * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's - * capacity is increased if necessary using buffer_set_capacity(). - * - * The buffer's limit is always set to the (possibly increased) - * capacity. - * \param[in] buffer the buffer - * \param[in] amount amount to use - * \return whether this failed or succeeded - */ -int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount); - -/** - * returns a pointer to the data at the indicated position. - * \param[in] buffer the buffer - * \param[in] at position - * \return the pointer to the data - */ -INLINE uint8_t * -sldns_buffer_at(const sldns_buffer *buffer, size_t at) -{ - assert(at <= buffer->_limit); - return buffer->_data + at; -} - -/** - * returns a pointer to the beginning of the buffer (the data at - * position 0). - * \param[in] buffer the buffer - * \return the pointer - */ -INLINE uint8_t * -sldns_buffer_begin(const sldns_buffer *buffer) -{ - return sldns_buffer_at(buffer, 0); -} - -/** - * returns a pointer to the end of the buffer (the data at the buffer's - * limit). - * \param[in] buffer the buffer - * \return the pointer - */ -INLINE uint8_t * -sldns_buffer_end(sldns_buffer *buffer) -{ - return sldns_buffer_at(buffer, buffer->_limit); -} - -/** - * returns a pointer to the data at the buffer's current position. - * \param[in] buffer the buffer - * \return the pointer - */ -INLINE uint8_t * -sldns_buffer_current(sldns_buffer *buffer) -{ - return sldns_buffer_at(buffer, buffer->_position); -} - -/** - * returns the number of bytes remaining between the indicated position and - * the limit. - * \param[in] buffer the buffer - * \param[in] at indicated position - * \return number of bytes - */ -INLINE size_t -sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at) -{ - sldns_buffer_invariant(buffer); - assert(at <= buffer->_limit); - return at < buffer->_limit ? buffer->_limit - at : 0; -} - -/** - * returns the number of bytes remaining between the buffer's position and - * limit. - * \param[in] buffer the buffer - * \return the number of bytes - */ -INLINE size_t -sldns_buffer_remaining(sldns_buffer *buffer) -{ - return sldns_buffer_remaining_at(buffer, buffer->_position); -} - -/** - * checks if the buffer has at least COUNT more bytes available. - * Before reading or writing the caller needs to ensure enough space - * is available! - * \param[in] buffer the buffer - * \param[in] at indicated position - * \param[in] count how much is available - * \return true or false (as int?) - */ -INLINE int -sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count) -{ - return count <= sldns_buffer_remaining_at(buffer, at); -} - -/** - * checks if the buffer has count bytes available at the current position - * \param[in] buffer the buffer - * \param[in] count how much is available - * \return true or false (as int?) - */ -INLINE int -sldns_buffer_available(sldns_buffer *buffer, size_t count) -{ - return sldns_buffer_available_at(buffer, buffer->_position, count); -} - -/** - * writes the given data to the buffer at the specified position - * \param[in] buffer the buffer - * \param[in] at the position (in number of bytes) to write the data at - * \param[in] data pointer to the data to write to the buffer - * \param[in] count the number of bytes of data to write - */ -INLINE void -sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count) -{ - assert(sldns_buffer_available_at(buffer, at, count)); - memcpy(buffer->_data + at, data, count); -} - -/** - * set the given byte to the buffer at the specified position - * \param[in] buffer the buffer - * \param[in] at the position (in number of bytes) to write the data at - * \param[in] c the byte to set to the buffer - * \param[in] count the number of bytes of bytes to write - */ - -INLINE void -sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count) -{ - assert(sldns_buffer_available_at(buffer, at, count)); - memset(buffer->_data + at, c, count); -} - - -/** - * writes count bytes of data to the current position of the buffer - * \param[in] buffer the buffer - * \param[in] data the data to write - * \param[in] count the length of the data to write - */ -INLINE void -sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count) -{ - sldns_buffer_write_at(buffer, buffer->_position, data, count); - buffer->_position += count; -} - -/** - * copies the given (null-delimited) string to the specified position at the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \param[in] str the string to write - */ -INLINE void -sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str) -{ - sldns_buffer_write_at(buffer, at, str, strlen(str)); -} - -/** - * copies the given (null-delimited) string to the current position at the buffer - * \param[in] buffer the buffer - * \param[in] str the string to write - */ -INLINE void -sldns_buffer_write_string(sldns_buffer *buffer, const char *str) -{ - sldns_buffer_write(buffer, str, strlen(str)); -} - -/** - * writes the given byte of data at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \param[in] data the 8 bits to write - */ -INLINE void -sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(data))); - buffer->_data[at] = data; -} - -/** - * writes the given byte of data at the current position in the buffer - * \param[in] buffer the buffer - * \param[in] data the 8 bits to write - */ -INLINE void -sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data) -{ - sldns_buffer_write_u8_at(buffer, buffer->_position, data); - buffer->_position += sizeof(data); -} - -/** - * writes the given 2 byte integer at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \param[in] data the 16 bits to write - */ -INLINE void -sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(data))); - sldns_write_uint16(buffer->_data + at, data); -} - -/** - * writes the given 2 byte integer at the current position in the buffer - * \param[in] buffer the buffer - * \param[in] data the 16 bits to write - */ -INLINE void -sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data) -{ - sldns_buffer_write_u16_at(buffer, buffer->_position, data); - buffer->_position += sizeof(data); -} - -/** - * writes the given 4 byte integer at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \param[in] data the 32 bits to write - */ -INLINE void -sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(data))); - sldns_write_uint32(buffer->_data + at, data); -} - -/** - * writes the given 6 byte integer at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \param[in] data the (lower) 48 bits to write - */ -INLINE void -sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data) -{ - assert(sldns_buffer_available_at(buffer, at, 6)); - sldns_write_uint48(buffer->_data + at, data); -} - -/** - * writes the given 4 byte integer at the current position in the buffer - * \param[in] buffer the buffer - * \param[in] data the 32 bits to write - */ -INLINE void -sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data) -{ - sldns_buffer_write_u32_at(buffer, buffer->_position, data); - buffer->_position += sizeof(data); -} - -/** - * writes the given 6 byte integer at the current position in the buffer - * \param[in] buffer the buffer - * \param[in] data the 48 bits to write - */ -INLINE void -sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data) -{ - sldns_buffer_write_u48_at(buffer, buffer->_position, data); - buffer->_position += 6; -} - -/** - * copies count bytes of data at the given position to the given data-array - * \param[in] buffer the buffer - * \param[in] at the position in the buffer to start - * \param[out] data buffer to copy to - * \param[in] count the length of the data to copy - */ -INLINE void -sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count) -{ - assert(sldns_buffer_available_at(buffer, at, count)); - memcpy(data, buffer->_data + at, count); -} - -/** - * copies count bytes of data at the current position to the given data-array - * \param[in] buffer the buffer - * \param[out] data buffer to copy to - * \param[in] count the length of the data to copy - */ -INLINE void -sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count) -{ - sldns_buffer_read_at(buffer, buffer->_position, data, count); - buffer->_position += count; -} - -/** - * returns the byte value at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at the position in the buffer - * \return 1 byte integer - */ -INLINE uint8_t -sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t))); - return buffer->_data[at]; -} - -/** - * returns the byte value at the current position in the buffer - * \param[in] buffer the buffer - * \return 1 byte integer - */ -INLINE uint8_t -sldns_buffer_read_u8(sldns_buffer *buffer) -{ - uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position); - buffer->_position += sizeof(uint8_t); - return result; -} - -/** - * returns the 2-byte integer value at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at position in the buffer - * \return 2 byte integer - */ -INLINE uint16_t -sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t))); - return sldns_read_uint16(buffer->_data + at); -} - -/** - * returns the 2-byte integer value at the current position in the buffer - * \param[in] buffer the buffer - * \return 2 byte integer - */ -INLINE uint16_t -sldns_buffer_read_u16(sldns_buffer *buffer) -{ - uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position); - buffer->_position += sizeof(uint16_t); - return result; -} - -/** - * returns the 4-byte integer value at the given position in the buffer - * \param[in] buffer the buffer - * \param[in] at position in the buffer - * \return 4 byte integer - */ -INLINE uint32_t -sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at) -{ - assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t))); - return sldns_read_uint32(buffer->_data + at); -} - -/** - * returns the 4-byte integer value at the current position in the buffer - * \param[in] buffer the buffer - * \return 4 byte integer - */ -INLINE uint32_t -sldns_buffer_read_u32(sldns_buffer *buffer) -{ - uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position); - buffer->_position += sizeof(uint32_t); - return result; -} - -/** - * returns the status of the buffer - * \param[in] buffer - * \return the status - */ -INLINE int -sldns_buffer_status(sldns_buffer *buffer) -{ - return (int)buffer->_status_err; -} - -/** - * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise - * \param[in] buffer the buffer - * \return true or false - */ -INLINE int -sldns_buffer_status_ok(sldns_buffer *buffer) -{ - if (buffer) { - return sldns_buffer_status(buffer) == 0; - } else { - return 0; - } -} - -/** - * prints to the buffer, increasing the capacity if required using - * buffer_reserve(). The buffer's position is set to the terminating '\\0' - * Returns the number of characters written (not including the - * terminating '\\0') or -1 on failure. - */ -int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...) - ATTR_FORMAT(printf, 2, 3); - -/** - * frees the buffer. - * \param[in] *buffer the buffer to be freed - */ -void sldns_buffer_free(sldns_buffer *buffer); - -/** - * Copy contents of the from buffer to the result buffer and then flips - * the result buffer. Data will be silently truncated if the result buffer is - * too small. - * \param[out] *result resulting buffer which is copied to. - * \param[in] *from what to copy to result. - */ -void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from); - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_SBUFFER_H */ diff --git a/crates/libunbound-sys/unbound/sldns/str2wire.c b/crates/libunbound-sys/unbound/sldns/str2wire.c deleted file mode 100644 index 45e24761..00000000 --- a/crates/libunbound-sys/unbound/sldns/str2wire.c +++ /dev/null @@ -1,2864 +0,0 @@ -/** - * str2wire.c - read txt presentation of RRs - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -/** - * \file - * - * Parses text to wireformat. - */ -#include "config.h" -#include "sldns/str2wire.h" -#include "sldns/wire2str.h" -#include "sldns/sbuffer.h" -#include "sldns/parse.h" -#include "sldns/parseutil.h" -#include -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif - -/** bits for the offset */ -#define RET_OFFSET_MASK (((unsigned)(~LDNS_WIREPARSE_MASK))>>LDNS_WIREPARSE_SHIFT) -/** return an error */ -#define RET_ERR(e, off) ((int)(((e)&LDNS_WIREPARSE_MASK)|(((off)&RET_OFFSET_MASK)< LDNS_MAX_DOMAINLEN * 4) { - return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0); - } - if (0 == len) { - return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0); - } - - /* root label */ - if (1 == len && *str == '.') { - if(*olen < 1) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); - buf[0] = 0; - *olen = 1; - return LDNS_WIREPARSE_ERR_OK; - } - - /* get on with the rest */ - - /* s is on the current character in the string - * pq points to where the labellength is going to go - * label_len keeps track of the current label's length - * q builds the dname inside the buf array - */ - len = 0; - if(*olen < 1) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); - q = buf+1; - pq = buf; - label_len = 0; - for (s = str; *s; s++, q++) { - if (q >= buf + *olen) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); - if (q >= buf + LDNS_MAX_DOMAINLEN) - return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); - switch (*s) { - case '.': - if (label_len > LDNS_MAX_LABELLEN) { - return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); - } - if (label_len == 0) { - return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); - } - len += label_len + 1; - *q = 0; - *pq = label_len; - label_len = 0; - pq = q; - break; - case '\\': - /* octet value or literal char */ - s += 1; - if (!sldns_parse_escape(q, &s)) { - *q = 0; - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf); - } - s -= 1; - label_len++; - break; - default: - *q = (uint8_t)*s; - label_len++; - } - } - - /* add root label if last char was not '.' */ - if(label_len != 0) { - if(rel) *rel = 1; - if (q >= buf + *olen) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); - if (q >= buf + LDNS_MAX_DOMAINLEN) { - return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); - } - if (label_len > LDNS_MAX_LABELLEN) { - return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); - } - if (label_len == 0) { /* label_len 0 but not . at end? */ - return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); - } - len += label_len + 1; - *pq = label_len; - *q = 0; - } - len++; - *olen = len; - - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len) -{ - return sldns_str2wire_dname_buf_rel(str, buf, len, NULL); -} - -int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, - uint8_t* origin, size_t origin_len) -{ - size_t dlen = *len; - int rel = 0; - int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel); - if(s) return s; - - if(rel && origin && dlen > 0) { - if((unsigned)dlen >= 0x00ffffffU || - (unsigned)origin_len >= 0x00ffffffU) - /* guard against integer overflow in addition */ - return RET_ERR(LDNS_WIREPARSE_ERR_GENERAL, *len); - if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN) - return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, - LDNS_MAX_DOMAINLEN); - if(dlen + origin_len - 1 > *len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - *len); - memmove(buf+dlen-1, origin, origin_len); - *len = dlen + origin_len - 1; - } else - *len = dlen; - return LDNS_WIREPARSE_ERR_OK; -} - -uint8_t* sldns_str2wire_dname(const char* str, size_t* len) -{ - uint8_t dname[LDNS_MAX_DOMAINLEN+1]; - *len = sizeof(dname); - if(sldns_str2wire_dname_buf(str, dname, len) == 0) { - uint8_t* r; - if(*len > sizeof(dname)) return NULL; - r = (uint8_t*)malloc(*len); - if(r) return memcpy(r, dname, *len); - } - *len = 0; - return NULL; -} - -/** read owner name */ -static int -rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len, - size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, - size_t prev_len, char* token, size_t token_len) -{ - /* split the rr in its parts -1 signals trouble */ - if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, - sldns_buffer_position(strbuf)); - } - - if(token_len < 2) /* make sure there is space to read "@" or "" */ - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - if(token[0]=='@' && token[1]=='\0') { - uint8_t* tocopy; - if (origin) { - *dname_len = origin_len; - tocopy = origin; - } else if (prev) { - *dname_len = prev_len; - tocopy = prev; - } else { - /* default to root */ - *dname_len = 1; - tocopy = (uint8_t*)"\0"; - } - if(*len < *dname_len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - memmove(rr, tocopy, *dname_len); - } else if(*token == '\0') { - /* no ownername was given, try prev, if that fails - * origin, else default to root */ - uint8_t* tocopy; - if(prev) { - *dname_len = prev_len; - tocopy = prev; - } else if(origin) { - *dname_len = origin_len; - tocopy = origin; - } else { - *dname_len = 1; - tocopy = (uint8_t*)"\0"; - } - if(*len < *dname_len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - memmove(rr, tocopy, *dname_len); - } else { - size_t dlen = *len; - int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen, - origin, origin_len); - if(s) return RET_ERR_SHIFT(s, - sldns_buffer_position(strbuf)-strlen(token)); - *dname_len = dlen; - } - return LDNS_WIREPARSE_ERR_OK; -} - -/** read ttl */ -static int -rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, - int* not_there, uint32_t* ttl, uint32_t default_ttl) -{ - const char* endptr; - int overflow; - if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, - sldns_buffer_position(strbuf)); - } - *ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow); - if(overflow) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, - sldns_buffer_position(strbuf)); - } - - if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { - *not_there = 1; - /* ah, it's not there or something */ - if (default_ttl == 0) { - *ttl = LDNS_DEFAULT_TTL; - } else { - *ttl = default_ttl; - } - } - return LDNS_WIREPARSE_ERR_OK; -} - -/** read class */ -static int -rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len, - int* not_there, uint16_t* cl) -{ - /* if 'not_there' then we got token from previous parse routine */ - if(!*not_there) { - /* parse new token for class */ - if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS, - sldns_buffer_position(strbuf)); - } - } else *not_there = 0; - *cl = sldns_get_rr_class_by_name(token); - /* class can be left out too, assume IN, current token must be type */ - if(*cl == 0 && strcmp(token, "CLASS0") != 0) { - *not_there = 1; - *cl = LDNS_RR_CLASS_IN; - } - return LDNS_WIREPARSE_ERR_OK; -} - -/** read type */ -static int -rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len, - int* not_there, uint16_t* tp) -{ - /* if 'not_there' then we got token from previous parse routine */ - if(!*not_there) { - /* parse new token for type */ - if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, - sldns_buffer_position(strbuf)); - } - } - *tp = sldns_get_rr_type_by_name(token); - if(*tp == 0 && strcmp(token, "TYPE0") != 0) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, - sldns_buffer_position(strbuf)); - } - return LDNS_WIREPARSE_ERR_OK; -} - -/** put type, class, ttl into rr buffer */ -static int -rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len, - size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question) -{ - if(question) { - /* question is : name, type, class */ - if(dname_len + 4 > len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - sldns_write_uint16(rr+dname_len, tp); - sldns_write_uint16(rr+dname_len+2, cl); - return LDNS_WIREPARSE_ERR_OK; - } - - /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */ - if(dname_len + 10 > len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - sldns_write_uint16(rr+dname_len, tp); - sldns_write_uint16(rr+dname_len+2, cl); - sldns_write_uint32(rr+dname_len+4, ttl); - sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */ - return LDNS_WIREPARSE_ERR_OK; -} - -/** find delimiters for type */ -static const char* -rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max) -{ - switch(rdftype) { - case LDNS_RDF_TYPE_B64 : - case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ - case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ - case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ - case LDNS_RDF_TYPE_IPSECKEY : - case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { - return "\n"; - } - break; - default : break; - } - return "\n\t "; -} - -/* Syntactic sugar for sldns_rr_new_frm_str_internal */ -static int -sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) -{ - return rdf_type == LDNS_RDF_TYPE_STR || - rdf_type == LDNS_RDF_TYPE_LONG_STR; -} - -/** see if rdata is quoted */ -static int -rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, - sldns_rdf_type rdftype) -{ - if(sldns_rdf_type_maybe_quoted(rdftype) && - sldns_buffer_remaining(strbuf) > 0) { - - /* skip spaces */ - while(sldns_buffer_remaining(strbuf) > 0 && - (*(sldns_buffer_current(strbuf)) == ' ' || - *(sldns_buffer_current(strbuf)) == '\t')) { - sldns_buffer_skip(strbuf, 1); - } - - if(sldns_buffer_remaining(strbuf) > 0 && - *(sldns_buffer_current(strbuf)) == '\"') { - *delimiters = "\"\0"; - sldns_buffer_skip(strbuf, 1); - return 1; - } - } - return 0; -} - -/** spool hex data into rdata */ -static int -rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, - size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size) -{ - char* p = token; - while(*p) { - if(isspace((unsigned char)*p)) { - p++; - continue; - } - if(!isxdigit((unsigned char)*p)) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, - p-token); - if(*cur_hex_data_size >= hex_data_size) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, - p-token); - /* extra robust check */ - if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - p-token); - /* see if 16s or 1s */ - if( ((*cur_hex_data_size)&1) == 0) { - rr[rr_cur_len+(*cur_hex_data_size)/2] = - (uint8_t)sldns_hexdigit_to_int(*p)*16; - } else { - rr[rr_cur_len+(*cur_hex_data_size)/2] += - (uint8_t)sldns_hexdigit_to_int(*p); - } - p++; - (*cur_hex_data_size)++; - } - return LDNS_WIREPARSE_ERR_OK; -} - -/** read unknown rr type format */ -static int -rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, - uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos) -{ - const char* delim = "\n\t "; - size_t hex_data_size, cur_hex_data_size; - /* go back to before \# - * and skip it while setting delimiters better - */ - sldns_buffer_set_position(strbuf, pre_data_pos); - if(sldns_bget_token(strbuf, token, delim, token_len) == -1) - return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */ - /* read rdata octet length */ - if(sldns_bget_token(strbuf, token, delim, token_len) == -1) { - /* something goes very wrong here */ - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, - sldns_buffer_position(strbuf)); - } - hex_data_size = (size_t)atoi(token); - if(hex_data_size > LDNS_MAX_RDFLEN || - *rr_cur_len + hex_data_size > *rr_len) { - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - } - /* copy hex chars into hex str (2 chars per byte) */ - hex_data_size *= 2; - cur_hex_data_size = 0; - while(cur_hex_data_size < hex_data_size) { - int status; - ssize_t c = sldns_bget_token(strbuf, token, delim, token_len); - if((status = rrinternal_spool_hex(token, rr, *rr_len, - *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0) - return RET_ERR_SHIFT(status, - sldns_buffer_position(strbuf)-strlen(token)); - if(c == -1) { - if(cur_hex_data_size != hex_data_size) - return RET_ERR( - LDNS_WIREPARSE_ERR_SYNTAX_RDATA, - sldns_buffer_position(strbuf)); - break; - } - } - *rr_cur_len += hex_data_size/2; - return LDNS_WIREPARSE_ERR_OK; -} - -/** parse normal RR rdata element */ -static int -rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len, - uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype, - uint16_t rr_type, size_t r_cnt, size_t r_max, size_t dname_len, - uint8_t* origin, size_t origin_len) -{ - size_t len; - int status; - - switch(rdftype) { - case LDNS_RDF_TYPE_DNAME: - /* check if the origin should be used or concatenated */ - if(strcmp(token, "@") == 0) { - uint8_t* tocopy; - size_t copylen; - if(origin) { - copylen = origin_len; - tocopy = origin; - } else if(rr_type == LDNS_RR_TYPE_SOA) { - copylen = dname_len; - tocopy = rr; /* copy rr owner name */ - } else { - copylen = 1; - tocopy = (uint8_t*)"\0"; - } - if((*rr_cur_len) + copylen > rr_len) - return RET_ERR( - LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - memmove(rr+*rr_cur_len, tocopy, copylen); - (*rr_cur_len) += copylen; - } else { - size_t dlen = rr_len - (*rr_cur_len); - int s = sldns_str2wire_dname_buf_origin(token, - rr+*rr_cur_len, &dlen, origin, origin_len); - if(s) return RET_ERR_SHIFT(s, - sldns_buffer_position(strbuf)-strlen(token)); - (*rr_cur_len) += dlen; - } - return LDNS_WIREPARSE_ERR_OK; - - case LDNS_RDF_TYPE_HEX: - case LDNS_RDF_TYPE_B64: - /* When this is the last rdata field, then the - * rest should be read in (cause then these - * rdf types may contain spaces). */ - if(r_cnt == r_max - 1) { - size_t tlen = strlen(token); - (void)sldns_bget_token(strbuf, token+tlen, "\n", - token_len - tlen); - } - break; - default: - break; - } - - len = rr_len - (*rr_cur_len); - if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len, - rdftype)) != 0) - return RET_ERR_SHIFT(status, - sldns_buffer_position(strbuf)-strlen(token)); - *rr_cur_len += len; - return LDNS_WIREPARSE_ERR_OK; -} - -/** - * Parse one rdf token. Takes care of quotes and parenthesis. - */ -static int -sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, - int* quoted, int* parens, size_t* pre_data_pos, - const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) -{ - size_t slen; - - /* skip spaces and tabs */ - while(sldns_buffer_remaining(strbuf) > 0 && !*quoted && - (*(sldns_buffer_current(strbuf)) == ' ' || - *(sldns_buffer_current(strbuf)) == '\t')) { - sldns_buffer_skip(strbuf, 1); - } - - *pre_data_pos = sldns_buffer_position(strbuf); - if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters, - token_len, parens, (*quoted)?NULL:" \t") == -1) { - return 0; - } - slen = strlen(token); - /* check if not quoted yet, and we have encountered quotes */ - if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && - slen >= 2 && - (token[0] == '"' || token[0] == '\'') && - (token[slen-1] == '"' || token[slen-1] == '\'')) { - /* move token two smaller (quotes) with endnull */ - memmove(token, token+1, slen-2); - token[slen-2] = 0; - slen -= 2; - *quoted = 1; - } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && - slen >= 2 && - (token[0] == '"' || token[0] == '\'')) { - /* got the start quote (remove it) but read remainder - * of quoted string as well into remainder of token */ - memmove(token, token+1, slen-1); - token[slen-1] = 0; - slen -= 1; - *quoted = 1; - /* rewind buffer over skipped whitespace */ - while(sldns_buffer_position(strbuf) > 0 && - (sldns_buffer_current(strbuf)[-1] == ' ' || - sldns_buffer_current(strbuf)[-1] == '\t')) { - sldns_buffer_skip(strbuf, -1); - } - if(sldns_bget_token_par(strbuf, token+slen, - "\"", token_len-slen, - parens, NULL) == -1) { - return 0; - } - slen = strlen(token); - } - *token_strlen = slen; - return 1; -} - -/** Add space and one more rdf token onto the existing token string. */ -static int -sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, - int* quoted, int* parens, size_t* pre_data_pos, - const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) -{ - size_t addlen = *token_len - *token_strlen; - size_t addstrlen = 0; - - /* add space */ - /* when addlen < 2, the token buffer is full considering the NULL byte - * from strlen and will lead to buffer overflow with the second - * assignment below. */ - if(addlen < 2) return 0; - token[*token_strlen] = ' '; - token[++(*token_strlen)] = 0; - - /* read another token */ - addlen = *token_len - *token_strlen; - if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted, - parens, pre_data_pos, delimiters, rdftype, &addstrlen)) - return 0; - (*token_strlen) += addstrlen; - return 1; -} - -static int sldns_str2wire_svcparam_key_cmp(const void *a, const void *b) -{ - return sldns_read_uint16(*(uint8_t**) a) - - sldns_read_uint16(*(uint8_t**) b); -} - -/** - * Add constraints to the SVCB RRs which involve the whole set - */ -static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len) -{ - size_t nparams = 0, i; - uint8_t new_rdata[LDNS_MAX_RDFLEN]; - uint8_t* new_rdata_ptr = new_rdata; - uint8_t* svcparams[MAX_NUMBER_OF_SVCPARAMS]; - uint8_t* rdata_ptr = rdata; - uint16_t rdata_remaining = rdata_len; - - /* find the SvcParams */ - while (rdata_remaining) { - uint16_t svcbparam_len; - - svcparams[nparams] = rdata_ptr; - if (rdata_remaining < 4) - return LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA; - svcbparam_len = sldns_read_uint16(rdata_ptr + 2); - rdata_remaining -= 4; - rdata_ptr += 4; - - if (rdata_remaining < svcbparam_len) - return LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA; - rdata_remaining -= svcbparam_len; - rdata_ptr += svcbparam_len; - - nparams += 1; - if (nparams >= MAX_NUMBER_OF_SVCPARAMS) - return LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS; - } - - /* In draft-ietf-dnsop-svcb-https-06 Section 7: - * - * In wire format, the keys are represented by their numeric - * values in network byte order, concatenated in ascending order. - */ - qsort((void *)svcparams - ,nparams - ,sizeof(uint8_t*) - ,sldns_str2wire_svcparam_key_cmp); - - - /* The code below revolves around semantic errors in the SVCParam set. - * So long as we do not distinguish between running Unbound as a primary - * or as a secondary, we default to secondary behavior and we ignore the - * semantic errors. */ - -#ifdef SVCB_SEMANTIC_ERRORS - { - uint8_t* mandatory = NULL; - /* In draft-ietf-dnsop-svcb-https-06 Section 7: - * - * Keys (...) MUST NOT appear more than once. - * - * If they key has already been seen, we have a duplicate - */ - for(i=0; i < nparams; i++) { - uint16_t key = sldns_read_uint16(svcparams[i]); - if(i + 1 < nparams && key == sldns_read_uint16(svcparams[i+1])) - return LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS; - if(key == SVCB_KEY_MANDATORY) - mandatory = svcparams[i]; - } - - /* Verify that all the SvcParamKeys in mandatory are present */ - if(mandatory) { - /* Divide by sizeof(uint16_t)*/ - uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t); - - /* Guaranteed by sldns_str2wire_svcparam_key_value */ - assert(mandatory_nkeys > 0); - - for(i=0; i < mandatory_nkeys; i++) { - uint16_t mandatory_key = sldns_read_uint16( - mandatory - + 2 * sizeof(uint16_t) - + i * sizeof(uint16_t)); - uint8_t found = 0; - size_t j; - - for(j=0; j < nparams; j++) { - if(mandatory_key == sldns_read_uint16(svcparams[j])) { - found = 1; - break; - } - } - - if(!found) - return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM; - } - } - } -#endif - /* Write rdata in correct order */ - for (i = 0; i < nparams; i++) { - uint16_t svcparam_len = sldns_read_uint16(svcparams[i] + 2) - + 2 * sizeof(uint16_t); - - if ((unsigned)(new_rdata_ptr - new_rdata) + svcparam_len > sizeof(new_rdata)) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - memcpy(new_rdata_ptr, svcparams[i], svcparam_len); - new_rdata_ptr += svcparam_len; - } - memcpy(rdata, new_rdata, rdata_len); - return LDNS_WIREPARSE_ERR_OK; -} - -/** parse rdata from string into rr buffer(-remainder after dname). */ -static int -rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, - uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type, - uint8_t* origin, size_t origin_len) -{ - const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type); - size_t r_cnt, r_min, r_max; - size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen; - int was_unknown_rr_format = 0, parens = 0, status, quoted; - const char* delimiters; - sldns_rdf_type rdftype; - /* a desc is always returned */ - if(!desc) return LDNS_WIREPARSE_ERR_GENERAL; - r_max = sldns_rr_descriptor_maximum(desc); - r_min = sldns_rr_descriptor_minimum(desc); - /* robust check */ - if(rr_cur_len > *rr_len) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(strbuf)); - - /* because number of fields can be variable, we can't rely on - * _maximum() only */ - for(r_cnt=0; r_cnt < r_max; r_cnt++) { - rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); - delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max); - quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype); - - if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed, - &parens, &pre_data_pos, delimiters, rdftype, - &token_strlen)) - break; - - /* rfc3597 specifies that any type can be represented - * with \# method, which can contain spaces... - * it does specify size though... */ - - /* unknown RR data */ - if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && - !quoted && (token_strlen == 2 || token[2]==' ' || - token[2]=='\t')) { - was_unknown_rr_format = 1; - if((status=rrinternal_parse_unknown(strbuf, token, - token_len, rr, rr_len, &rr_cur_len, - pre_data_pos)) != 0) - return status; - } else if(token_strlen > 0 || quoted) { - if(rdftype == LDNS_RDF_TYPE_HIP) { - /* affix the HIT and PK fields, with a space */ - if(!sldns_affix_token(strbuf, token, - &token_len, "ed, &parens, - &pre_data_pos, delimiters, - rdftype, &token_strlen)) - break; - if(!sldns_affix_token(strbuf, token, - &token_len, "ed, &parens, - &pre_data_pos, delimiters, - rdftype, &token_strlen)) - break; - } else if(rdftype == LDNS_RDF_TYPE_INT16_DATA && - strcmp(token, "0")!=0) { - /* affix len and b64 fields */ - if(!sldns_affix_token(strbuf, token, - &token_len, "ed, &parens, - &pre_data_pos, delimiters, - rdftype, &token_strlen)) - break; - } - - /* normal RR */ - if((status=rrinternal_parse_rdf(strbuf, token, - token_len, rr, *rr_len, &rr_cur_len, rdftype, - rr_type, r_cnt, r_max, dname_len, origin, - origin_len)) != 0) { - return status; - } - } - } - if(!was_unknown_rr_format && r_cnt+1 < r_min) { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, - sldns_buffer_position(strbuf)); - } - while(parens != 0) { - /* read remainder, must be "" */ - if(sldns_bget_token_par(strbuf, token, "\n", token_len, - &parens, " \t") == -1) { - if(parens != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, - sldns_buffer_position(strbuf)); - break; - } - if(strcmp(token, "") != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, - sldns_buffer_position(strbuf)); - } - /* write rdata length */ - sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10)); - *rr_len = rr_cur_len; - /* SVCB/HTTPS handling */ - if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) { - size_t rdata_len = rr_cur_len - dname_len - 10; - uint8_t *rdata = rr+dname_len + 10; - - /* skip 1st rdata field SvcPriority (uint16_t) */ - if (rdata_len < sizeof(uint16_t)) - return LDNS_WIREPARSE_ERR_OK; - - rdata_len -= sizeof(uint16_t); - rdata += sizeof(uint16_t); - - /* skip 2nd rdata field dname */ - while (rdata_len && *rdata != 0) { - uint8_t label_len; - - if (*rdata & 0xC0) - return LDNS_WIREPARSE_ERR_OK; - - label_len = *rdata + 1; - if (rdata_len < label_len) - return LDNS_WIREPARSE_ERR_OK; - - rdata_len -= label_len; - rdata += label_len; - } - /* The root label is one more character, so smaller - * than 1 + 1 means no Svcparam Keys */ - if (rdata_len < 2 || *rdata != 0) - return LDNS_WIREPARSE_ERR_OK; - - rdata_len -= 1; - rdata += 1; - return sldns_str2wire_check_svcbparams(rdata, rdata_len); - - } - return LDNS_WIREPARSE_ERR_OK; -} - -/* - * trailing spaces are allowed - * leading spaces are not allowed - * allow ttl to be optional - * class is optional too - * if ttl is missing, and default_ttl is 0, use DEF_TTL - * allow ttl to be written as 1d3h - * So the RR should look like. e.g. - * miek.nl. 3600 IN MX 10 elektron.atoom.net - * or - * miek.nl. 1h IN MX 10 elektron.atoom.net - * or - * miek.nl. IN MX 10 elektron.atoom.net - */ -static int -sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, - size_t* dname_len, uint32_t default_ttl, uint8_t* origin, - size_t origin_len, uint8_t* prev, size_t prev_len, int question) -{ - int status; - int not_there = 0; - char token[LDNS_MAX_RDFLEN+1]; - uint32_t ttl = 0; - uint16_t tp = 0, cl = 0; - size_t ddlen = 0; - - /* string in buffer */ - sldns_buffer strbuf; - sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); - if(!dname_len) dname_len = &ddlen; - - /* parse the owner */ - if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, - origin_len, prev, prev_len, token, sizeof(token))) != 0) - return status; - - /* parse the [ttl] [class] */ - if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), - ¬_there, &ttl, default_ttl)) != 0) - return status; - if((status=rrinternal_get_class(&strbuf, token, sizeof(token), - ¬_there, &cl)) != 0) - return status; - if((status=rrinternal_get_type(&strbuf, token, sizeof(token), - ¬_there, &tp)) != 0) - return status; - /* put ttl, class, type into the rr result */ - if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, - ttl, question)) != 0) - return status; - /* for a question-RR we are done, no rdata */ - if(question) { - *len = *dname_len + 4; - return LDNS_WIREPARSE_ERR_OK; - } - - /* rdata */ - if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), - rr, len, *dname_len, tp, origin, origin_len)) != 0) - return status; - - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, - size_t* dname_len, uint32_t default_ttl, uint8_t* origin, - size_t origin_len, uint8_t* prev, size_t prev_len) -{ - return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, - default_ttl, origin, origin_len, prev, prev_len, 0); -} - -int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, - size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, - size_t prev_len) -{ - return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, - 0, origin, origin_len, prev, prev_len, 1); -} - -uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+2) - return 0; - return sldns_read_uint16(rr+dname_len); -} - -uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+4) - return 0; - return sldns_read_uint16(rr+dname_len+2); -} - -uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+8) - return 0; - return sldns_read_uint32(rr+dname_len+4); -} - -uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+10) - return 0; - return sldns_read_uint16(rr+dname_len+8); -} - -uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+10) - return NULL; - return rr+dname_len+10; -} - -uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) -{ - if(len < dname_len+10) - return NULL; - return rr+dname_len+8; -} - -const char* sldns_get_errorstr_parse(int e) -{ - sldns_lookup_table *lt; - lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); - return lt?lt->name:"unknown error"; -} - -/* Strip whitespace from the start and the end of . */ -char * -sldns_strip_ws(char *line) -{ - char *s = line, *e; - - for (s = line; *s && isspace((unsigned char)*s); s++) - ; - for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) - ; - *e = 0; - return s; -} - -int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, - struct sldns_file_parse_state* parse_state) -{ - char line[LDNS_RR_BUF_SIZE+1]; - ssize_t size; - - /* read an entire line in from the file */ - if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, - LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) - == -1) { - /* if last line was empty, we are now at feof, which is not - * always a parse error (happens when for instance last line - * was a comment) - */ - return LDNS_WIREPARSE_ERR_SYNTAX; - } - - /* we can have the situation, where we've read ok, but still got - * no bytes to play with, in this case size is 0 */ - if(size == 0) { - if(*len > 0) - rr[0] = 0; - *len = 0; - *dname_len = 0; - return LDNS_WIREPARSE_ERR_OK; - } - - if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { - int s; - strlcpy((char*)rr, line, *len); - *len = 0; - *dname_len = 0; - if(!parse_state) return LDNS_WIREPARSE_ERR_OK; - parse_state->origin_len = sizeof(parse_state->origin); - s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), - parse_state->origin, &parse_state->origin_len); - if(s) parse_state->origin_len = 0; - return s; - } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { - const char* end = NULL; - int overflow = 0; - strlcpy((char*)rr, line, *len); - *len = 0; - *dname_len = 0; - if(!parse_state) return LDNS_WIREPARSE_ERR_OK; - parse_state->default_ttl = sldns_str2period( - sldns_strip_ws(line+5), &end, &overflow); - if(overflow) - return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; - } else if (strncmp(line, "$INCLUDE", 8) == 0) { - strlcpy((char*)rr, line, *len); - *len = 0; - *dname_len = 0; - return LDNS_WIREPARSE_ERR_INCLUDE; - } else if (strncmp(line, "$", 1) == 0) { - strlcpy((char*)rr, line, *len); - *len = 0; - *dname_len = 0; - return LDNS_WIREPARSE_ERR_INCLUDE; - } else { - int r = sldns_str2wire_rr_buf(line, rr, len, dname_len, - parse_state?parse_state->default_ttl:0, - (parse_state&&parse_state->origin_len)? - parse_state->origin:NULL, - parse_state?parse_state->origin_len:0, - (parse_state&&parse_state->prev_rr_len)? - parse_state->prev_rr:NULL, - parse_state?parse_state->prev_rr_len:0); - if(r == LDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 && - parse_state && - (*dname_len) <= sizeof(parse_state->prev_rr)) { - memmove(parse_state->prev_rr, rr, *dname_len); - parse_state->prev_rr_len = (*dname_len); - } - if(r == LDNS_WIREPARSE_ERR_OK && parse_state) { - parse_state->default_ttl = sldns_wirerr_get_ttl( - rr, *len, *dname_len); - } - return r; - } - return LDNS_WIREPARSE_ERR_OK; -} - -static int -sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len) -{ - char buf[64]; - char *endptr; - unsigned long int key_value; - - if (key_len >= 4 && key_len <= 8 && !strncmp(key, "key", 3)) { - memcpy(buf, key + 3, key_len - 3); - buf[key_len - 3] = 0; - key_value = strtoul(buf, &endptr, 10); - - if (endptr > buf /* digits seen */ - && *endptr == 0 /* no non-digit chars after digits */ - && key_value <= 65535) /* no overflow */ - return key_value; - - } else switch (key_len) { - case 3: - if (!strncmp(key, "ech", key_len)) - return SVCB_KEY_ECH; - break; - - case 4: - if (!strncmp(key, "alpn", key_len)) - return SVCB_KEY_ALPN; - if (!strncmp(key, "port", key_len)) - return SVCB_KEY_PORT; - break; - - case 7: - if (!strncmp(key, "dohpath", key_len)) - return SVCB_KEY_DOHPATH; - break; - - case 8: - if (!strncmp(key, "ipv4hint", key_len)) - return SVCB_KEY_IPV4HINT; - if (!strncmp(key, "ipv6hint", key_len)) - return SVCB_KEY_IPV6HINT; - break; - - case 9: - if (!strncmp(key, "mandatory", key_len)) - return SVCB_KEY_MANDATORY; - if (!strncmp(key, "echconfig", key_len)) - return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */ - break; - - case 15: - if (!strncmp(key, "no-default-alpn", key_len)) - return SVCB_KEY_NO_DEFAULT_ALPN; - break; - - default: - break; - } - - /* Although the returned value might be used by the caller, - * the parser has erred, so the zone will not be loaded. - */ - return -1; -} - -static int -sldns_str2wire_svcparam_port(const char* val, uint8_t* rd, size_t* rd_len) -{ - unsigned long int port; - char *endptr; - - if (*rd_len < 6) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - port = strtoul(val, &endptr, 10); - - if (endptr > val /* digits seen */ - && *endptr == 0 /* no non-digit chars after digits */ - && port <= 65535) { /* no overflow */ - - sldns_write_uint16(rd, SVCB_KEY_PORT); - sldns_write_uint16(rd + 2, sizeof(uint16_t)); - sldns_write_uint16(rd + 4, port); - *rd_len = 6; - - return LDNS_WIREPARSE_ERR_OK; - } - - return LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX; -} - -static int -sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len) -{ - size_t count; - char ip_str[INET_ADDRSTRLEN+1]; - char *next_ip_str; - size_t i; - - for (i = 0, count = 1; val[i]; i++) { - if (val[i] == ',') - count += 1; - if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { - return LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES; - } - } - - if (*rd_len < (LDNS_IP4ADDRLEN * count) + 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - /* count is number of comma's in val + 1; so the actual number of IPv4 - * addresses in val - */ - sldns_write_uint16(rd, SVCB_KEY_IPV4HINT); - sldns_write_uint16(rd + 2, LDNS_IP4ADDRLEN * count); - *rd_len = 4; - - while (count) { - if (!(next_ip_str = strchr(val, ','))) { - if (inet_pton(AF_INET, val, rd + *rd_len) != 1) - break; - *rd_len += LDNS_IP4ADDRLEN; - - assert(count == 1); - - } else if (next_ip_str - val >= (int)sizeof(ip_str)) - break; - - else { - memcpy(ip_str, val, next_ip_str - val); - ip_str[next_ip_str - val] = 0; - if (inet_pton(AF_INET, ip_str, rd + *rd_len) != 1) { - break; - } - *rd_len += LDNS_IP4ADDRLEN; - - val = next_ip_str + 1; - } - count--; - } - if (count) /* verify that we parsed all values */ - return LDNS_WIREPARSE_ERR_SYNTAX_IP4; - - return LDNS_WIREPARSE_ERR_OK; -} - -static int -sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len) -{ - size_t count; - char ip_str[INET6_ADDRSTRLEN+1]; - char *next_ip_str; - size_t i; - - for (i = 0, count = 1; val[i]; i++) { - if (val[i] == ',') - count += 1; - if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { - return LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES; - } - } - - if (*rd_len < (LDNS_IP6ADDRLEN * count) + 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - /* count is number of comma's in val + 1; so the actual number of IPv6 - * addresses in val - */ - sldns_write_uint16(rd, SVCB_KEY_IPV6HINT); - sldns_write_uint16(rd + 2, LDNS_IP6ADDRLEN * count); - *rd_len = 4; - - while (count) { - if (!(next_ip_str = strchr(val, ','))) { - if (inet_pton(AF_INET6, val, rd + *rd_len) != 1) - break; - *rd_len += LDNS_IP6ADDRLEN; - - assert(count == 1); - - } else if (next_ip_str - val >= (int)sizeof(ip_str)) - break; - - else { - memcpy(ip_str, val, next_ip_str - val); - ip_str[next_ip_str - val] = 0; - if (inet_pton(AF_INET6, ip_str, rd + *rd_len) != 1) { - break; - } - *rd_len += LDNS_IP6ADDRLEN; - - val = next_ip_str + 1; - } - count--; - } - if (count) /* verify that we parsed all values */ - return LDNS_WIREPARSE_ERR_SYNTAX_IP6; - - return LDNS_WIREPARSE_ERR_OK; -} - -/* compare function used for sorting uint16_t's */ -static int -sldns_network_uint16_cmp(const void *a, const void *b) -{ - return ((int)sldns_read_uint16(a)) - ((int)sldns_read_uint16(b)); -} - -static int -sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len) -{ - size_t i, count, val_len; - char* next_key; - - val_len = strlen(val); - - for (i = 0, count = 1; val[i]; i++) { - if (val[i] == ',') - count += 1; - if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { - return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS; - } - } - if (sizeof(uint16_t) * (count + 2) > *rd_len) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - sldns_write_uint16(rd, SVCB_KEY_MANDATORY); - sldns_write_uint16(rd + 2, sizeof(uint16_t) * count); - *rd_len = 4; - - while (1) { - int svcparamkey; - - if (!(next_key = strchr(val, ','))) { - svcparamkey = sldns_str2wire_svcparam_key_lookup(val, val_len); - - if (svcparamkey < 0) { - return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; - } - - sldns_write_uint16(rd + *rd_len, svcparamkey); - *rd_len += 2; - break; - } else { - svcparamkey = sldns_str2wire_svcparam_key_lookup(val, next_key - val); - - if (svcparamkey < 0) { - return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; - } - - sldns_write_uint16(rd + *rd_len, - svcparamkey); - *rd_len += 2; - } - - val_len -= next_key - val + 1; - val = next_key + 1; /* skip the comma */ - } - - /* In draft-ietf-dnsop-svcb-https-06 Section 7: - * - * "In wire format, the keys are represented by their numeric - * values in network byte order, concatenated in ascending order." - */ - qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); - - /* The code below revolves around semantic errors in the SVCParam set. - * So long as we do not distinguish between running Unbound as a primary - * or as a secondary, we default to secondary behavior and we ignore the - * semantic errors. */ -#ifdef SVCB_SEMANTIC_ERRORS - /* In draft-ietf-dnsop-svcb-https-06 Section 8 - * automatically mandatory MUST NOT appear in its own value-list - */ - if (sldns_read_uint16(rd + 4) == SVCB_KEY_MANDATORY) - return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY; - - /* Guarantee key uniqueness. After the sort we only need to - * compare neighbouring keys */ - if (count > 1) { - for (i = 0; i < count - 1; i++) { - uint8_t* current_pos = (rd + 4 + (sizeof(uint16_t) * i)); - uint16_t key = sldns_read_uint16(current_pos); - - if (key == sldns_read_uint16(current_pos + 2)) { - return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY; - } - } - } -#endif - return LDNS_WIREPARSE_ERR_OK; -} - -static int -sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len) -{ - uint8_t buffer[LDNS_MAX_RDFLEN]; - int wire_len; - - /* single 0 represents empty buffer */ - if(strcmp(val, "0") == 0) { - if (*rd_len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint16(rd, SVCB_KEY_ECH); - sldns_write_uint16(rd + 2, 0); - - return LDNS_WIREPARSE_ERR_OK; - } - - wire_len = sldns_b64_pton(val, buffer, LDNS_MAX_RDFLEN); - - if (wire_len <= 0) { - return LDNS_WIREPARSE_ERR_SYNTAX_B64; - } else if ((unsigned)wire_len + 4 > *rd_len) { - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - } else { - sldns_write_uint16(rd, SVCB_KEY_ECH); - sldns_write_uint16(rd + 2, wire_len); - memcpy(rd + 4, buffer, wire_len); - *rd_len = 4 + wire_len; - - return LDNS_WIREPARSE_ERR_OK; - } -} - -static const char* -sldns_str2wire_svcbparam_parse_next_unescaped_comma(const char *val) -{ - while (*val) { - /* Only return when the comma is not escaped*/ - if (*val == '\\'){ - ++val; - if (!*val) - break; - } else if (*val == ',') - return val; - - val++; - } - return NULL; -} - -/* The source is already properly unescaped, this double unescaping is purely to allow for - * comma's in comma separated alpn lists. - * - * In draft-ietf-dnsop-svcb-https-06 Section 7: - * To enable simpler parsing, this SvcParamValue MUST NOT contain escape sequences. - */ -static size_t -sldns_str2wire_svcbparam_parse_copy_unescaped(uint8_t *dst, - const char *src, size_t len) -{ - uint8_t *orig_dst = dst; - - while (len) { - if (*src == '\\') { - src++; - len--; - if (!len) - break; - } - *dst++ = *src++; - len--; - } - return (size_t)(dst - orig_dst); -} - -static int -sldns_str2wire_svcbparam_alpn_value(const char* val, - uint8_t* rd, size_t* rd_len) -{ - uint8_t unescaped_dst[LDNS_MAX_RDFLEN]; - uint8_t *dst = unescaped_dst; - const char *next_str; - size_t str_len; - size_t dst_len; - size_t val_len; - - val_len = strlen(val); - - if (val_len > sizeof(unescaped_dst)) { - return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; - } - while (val_len) { - size_t key_len; - - str_len = (next_str = sldns_str2wire_svcbparam_parse_next_unescaped_comma(val)) - ? (size_t)(next_str - val) : val_len; - - if (str_len > 255) { - return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; - } - - key_len = sldns_str2wire_svcbparam_parse_copy_unescaped(dst + 1, val, str_len); - *dst++ = key_len; - dst += key_len; - - if (!next_str) - break; - - /* skip the comma in the next iteration */ - val_len -= next_str - val + 1; - val = next_str + 1; - } - dst_len = dst - unescaped_dst; - if (*rd_len < 4 + dst_len) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint16(rd, SVCB_KEY_ALPN); - sldns_write_uint16(rd + 2, dst_len); - memcpy(rd + 4, unescaped_dst, dst_len); - *rd_len = 4 + dst_len; - - return LDNS_WIREPARSE_ERR_OK; -} - -static int -sldns_str2wire_svcbparam_dohpath_value(const char* val, - uint8_t* rd, size_t* rd_len) -{ - size_t val_len; - - /* RFC6570#section-2.1 - * "The characters outside of expressions in a URI Template string are - * intended to be copied literally" - * Practically this means we do not have to look for "double escapes" - * like in the alpn value list. - */ - - val_len = strlen(val); - - if (*rd_len < 4 + val_len) { - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - } - - sldns_write_uint16(rd, SVCB_KEY_DOHPATH); - sldns_write_uint16(rd + 2, val_len); - memcpy(rd + 4, val, val_len); - *rd_len = 4 + val_len; - - return LDNS_WIREPARSE_ERR_OK; -} - -static int -sldns_str2wire_svcparam_value(const char *key, size_t key_len, - const char *val, uint8_t* rd, size_t* rd_len) -{ - size_t str_len; - int svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len); - - if (svcparamkey < 0) { - return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; - } - - /* key without value */ - if (val == NULL) { - switch (svcparamkey) { -#ifdef SVCB_SEMANTIC_ERRORS - case SVCB_KEY_MANDATORY: - case SVCB_KEY_ALPN: - case SVCB_KEY_PORT: - case SVCB_KEY_IPV4HINT: - case SVCB_KEY_IPV6HINT: - case SVCB_KEY_DOHPATH: - return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM; -#endif - default: - if (*rd_len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint16(rd, svcparamkey); - sldns_write_uint16(rd + 2, 0); - *rd_len = 4; - - return LDNS_WIREPARSE_ERR_OK; - } - } - - /* value is non-empty */ - switch (svcparamkey) { - case SVCB_KEY_PORT: - return sldns_str2wire_svcparam_port(val, rd, rd_len); - case SVCB_KEY_IPV4HINT: - return sldns_str2wire_svcbparam_ipv4hint(val, rd, rd_len); - case SVCB_KEY_IPV6HINT: - return sldns_str2wire_svcbparam_ipv6hint(val, rd, rd_len); - case SVCB_KEY_MANDATORY: - return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len); -#ifdef SVCB_SEMANTIC_ERRORS - case SVCB_KEY_NO_DEFAULT_ALPN: - return LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE; -#endif - case SVCB_KEY_ECH: - return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); - case SVCB_KEY_ALPN: - return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); - case SVCB_KEY_DOHPATH: - return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len); - default: - str_len = strlen(val); - if (*rd_len < 4 + str_len) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint16(rd, svcparamkey); - sldns_write_uint16(rd + 2, str_len); - memcpy(rd + 4, val, str_len); - *rd_len = 4 + str_len; - - return LDNS_WIREPARSE_ERR_OK; - } - - return LDNS_WIREPARSE_ERR_GENERAL; -} - -static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) -{ - const char* eq_pos; - char unescaped_val[LDNS_MAX_RDFLEN]; - char* val_out = unescaped_val; - const char* val_in; - - eq_pos = strchr(str, '='); - - /* case: key=value */ - if (eq_pos != NULL && eq_pos[1]) { - val_in = eq_pos + 1; - - /* unescape characters and "" blocks */ - if (*val_in == '"') { - val_in++; - while (*val_in != '"' - && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) - && sldns_parse_char( (uint8_t*) val_out, &val_in)) { - val_out++; - } - } else { - while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) - && sldns_parse_char( (uint8_t*) val_out, &val_in)) { - val_out++; - } - } - *val_out = 0; - - return sldns_str2wire_svcparam_value(str, eq_pos - str, - unescaped_val[0] ? unescaped_val : NULL, rd, rd_len); - } - /* case: key= */ - else if (eq_pos != NULL && !(eq_pos[1])) { - return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len); - } - /* case: key */ - else { - return sldns_str2wire_svcparam_value(str, strlen(str), NULL, rd, rd_len); - } -} - -int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, - sldns_rdf_type rdftype) -{ - switch (rdftype) { - case LDNS_RDF_TYPE_DNAME: - return sldns_str2wire_dname_buf(str, rd, len); - case LDNS_RDF_TYPE_INT8: - return sldns_str2wire_int8_buf(str, rd, len); - case LDNS_RDF_TYPE_INT16: - return sldns_str2wire_int16_buf(str, rd, len); - case LDNS_RDF_TYPE_INT32: - return sldns_str2wire_int32_buf(str, rd, len); - case LDNS_RDF_TYPE_A: - return sldns_str2wire_a_buf(str, rd, len); - case LDNS_RDF_TYPE_AAAA: - return sldns_str2wire_aaaa_buf(str, rd, len); - case LDNS_RDF_TYPE_STR: - return sldns_str2wire_str_buf(str, rd, len); - case LDNS_RDF_TYPE_APL: - return sldns_str2wire_apl_buf(str, rd, len); - case LDNS_RDF_TYPE_B64: - return sldns_str2wire_b64_buf(str, rd, len); - case LDNS_RDF_TYPE_B32_EXT: - return sldns_str2wire_b32_ext_buf(str, rd, len); - case LDNS_RDF_TYPE_HEX: - return sldns_str2wire_hex_buf(str, rd, len); - case LDNS_RDF_TYPE_NSEC: - return sldns_str2wire_nsec_buf(str, rd, len); - case LDNS_RDF_TYPE_TYPE: - return sldns_str2wire_type_buf(str, rd, len); - case LDNS_RDF_TYPE_CLASS: - return sldns_str2wire_class_buf(str, rd, len); - case LDNS_RDF_TYPE_CERT_ALG: - return sldns_str2wire_cert_alg_buf(str, rd, len); - case LDNS_RDF_TYPE_ALG: - return sldns_str2wire_alg_buf(str, rd, len); - case LDNS_RDF_TYPE_TIME: - return sldns_str2wire_time_buf(str, rd, len); - case LDNS_RDF_TYPE_PERIOD: - return sldns_str2wire_period_buf(str, rd, len); - case LDNS_RDF_TYPE_TSIGTIME: - return sldns_str2wire_tsigtime_buf(str, rd, len); - case LDNS_RDF_TYPE_LOC: - return sldns_str2wire_loc_buf(str, rd, len); - case LDNS_RDF_TYPE_WKS: - return sldns_str2wire_wks_buf(str, rd, len); - case LDNS_RDF_TYPE_NSAP: - return sldns_str2wire_nsap_buf(str, rd, len); - case LDNS_RDF_TYPE_ATMA: - return sldns_str2wire_atma_buf(str, rd, len); - case LDNS_RDF_TYPE_IPSECKEY: - return sldns_str2wire_ipseckey_buf(str, rd, len); - case LDNS_RDF_TYPE_NSEC3_SALT: - return sldns_str2wire_nsec3_salt_buf(str, rd, len); - case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: - return sldns_str2wire_b32_ext_buf(str, rd, len); - case LDNS_RDF_TYPE_ILNP64: - return sldns_str2wire_ilnp64_buf(str, rd, len); - case LDNS_RDF_TYPE_EUI48: - return sldns_str2wire_eui48_buf(str, rd, len); - case LDNS_RDF_TYPE_EUI64: - return sldns_str2wire_eui64_buf(str, rd, len); - case LDNS_RDF_TYPE_TAG: - return sldns_str2wire_tag_buf(str, rd, len); - case LDNS_RDF_TYPE_LONG_STR: - return sldns_str2wire_long_str_buf(str, rd, len); - case LDNS_RDF_TYPE_TSIGERROR: - return sldns_str2wire_tsigerror_buf(str, rd, len); - case LDNS_RDF_TYPE_HIP: - return sldns_str2wire_hip_buf(str, rd, len); - case LDNS_RDF_TYPE_INT16_DATA: - return sldns_str2wire_int16_data_buf(str, rd, len); - case LDNS_RDF_TYPE_SVCPARAM: - return sldns_str2wire_svcparam_buf(str, rd, len); - case LDNS_RDF_TYPE_UNKNOWN: - case LDNS_RDF_TYPE_SERVICE: - return LDNS_WIREPARSE_ERR_NOT_IMPL; - case LDNS_RDF_TYPE_NONE: - default: - break; - } - return LDNS_WIREPARSE_ERR_GENERAL; -} - -int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* end; - uint8_t r = (uint8_t)strtol((char*)str, &end, 10); - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); - if(*len < 1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[0] = r; - *len = 1; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* end; - uint16_t r = (uint16_t)strtol((char*)str, &end, 10); - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); - if(*len < 2) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint16(rd, r); - *len = 2; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* end; - uint32_t r; - errno = 0; /* must set to zero before call, - note race condition on errno */ - if(*str == '-') - r = (uint32_t)strtol((char*)str, &end, 10); - else r = (uint32_t)strtoul((char*)str, &end, 10); - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); - if(errno == ERANGE) - return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; - if(*len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint32(rd, r); - *len = 4; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) -{ - struct in_addr address; - if(inet_pton(AF_INET, (char*)str, &address) != 1) - return LDNS_WIREPARSE_ERR_SYNTAX_IP4; - if(*len < sizeof(address)) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - memmove(rd, &address, sizeof(address)); - *len = sizeof(address); - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) -{ -#ifdef AF_INET6 - uint8_t address[LDNS_IP6ADDRLEN + 1]; - if(inet_pton(AF_INET6, (char*)str, address) != 1) - return LDNS_WIREPARSE_ERR_SYNTAX_IP6; - if(*len < LDNS_IP6ADDRLEN) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - memmove(rd, address, LDNS_IP6ADDRLEN); - *len = LDNS_IP6ADDRLEN; - return LDNS_WIREPARSE_ERR_OK; -#else - return LDNS_WIREPARSE_ERR_NOT_IMPL; -#endif -} - -int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) -{ - uint8_t ch = 0; - size_t sl = 0; - const char* s = str; - /* skip length byte */ - if(*len < 1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - /* read characters */ - while(sldns_parse_char(&ch, &s)) { - if(sl >= 255) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); - if(*len < sl+2) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - s-str); - rd[++sl] = ch; - } - if(!s) - return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; - rd[0] = (uint8_t)sl; - *len = sl+1; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char *my_str = str; - - char my_ip_str[64]; - size_t ip_str_len; - - uint16_t family; - int negation; - size_t adflength = 0; - uint8_t data[16+4]; - uint8_t prefix; - size_t i; - - if(*my_str == '\0') { - /* empty APL element, no data, no string */ - *len = 0; - return LDNS_WIREPARSE_ERR_OK; - } - - /* [!]afi:address/prefix */ - if (strlen(my_str) < 2 - || strchr(my_str, ':') == NULL - || strchr(my_str, '/') == NULL - || strchr(my_str, ':') > strchr(my_str, '/')) { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - if (my_str[0] == '!') { - negation = 1; - my_str += 1; - } else { - negation = 0; - } - - family = (uint16_t) atoi(my_str); - - my_str = strchr(my_str, ':') + 1; - - /* need ip addr and only ip addr for inet_pton */ - ip_str_len = (size_t) (strchr(my_str, '/') - my_str); - if(ip_str_len+1 > sizeof(my_ip_str)) - return LDNS_WIREPARSE_ERR_INVALID_STR; - (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); - my_ip_str[ip_str_len] = 0; - - if (family == 1) { - /* ipv4 */ - if(inet_pton(AF_INET, my_ip_str, data+4) == 0) - return LDNS_WIREPARSE_ERR_INVALID_STR; - for (i = 0; i < 4; i++) { - if (data[i+4] != 0) { - adflength = i + 1; - } - } - } else if (family == 2) { - /* ipv6 */ - if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) - return LDNS_WIREPARSE_ERR_INVALID_STR; - for (i = 0; i < 16; i++) { - if (data[i+4] != 0) { - adflength = i + 1; - } - } - } else { - /* unknown family */ - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - my_str = strchr(my_str, '/') + 1; - prefix = (uint8_t) atoi(my_str); - - sldns_write_uint16(data, family); - data[2] = prefix; - data[3] = (uint8_t)adflength; - if (negation) { - /* set bit 1 of byte 3 */ - data[3] = data[3] | 0x80; - } - - if(*len < 4+adflength) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - memmove(rd, data, 4+adflength); - *len = 4+adflength; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) -{ - size_t sz = sldns_b64_pton_calculate_size(strlen(str)); - int n; - if(strcmp(str, "0") == 0) { - *len = 0; - return LDNS_WIREPARSE_ERR_OK; - } - if(*len < sz) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - n = sldns_b64_pton(str, rd, *len); - if(n < 0) - return LDNS_WIREPARSE_ERR_SYNTAX_B64; - *len = (size_t)n; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) -{ - size_t slen = strlen(str); - size_t sz = sldns_b32_pton_calculate_size(slen); - int n; - if(*len < 1+sz) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[0] = (uint8_t)sz; - n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); - if(n < 0) - return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; - *len = (size_t)n+1; - return LDNS_WIREPARSE_ERR_OK; -} - -/** see if the string ends, or ends in whitespace */ -static int -sldns_is_last_of_string(const char* str) -{ - if(*str == 0) return 1; - while(isspace((unsigned char)*str)) - str++; - if(*str == 0) return 1; - return 0; -} - -int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char* s = str; - size_t dlen = 0; /* number of hexdigits parsed */ - while(*s) { - if(isspace((unsigned char)*s)) { - s++; - continue; - } - if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) { - *len = 0; - return LDNS_WIREPARSE_ERR_OK; - } - if(!isxdigit((unsigned char)*s)) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - if(*len < dlen/2 + 1) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - s-str); - if((dlen&1)==0) - rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; - else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); - dlen++; - } - if((dlen&1)!=0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - *len = dlen/2; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char *delim = "\n\t "; - char token[64]; /* for a type name */ - size_t type_count = 0; - int block; - size_t used = 0; - uint16_t maxtype = 0; - uint8_t typebits[8192]; /* 65536 bits */ - uint8_t window_in_use[256]; - - /* string in buffer */ - sldns_buffer strbuf; - sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); - - /* parse the types */ - memset(typebits, 0, sizeof(typebits)); - memset(window_in_use, 0, sizeof(window_in_use)); - while(sldns_buffer_remaining(&strbuf) > 0 && - sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { - uint16_t t = sldns_get_rr_type_by_name(token); - if(token[0] == 0) - continue; - if(t == 0 && strcmp(token, "TYPE0") != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, - sldns_buffer_position(&strbuf)); - typebits[t/8] |= (0x80>>(t%8)); - window_in_use[t/256] = 1; - type_count++; - if(t > maxtype) maxtype = t; - } - - /* empty NSEC bitmap */ - if(type_count == 0) { - *len = 0; - return LDNS_WIREPARSE_ERR_OK; - } - - /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, - * block is 0-255 upper octet of types, length if 0-32. */ - for(block = 0; block <= (int)maxtype/256; block++) { - int i, blocklen = 0; - if(!window_in_use[block]) - continue; - for(i=0; i<32; i++) { - if(typebits[block*32+i] != 0) - blocklen = i+1; - } - if(blocklen == 0) - continue; /* empty window should have been !in_use */ - if(used+blocklen+2 > *len) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[used+0] = (uint8_t)block; - rd[used+1] = (uint8_t)blocklen; - for(i=0; iid); - } else { - int s = sldns_str2wire_int16_buf(str, rd, len); - if(s) return s; - if(sldns_read_uint16(rd) == 0) - return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; - } - *len = 2; - return LDNS_WIREPARSE_ERR_OK; -} - -/* An alg field can either be specified as a 8 bits number - * or by its symbolic name. Handle both */ -int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) -{ - sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); - if(*len < 1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - if(lt) { - rd[0] = (uint8_t)lt->id; - *len = 1; - } else { - /* try as-is (a number) */ - return sldns_str2wire_int8_buf(str, rd, len); - } - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len) -{ - sldns_lookup_table *lt = sldns_lookup_by_name(sldns_tsig_errors, str); - if(*len < 2) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - if(lt) { - sldns_write_uint16(rd, (uint16_t)lt->id); - *len = 2; - } else { - /* try as-is (a number) */ - return sldns_str2wire_int16_buf(str, rd, len); - } - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) -{ - /* convert a time YYYYDDMMHHMMSS to wireformat */ - struct tm tm; - if(*len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - /* Try to scan the time... */ - memset(&tm, 0, sizeof(tm)); - if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, - &tm.tm_min, &tm.tm_sec) == 6) { - tm.tm_year -= 1900; - tm.tm_mon--; - /* Check values */ - if (tm.tm_year < 70) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - if (tm.tm_mon < 0 || tm.tm_mon > 11) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - if (tm.tm_mday < 1 || tm.tm_mday > 31) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - if (tm.tm_hour < 0 || tm.tm_hour > 23) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - if (tm.tm_min < 0 || tm.tm_min > 59) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - if (tm.tm_sec < 0 || tm.tm_sec > 59) - return LDNS_WIREPARSE_ERR_SYNTAX_TIME; - - sldns_write_uint32(rd, (uint32_t)sldns_mktime_from_utc(&tm)); - } else { - /* handle it as 32 bits timestamp */ - char *end; - uint32_t l = (uint32_t)strtol((char*)str, &end, 10); - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, - end-(char*)str); - sldns_write_uint32(rd, l); - } - *len = 4; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* end; - uint64_t t = (uint64_t)strtol((char*)str, &end, 10); - uint16_t high; - uint32_t low; - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, end-str); - if(*len < 6) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - high = (uint16_t)(t>>32); - low = (uint32_t)(t); - sldns_write_uint16(rd, high); - sldns_write_uint32(rd+2, low); - *len = 6; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char* end; - int overflow; - uint32_t p = sldns_str2period(str, &end, &overflow); - if(*end != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); - if(overflow) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, - end-str); - if(*len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - sldns_write_uint32(rd, p); - *len = 4; - return LDNS_WIREPARSE_ERR_OK; -} - -/** read "[.][mM]" into mantissa exponent format for LOC type */ -static int -loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) -{ - uint32_t meters = 0, cm = 0, val; - char* cm_endstr; - while (isblank((unsigned char)*my_str)) { - my_str++; - } - meters = (uint32_t)strtol(my_str, &my_str, 10); - if (*my_str == '.') { - my_str++; - cm = (uint32_t)strtol(my_str, &cm_endstr, 10); - if(cm_endstr == my_str + 1) - cm *= 10; - my_str = cm_endstr; - } - if (meters >= 1) { - *e = 2; - val = meters; - } else { - *e = 0; - val = cm; - } - while(val >= 10) { - (*e)++; - val /= 10; - } - *m = (uint8_t)val; - - if (*e > 9) - return 0; - if (*my_str == 'm' || *my_str == 'M') { - my_str++; - } - *endstr = my_str; - return 1; -} - -int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) -{ - uint32_t latitude = 0; - uint32_t longitude = 0; - uint32_t altitude = 0; - - uint32_t equator = (uint32_t)1<<31; /* 2**31 */ - - /* only support version 0 */ - uint32_t h = 0; - uint32_t m = 0; - uint8_t size_b = 1, size_e = 2; - uint8_t horiz_pre_b = 1, horiz_pre_e = 6; - uint8_t vert_pre_b = 1, vert_pre_e = 3; - - double s = 0.0; - int northerness; - int easterness; - - char *my_str = (char *) str; - - if (isdigit((unsigned char) *my_str)) { - h = (uint32_t) strtol(my_str, &my_str, 10); - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - while (isblank((unsigned char) *my_str)) { - my_str++; - } - - if (isdigit((unsigned char) *my_str)) { - m = (uint32_t) strtol(my_str, &my_str, 10); - } else if (*my_str == 'N' || *my_str == 'S') { - goto north; - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - while (isblank((unsigned char) *my_str)) { - my_str++; - } - - if (isdigit((unsigned char) *my_str)) { - s = strtod(my_str, &my_str); - } - - /* skip blanks before northerness */ - while (isblank((unsigned char) *my_str)) { - my_str++; - } - -north: - if (*my_str == 'N') { - northerness = 1; - } else if (*my_str == 'S') { - northerness = 0; - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - my_str++; - - /* store number */ - s = 1000.0 * s; - /* add a little to make floor in conversion a round */ - s += 0.0005; - latitude = (uint32_t) s; - latitude += 1000 * 60 * m; - latitude += 1000 * 60 * 60 * h; - if (northerness) { - latitude = equator + latitude; - } else { - latitude = equator - latitude; - } - while (isblank((unsigned char)*my_str)) { - my_str++; - } - - if (isdigit((unsigned char) *my_str)) { - h = (uint32_t) strtol(my_str, &my_str, 10); - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - while (isblank((unsigned char) *my_str)) { - my_str++; - } - - if (isdigit((unsigned char) *my_str)) { - m = (uint32_t) strtol(my_str, &my_str, 10); - } else if (*my_str == 'E' || *my_str == 'W') { - goto east; - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - while (isblank((unsigned char)*my_str)) { - my_str++; - } - - if (isdigit((unsigned char) *my_str)) { - s = strtod(my_str, &my_str); - } - - /* skip blanks before easterness */ - while (isblank((unsigned char)*my_str)) { - my_str++; - } - -east: - if (*my_str == 'E') { - easterness = 1; - } else if (*my_str == 'W') { - easterness = 0; - } else { - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - my_str++; - - /* store number */ - s *= 1000.0; - /* add a little to make floor in conversion a round */ - s += 0.0005; - longitude = (uint32_t) s; - longitude += 1000 * 60 * m; - longitude += 1000 * 60 * 60 * h; - - if (easterness) { - longitude += equator; - } else { - longitude = equator - longitude; - } - - altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + - 10000000.0 + 0.5); - if (*my_str == 'm' || *my_str == 'M') { - my_str++; - } - - if (strlen(my_str) > 0) { - if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - if (strlen(my_str) > 0) { - if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - if (strlen(my_str) > 0) { - if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) - return LDNS_WIREPARSE_ERR_INVALID_STR; - } - - if(*len < 16) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[0] = 0; - rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); - rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); - rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); - sldns_write_uint32(rd + 4, latitude); - sldns_write_uint32(rd + 8, longitude); - sldns_write_uint32(rd + 12, altitude); - *len = 16; - return LDNS_WIREPARSE_ERR_OK; -} - -static void -ldns_tolower_str(char* s) -{ - if(s) { - while(*s) { - *s = (char)tolower((unsigned char)*s); - s++; - } - } -} - -int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) -{ - int rd_len = 1; - int have_proto = 0; - char token[50], proto_str[50]; - sldns_buffer strbuf; - sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); - proto_str[0]=0; - - /* check we have one byte for proto */ - if(*len < 1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { - ldns_tolower_str(token); - if(!have_proto) { - struct protoent *p = getprotobyname(token); - have_proto = 1; - if(p) rd[0] = (uint8_t)p->p_proto; - else if(strcasecmp(token, "tcp")==0) rd[0]=6; - else if(strcasecmp(token, "udp")==0) rd[0]=17; - else rd[0] = (uint8_t)atoi(token); - (void)strlcpy(proto_str, token, sizeof(proto_str)); - } else { - int serv_port; - struct servent *serv = getservbyname(token, proto_str); - if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); - else if(strcasecmp(token, "domain")==0) serv_port=53; - else { - serv_port = atoi(token); - if(serv_port == 0 && strcmp(token, "0") != 0) { -#ifdef HAVE_ENDSERVENT - endservent(); -#endif -#ifdef HAVE_ENDPROTOENT - endprotoent(); -#endif - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, - sldns_buffer_position(&strbuf)); - } - if(serv_port < 0 || serv_port > 65535) { -#ifdef HAVE_ENDSERVENT - endservent(); -#endif -#ifdef HAVE_ENDPROTOENT - endprotoent(); -#endif - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, - sldns_buffer_position(&strbuf)); - } - } - if(rd_len < 1+serv_port/8+1) { - /* bitmap is larger, init new bytes at 0 */ - if(*len < 1+(size_t)serv_port/8+1) { -#ifdef HAVE_ENDSERVENT - endservent(); -#endif -#ifdef HAVE_ENDPROTOENT - endprotoent(); -#endif - return RET_ERR( - LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(&strbuf)); - } - memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); - rd_len = 1+serv_port/8+1; - } - rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); - } - } - *len = (size_t)rd_len; - -#ifdef HAVE_ENDSERVENT - endservent(); -#endif -#ifdef HAVE_ENDPROTOENT - endprotoent(); -#endif - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char* s = str; - size_t slen; - size_t dlen = 0; /* number of hexdigits parsed */ - - /* just a hex string with optional dots? */ - if (s[0] != '0' || s[1] != 'x') - return LDNS_WIREPARSE_ERR_INVALID_STR; - s += 2; - slen = strlen(s); - if(slen > LDNS_MAX_RDFLEN*2) - return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; - while(*s) { - if(isspace((unsigned char)*s) || *s == '.') { - s++; - continue; - } - if(!isxdigit((unsigned char)*s)) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - if(*len < dlen/2 + 1) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - s-str); - if((dlen&1)==0) - rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; - else rd[dlen/2] += sldns_hexdigit_to_int(*s++); - dlen++; - } - if((dlen&1)!=0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - *len = dlen/2; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) -{ - const char* s = str; - size_t slen = strlen(str); - size_t dlen = 0; /* number of hexdigits parsed */ - - /* just a hex string with optional dots? */ - /* notimpl e.164 format */ - if(slen > LDNS_MAX_RDFLEN*2) - return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; - while(*s) { - if(isspace((unsigned char)*s) || *s == '.') { - s++; - continue; - } - if(!isxdigit((unsigned char)*s)) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - if(*len < dlen/2 + 1) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - s-str); - if((dlen&1)==0) - rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; - else rd[dlen/2] += sldns_hexdigit_to_int(*s++); - dlen++; - } - if((dlen&1)!=0) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); - *len = dlen/2; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) -{ - size_t gwlen = 0, keylen = 0; - int s; - uint8_t gwtype; - char token[512]; - sldns_buffer strbuf; - sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); - - if(*len < 3) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - /* precedence */ - if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - rd[0] = (uint8_t)atoi(token); - /* gateway_type */ - if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - rd[1] = (uint8_t)atoi(token); - gwtype = rd[1]; - /* algorithm */ - if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - rd[2] = (uint8_t)atoi(token); - - /* gateway */ - if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - if(gwtype == 0) { - /* NOGATEWAY */ - if(strcmp(token, ".") != 0) - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - gwlen = 0; - } else if(gwtype == 1) { - /* IP4 */ - gwlen = *len - 3; - s = sldns_str2wire_a_buf(token, rd+3, &gwlen); - if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); - } else if(gwtype == 2) { - /* IP6 */ - gwlen = *len - 3; - s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); - if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); - } else if(gwtype == 3) { - /* DNAME */ - gwlen = *len - 3; - s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); - if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); - } else { - /* unknown gateway type */ - return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, - sldns_buffer_position(&strbuf)); - } - /* double check for size */ - if(*len < 3 + gwlen) - return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, - sldns_buffer_position(&strbuf)); - - /* publickey in remainder of strbuf */ - keylen = *len - 3 - gwlen; - s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), - rd+3+gwlen, &keylen); - if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); - - *len = 3 + gwlen + keylen; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) -{ - int i, salt_length_str = (int)strlen(str); - if (salt_length_str == 1 && str[0] == '-') { - salt_length_str = 0; - } else if (salt_length_str % 2 != 0) { - return LDNS_WIREPARSE_ERR_SYNTAX_HEX; - } - if (salt_length_str > 512) - return LDNS_WIREPARSE_ERR_SYNTAX_HEX; - if(*len < 1+(size_t)salt_length_str / 2) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[0] = (uint8_t) (salt_length_str / 2); - for (i = 0; i < salt_length_str; i += 2) { - if (isxdigit((unsigned char)str[i]) && - isxdigit((unsigned char)str[i+1])) { - rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 - + sldns_hexdigit_to_int(str[i+1])); - } else { - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); - } - } - *len = 1 + (size_t)rd[0]; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) -{ - unsigned int a, b, c, d; - uint16_t shorts[4]; - int l; - if(*len < sizeof(shorts)) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || - l != (int)strlen(str) || /* more data to read */ - strpbrk(str, "+-") /* signed hexes */ - ) - return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; - shorts[0] = htons(a); - shorts[1] = htons(b); - shorts[2] = htons(c); - shorts[3] = htons(d); - memmove(rd, &shorts, sizeof(shorts)); - *len = sizeof(shorts); - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) -{ - unsigned int a, b, c, d, e, f; - int l; - - if(*len < 6) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", - &a, &b, &c, &d, &e, &f, &l) != 6 || - l != (int)strlen(str)) - return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; - rd[0] = a; - rd[1] = b; - rd[2] = c; - rd[3] = d; - rd[4] = e; - rd[5] = f; - *len = 6; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) -{ - unsigned int a, b, c, d, e, f, g, h; - int l; - - if(*len < 8) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", - &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || - l != (int)strlen(str)) - return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; - rd[0] = a; - rd[1] = b; - rd[2] = c; - rd[3] = d; - rd[4] = e; - rd[5] = f; - rd[6] = g; - rd[7] = h; - *len = 8; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) -{ - size_t slen = strlen(str); - const char* ptr; - - if (slen > 255) - return LDNS_WIREPARSE_ERR_SYNTAX_TAG; - if(*len < slen+1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - for (ptr = str; *ptr; ptr++) { - if(!isalnum((unsigned char)*ptr)) - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); - } - rd[0] = (uint8_t)slen; - memmove(rd+1, str, slen); - *len = slen+1; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) -{ - uint8_t ch = 0; - const char* pstr = str; - size_t length = 0; - - /* Fill data with parsed bytes */ - while (sldns_parse_char(&ch, &pstr)) { - if(*len < length+1) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - rd[length++] = ch; - } - if(!pstr) - return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; - *len = length; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* s, *end; - int e; - size_t hitlen, pklen = 0; - /* presentation format: - * pk-algo HIThex pubkeybase64 - * wireformat: - * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ - if(*len < 4) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - - /* read PK algorithm */ - rd[1] = (uint8_t)strtol((char*)str, &s, 10); - if(*s != ' ') - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); - s++; - while(*s == ' ') - s++; - - /* read HIT hex tag */ - /* zero terminate the tag (replace later) */ - end = strchr(s, ' '); - if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); - *end = 0; - hitlen = *len - 4; - if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { - *end = ' '; - return RET_ERR_SHIFT(e, s-(char*)str); - } - if(hitlen > 255) { - *end = ' '; - return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); - } - rd[0] = (uint8_t)hitlen; - *end = ' '; - s = end+1; - - /* read pubkey base64 sequence */ - pklen = *len - 4 - hitlen; - if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) - return RET_ERR_SHIFT(e, s-(char*)str); - if(pklen > 65535) - return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); - sldns_write_uint16(rd+2, (uint16_t)pklen); - - *len = 4 + hitlen + pklen; - return LDNS_WIREPARSE_ERR_OK; -} - -int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) -{ - char* s; - int n; - n = strtol(str, &s, 10); - if(n < 0) /* negative number not allowed */ - return LDNS_WIREPARSE_ERR_SYNTAX; - if(*len < ((size_t)n)+2) - return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; - if(n > 65535) - return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; - - if(n == 0) { - sldns_write_uint16(rd, 0); - *len = 2; - return LDNS_WIREPARSE_ERR_OK; - } - if(*s != ' ') - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); - s++; - while(*s == ' ') - s++; - - n = sldns_b64_pton(s, rd+2, (*len)-2); - if(n < 0) - return LDNS_WIREPARSE_ERR_SYNTAX_B64; - sldns_write_uint16(rd, (uint16_t)n); - *len = ((size_t)n)+2; - return LDNS_WIREPARSE_ERR_OK; -} diff --git a/crates/libunbound-sys/unbound/sldns/str2wire.h b/crates/libunbound-sys/unbound/sldns/str2wire.h deleted file mode 100644 index 5e4d146d..00000000 --- a/crates/libunbound-sys/unbound/sldns/str2wire.h +++ /dev/null @@ -1,600 +0,0 @@ -/** - * str2wire.h - read txt presentation of RRs - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -/** - * \file - * - * Parses text to wireformat. - */ - -#ifndef LDNS_STR2WIRE_H -#define LDNS_STR2WIRE_H - -/* include rrdef for MAX_DOMAINLEN constant */ -#include - -#ifdef __cplusplus -extern "C" { -#endif -struct sldns_struct_lookup_table; - -#define LDNS_IP4ADDRLEN (32/8) -#define LDNS_IP6ADDRLEN (128/8) - -/** buffer to read an RR, cannot be larger than 64K because of packet size */ -#define LDNS_RR_BUF_SIZE 65535 /* bytes */ -#define LDNS_DEFAULT_TTL 3600 - -/* SVCB keys currently defined in draft-ietf-dnsop-svcb-https */ -#define SVCB_KEY_MANDATORY 0 -#define SVCB_KEY_ALPN 1 -#define SVCB_KEY_NO_DEFAULT_ALPN 2 -#define SVCB_KEY_PORT 3 -#define SVCB_KEY_IPV4HINT 4 -#define SVCB_KEY_ECH 5 -#define SVCB_KEY_IPV6HINT 6 -#define SVCB_KEY_DOHPATH 7 -#define SVCPARAMKEY_COUNT 8 - -#define MAX_NUMBER_OF_SVCPARAMS 64 - -#define SVCB_MAX_COMMA_SEPARATED_VALUES 1000 - -/* - * To convert class and type to string see - * sldns_get_rr_class_by_name(str) - * sldns_get_rr_type_by_name(str) - * from rrdef.h - */ - -/** - * Convert text string into dname wireformat, mallocless, with user buffer. - * @param str: the text string with the domain name. - * @param buf: the result buffer, suggested size LDNS_MAX_DOMAINLEN+1 - * @param len: length of the buffer on input, length of the result on output. - * @return 0 on success, otherwise an error. - */ -int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len); - -/** - * Same as sldns_str2wire_dname_buf, but concatenates origin if the domain - * name is relative (does not end in '.'). - * @param str: the text string with the domain name. - * @param buf: the result buffer, suggested size LDNS_MAX_DOMAINLEN+1 - * @param len: length of the buffer on input, length of the result on output. - * @param origin: the origin to append or NULL (nothing is appended). - * @param origin_len: length of origin. - * @return 0 on success, otherwise an error. - */ -int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, - uint8_t* origin, size_t origin_len); - -/** - * Convert text string into dname wireformat - * @param str: the text string with the domain name. - * @param len: returned length of wireformat. - * @return wireformat dname (malloced) or NULL on failure. - */ -uint8_t* sldns_str2wire_dname(const char* str, size_t* len); - -/** - * Convert text RR to wireformat, with user buffer. - * @param str: the RR data in text presentation format. - * @param rr: the buffer where the result is stored into. This buffer has - * the wire-dname(uncompressed), type, class, ttl, rdatalen, rdata. - * These values are probably not aligned, and in network format. - * Use the sldns_wirerr_get_xxx functions to access them safely. - * buffer size LDNS_RR_BUF_SIZE is suggested. - * @param len: on input the length of the buffer, on output the amount of - * the buffer used for the rr. - * @param dname_len: if non-NULL, filled with the dname length as result. - * Because after the dname you find the type, class, ttl, rdatalen, rdata. - * @param default_ttl: TTL used if no TTL available. - * @param origin: used for origin dname (if not NULL) - * @param origin_len: length of origin. - * @param prev: used for prev_rr dname (if not NULL) - * @param prev_len: length of prev. - * @return 0 on success, an error on failure. - */ -int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, - size_t* dname_len, uint32_t default_ttl, uint8_t* origin, - size_t origin_len, uint8_t* prev, size_t prev_len); - -/** - * Same as sldns_str2wire_rr_buf, but there is no rdata, it returns an RR - * with zero rdata and no ttl. It has name, type, class. - * You can access those with the sldns_wirerr_get_type and class functions. - * @param str: the RR data in text presentation format. - * @param rr: the buffer where the result is stored into. - * @param len: on input the length of the buffer, on output the amount of - * the buffer used for the rr. - * @param dname_len: if non-NULL, filled with the dname length as result. - * Because after the dname you find the type, class, ttl, rdatalen, rdata. - * @param origin: used for origin dname (if not NULL) - * @param origin_len: length of origin. - * @param prev: used for prev_rr dname (if not NULL) - * @param prev_len: length of prev. - * @return 0 on success, an error on failure. - */ -int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, - size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, - size_t prev_len); - -/** - * Get the type of the RR. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return type in host byteorder - */ -uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Get the class of the RR. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return class in host byteorder - */ -uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Get the ttl of the RR. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return ttl in host byteorder - */ -uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Get the rdata length of the RR. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return rdata length in host byteorder - * If the rdata length is larger than the rr-len allows, it is truncated. - * So, that it is safe to read the data length returned - * from this function from the rdata pointer of sldns_wirerr_get_rdata. - */ -uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Get the rdata pointer of the RR. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return rdata pointer - */ -uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Get the rdata pointer of the RR. prefixed with rdata length. - * @param rr: the RR in wire format. - * @param len: rr length. - * @param dname_len: dname length to skip. - * @return pointer to rdatalength, followed by the rdata. - */ -uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len); - -/** - * Parse result codes - */ -#define LDNS_WIREPARSE_MASK 0x0fff -#define LDNS_WIREPARSE_SHIFT 12 -#define LDNS_WIREPARSE_ERROR(e) ((e)&LDNS_WIREPARSE_MASK) -#define LDNS_WIREPARSE_OFFSET(e) ((((unsigned)(e))&~LDNS_WIREPARSE_MASK)>>LDNS_WIREPARSE_SHIFT) -/* use lookuptable to get error string, sldns_wireparse_errors */ -#define LDNS_WIREPARSE_ERR_OK 0 -#define LDNS_WIREPARSE_ERR_GENERAL 342 -#define LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW 343 -#define LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW 344 -#define LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL 345 -#define LDNS_WIREPARSE_ERR_LABEL_OVERFLOW 346 -#define LDNS_WIREPARSE_ERR_EMPTY_LABEL 347 -#define LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE 348 -#define LDNS_WIREPARSE_ERR_SYNTAX 349 -#define LDNS_WIREPARSE_ERR_SYNTAX_TTL 350 -#define LDNS_WIREPARSE_ERR_SYNTAX_TYPE 351 -#define LDNS_WIREPARSE_ERR_SYNTAX_CLASS 352 -#define LDNS_WIREPARSE_ERR_SYNTAX_RDATA 353 -#define LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE 354 -#define LDNS_WIREPARSE_ERR_INVALID_STR 355 -#define LDNS_WIREPARSE_ERR_SYNTAX_B64 356 -#define LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT 357 -#define LDNS_WIREPARSE_ERR_SYNTAX_HEX 358 -#define LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM 359 -#define LDNS_WIREPARSE_ERR_SYNTAX_TIME 360 -#define LDNS_WIREPARSE_ERR_SYNTAX_PERIOD 361 -#define LDNS_WIREPARSE_ERR_SYNTAX_ILNP64 362 -#define LDNS_WIREPARSE_ERR_SYNTAX_EUI48 363 -#define LDNS_WIREPARSE_ERR_SYNTAX_EUI64 364 -#define LDNS_WIREPARSE_ERR_SYNTAX_TAG 365 -#define LDNS_WIREPARSE_ERR_NOT_IMPL 366 -#define LDNS_WIREPARSE_ERR_SYNTAX_INT 367 -#define LDNS_WIREPARSE_ERR_SYNTAX_IP4 368 -#define LDNS_WIREPARSE_ERR_SYNTAX_IP6 369 -#define LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW 370 -#define LDNS_WIREPARSE_ERR_INCLUDE 371 -#define LDNS_WIREPARSE_ERR_PARENTHESIS 372 -#define LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY 373 -#define LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM 374 -#define LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS 375 -#define LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS 376 -#define LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS 377 -#define LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM 378 -#define LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY 379 -#define LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY 380 -#define LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX 381 -#define LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES 382 -#define LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES 383 -#define LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE 384 -#define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385 -#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386 - - -/** - * Get reference to a constant string for the (parse) error. - * @param e: error return value - * @return string. - */ -const char* sldns_get_errorstr_parse(int e); - -/** - * wire parse state for parsing files - */ -struct sldns_file_parse_state { - /** the origin domain name, if len!=0. uncompressed wireformat */ - uint8_t origin[LDNS_MAX_DOMAINLEN+1]; - /** length of origin domain name, in bytes. 0 if not set. */ - size_t origin_len; - /** the previous domain name, if len!=0. uncompressed wireformat*/ - uint8_t prev_rr[LDNS_MAX_DOMAINLEN+1]; - /** length of the previous domain name, in bytes. 0 if not set. */ - size_t prev_rr_len; - /** default TTL, this is used if the text does not specify a TTL, - * host byteorder */ - uint32_t default_ttl; - /** line number information */ - int lineno; -}; - -/** - * Read one RR from zonefile with buffer for the data. - * @param in: file that is read from (one RR, multiple lines if it spans them). - * @param rr: this is malloced by the user and the result is stored here, - * if an RR is read. If no RR is read this is signalled with the - * return len set to 0 (for ORIGIN, TTL directives). - * The read line is available in the rr_buf (zero terminated), for - * $DIRECTIVE style elements. - * @param len: on input, the length of the rr buffer. on output the rr len. - * Buffer size of 64k should be enough. - * @param dname_len: returns the length of the dname initial part of the rr. - * @param parse_state: pass a pointer to user-allocated struct. - * Contents are maintained by this function. - * If you pass NULL then ORIGIN and TTL directives are not honored. - * You can start out with a particular origin by pre-filling it. - * otherwise, zero the structure before passing it. - * lineno is incremented when a newline is passed by the parser, - * you should initialize it at 1 at the start of the file. - * @return 0 on success, error on failure. - */ -int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, - struct sldns_file_parse_state* parse_state); - -/** - * Convert one rdf in rdata to wireformat and parse from string. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @param rdftype: the type of the rdf. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, - sldns_rdf_type rdftype); - -/** - * Convert rdf of type LDNS_RDF_TYPE_INT8 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_INT16 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_INT32 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_A from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_AAAA from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_STR from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_APL from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_B64 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_B32_EXT from string to wireformat. - * And also LDNS_RDF_TYPE_NSEC3_NEXT_OWNER. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_HEX from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_NSEC from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_TYPE from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_CLASS from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_CERT_ALG from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_ALG from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_TIME from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_PERIOD from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_TSIGTIME from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_TSIGERROR from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_LOC from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_WKS from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_NSAP from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_ATMA from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_IPSECKEY from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_NSEC3_SALT from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_ILNP64 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_EUI48 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_EUI64 from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_LONG_STR from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_HIP from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Convert rdf of type LDNS_RDF_TYPE_INT16_DATA from string to wireformat. - * @param str: the text to convert for this rdata element. - * @param rd: rdata buffer for the wireformat. - * @param len: length of rd buffer on input, used length on output. - * @return 0 on success, error on failure. - */ -int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len); - -/** - * Strip whitespace from the start and the end of line. - * @param line: modified with 0 to shorten it. - * @return new start with spaces skipped. - */ -char * sldns_strip_ws(char *line); -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_STR2WIRE_H */ diff --git a/crates/libunbound-sys/unbound/sldns/wire2str.c b/crates/libunbound-sys/unbound/sldns/wire2str.c deleted file mode 100644 index e6278ff5..00000000 --- a/crates/libunbound-sys/unbound/sldns/wire2str.c +++ /dev/null @@ -1,2374 +0,0 @@ -/* - * wire2str.c - * - * conversion routines from the wire format - * to the presentation format (strings) - * - * (c) NLnet Labs, 2004-2006 - * - * See the file LICENSE for the license - */ -/** - * \file - * - * Contains functions to translate the wireformat to text - * representation, as well as functions to print them. - */ -#include "config.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" -#include "sldns/rrdef.h" -#include "sldns/pkthdr.h" -#include "sldns/parseutil.h" -#include "sldns/sbuffer.h" -#include "sldns/keyraw.h" -#include "util/data/dname.h" -#ifdef HAVE_TIME_H -#include -#endif -#include -#include -#include -#ifdef HAVE_NETDB_H -#include -#endif - -/* lookup tables for standard DNS stuff */ -/* Taken from RFC 2535, section 7. */ -static sldns_lookup_table sldns_algorithms_data[] = { - { LDNS_RSAMD5, "RSAMD5" }, - { LDNS_DH, "DH" }, - { LDNS_DSA, "DSA" }, - { LDNS_ECC, "ECC" }, - { LDNS_RSASHA1, "RSASHA1" }, - { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, - { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, - { LDNS_RSASHA256, "RSASHA256"}, - { LDNS_RSASHA512, "RSASHA512"}, - { LDNS_ECC_GOST, "ECC-GOST"}, - { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, - { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, - { LDNS_ED25519, "ED25519"}, - { LDNS_ED448, "ED448"}, - { LDNS_INDIRECT, "INDIRECT" }, - { LDNS_PRIVATEDNS, "PRIVATEDNS" }, - { LDNS_PRIVATEOID, "PRIVATEOID" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_algorithms = sldns_algorithms_data; - -/* hash algorithms in DS record */ -static sldns_lookup_table sldns_hashes_data[] = { - { LDNS_SHA1, "SHA1" }, - { LDNS_SHA256, "SHA256" }, - { LDNS_HASH_GOST, "HASH-GOST" }, - { LDNS_SHA384, "SHA384" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_hashes = sldns_hashes_data; - -/* Taken from RFC 4398 */ -static sldns_lookup_table sldns_cert_algorithms_data[] = { - { LDNS_CERT_PKIX, "PKIX" }, - { LDNS_CERT_SPKI, "SPKI" }, - { LDNS_CERT_PGP, "PGP" }, - { LDNS_CERT_IPKIX, "IPKIX" }, - { LDNS_CERT_ISPKI, "ISPKI" }, - { LDNS_CERT_IPGP, "IPGP" }, - { LDNS_CERT_ACPKIX, "ACPKIX" }, - { LDNS_CERT_IACPKIX, "IACPKIX" }, - { LDNS_CERT_URI, "URI" }, - { LDNS_CERT_OID, "OID" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data; - -/* if these are used elsewhere */ -static sldns_lookup_table sldns_rcodes_data[] = { - { LDNS_RCODE_NOERROR, "NOERROR" }, - { LDNS_RCODE_FORMERR, "FORMERR" }, - { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, - { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, - { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, - { LDNS_RCODE_REFUSED, "REFUSED" }, - { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, - { LDNS_RCODE_YXRRSET, "YXRRSET" }, - { LDNS_RCODE_NXRRSET, "NXRRSET" }, - { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, - { LDNS_RCODE_NOTZONE, "NOTZONE" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_rcodes = sldns_rcodes_data; - -static sldns_lookup_table sldns_opcodes_data[] = { - { LDNS_PACKET_QUERY, "QUERY" }, - { LDNS_PACKET_IQUERY, "IQUERY" }, - { LDNS_PACKET_STATUS, "STATUS" }, - { LDNS_PACKET_NOTIFY, "NOTIFY" }, - { LDNS_PACKET_UPDATE, "UPDATE" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_opcodes = sldns_opcodes_data; - -static sldns_lookup_table sldns_wireparse_errors_data[] = { - { LDNS_WIREPARSE_ERR_OK, "no parse error" }, - { LDNS_WIREPARSE_ERR_GENERAL, "parse error" }, - { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" }, - { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" }, - { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" }, - { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" }, - { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" }, - { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" }, - { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" }, - { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" }, - { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" }, - { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" }, - { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" }, - { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" }, - { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" }, - { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" }, - { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_EUI48, - "Conversion error, 6 two character hex numbers " - "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" }, - { LDNS_WIREPARSE_ERR_SYNTAX_EUI64, - "Conversion error, 8 two character hex numbers " - "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" }, - { LDNS_WIREPARSE_ERR_SYNTAX_TAG, - "Conversion error, a non-zero sequence of US-ASCII letters " - "and numbers in lower case expected" }, - { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" }, - { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" }, - { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" }, - { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" }, - { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" }, - { LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY, "Unknown SvcParamKey"}, - { LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM, "SvcParam is missing a SvcParamValue"}, - { LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS, "Duplicate SVCB key found"}, - { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS, "Too many keys in mandatory" }, - { LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS, - "Too many SvcParams. Unbound only allows 63 entries" }, - { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM, - "Mandatory SvcParamKey is missing"}, - { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY, - "Keys in SvcParam mandatory MUST be unique" }, - { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY, - "mandatory MUST not be included as mandatory parameter" }, - { LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX, - "Could not parse port SvcParamValue" }, - { LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES, - "Too many IPv4 addresses in ipv4hint" }, - { LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES, - "Too many IPv6 addresses in ipv6hint" }, - { LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE, - "Alpn strings need to be smaller than 255 chars"}, - { LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE, - "No-default-alpn should not have a value" }, - { LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA, - "General SVCParam error" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data; - -static sldns_lookup_table sldns_edns_flags_data[] = { - { 3600, "do"}, - { 0, NULL} -}; -sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data; - -static sldns_lookup_table sldns_edns_options_data[] = { - { 1, "LLQ" }, - { 2, "UL" }, - { 3, "NSID" }, - /* 4 draft-cheshire-edns0-owner-option */ - { 5, "DAU" }, - { 6, "DHU" }, - { 7, "N3U" }, - { 8, "edns-client-subnet" }, - { 11, "edns-tcp-keepalive"}, - { 12, "Padding" }, - { 15, "EDE"}, - { 0, NULL} -}; -sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; - -static sldns_lookup_table sldns_tsig_errors_data[] = { - { LDNS_TSIG_ERROR_NOERROR, "NOERROR" }, - { LDNS_RCODE_FORMERR, "FORMERR" }, - { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, - { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, - { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, - { LDNS_RCODE_REFUSED, "REFUSED" }, - { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, - { LDNS_RCODE_YXRRSET, "YXRRSET" }, - { LDNS_RCODE_NXRRSET, "NXRRSET" }, - { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, - { LDNS_RCODE_NOTZONE, "NOTZONE" }, - { LDNS_TSIG_ERROR_BADSIG, "BADSIG" }, - { LDNS_TSIG_ERROR_BADKEY, "BADKEY" }, - { LDNS_TSIG_ERROR_BADTIME, "BADTIME" }, - { LDNS_TSIG_ERROR_BADMODE, "BADMODE" }, - { LDNS_TSIG_ERROR_BADNAME, "BADNAME" }, - { LDNS_TSIG_ERROR_BADALG, "BADALG" }, - { 0, NULL } -}; -sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; - -/* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */ -const char *svcparamkey_strs[] = { - "mandatory", "alpn", "no-default-alpn", "port", - "ipv4hint", "ech", "ipv6hint", "dohpath" -}; - -char* sldns_wire2str_pkt(uint8_t* data, size_t len) -{ - size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0); - char* result = (char*)malloc(slen+1); - if(!result) return NULL; - sldns_wire2str_pkt_buf(data, len, result, slen+1); - return result; -} - -char* sldns_wire2str_rr(uint8_t* rr, size_t len) -{ - size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0); - char* result = (char*)malloc(slen+1); - if(!result) return NULL; - sldns_wire2str_rr_buf(rr, len, result, slen+1); - return result; -} - -char* sldns_wire2str_type(uint16_t rrtype) -{ - char buf[16]; - sldns_wire2str_type_buf(rrtype, buf, sizeof(buf)); - return strdup(buf); -} - -char* sldns_wire2str_class(uint16_t rrclass) -{ - char buf[16]; - sldns_wire2str_class_buf(rrclass, buf, sizeof(buf)); - return strdup(buf); -} - -char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len) -{ - size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0); - char* result = (char*)malloc(slen+1); - if(!result) return NULL; - sldns_wire2str_dname_buf(dname, dname_len, result, slen+1); - return result; -} - -char* sldns_wire2str_rcode(int rcode) -{ - char buf[16]; - sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf)); - return strdup(buf); -} - -int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen); -} - -int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); -} - -int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); -} - -int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, - size_t str_len, uint16_t rrtype) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len, - rrtype, NULL, 0, NULL); -} - -int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); -} - -int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len, - char* s, size_t slen) -{ - uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len); - return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len, - rrtype); -} - -int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_type_print(&s, &slen, rrtype); -} - -int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_class_print(&s, &slen, rrclass); -} - -int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_rcode_print(&s, &slen, rcode); -} - -int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_opcode_print(&s, &slen, opcode); -} - -int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) -{ - /* use arguments as temporary variables */ - return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); -} - -int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) -{ - int w = vsnprintf(*str, *slen, format, args); - if(w < 0) { - /* error in printout */ - return 0; - } else if((size_t)w >= *slen) { - *str = NULL; /* we do not want str to point outside of buffer*/ - *slen = 0; - } else { - *str += w; - *slen -= w; - } - return w; -} - -int sldns_str_print(char** str, size_t* slen, const char* format, ...) -{ - int w; - va_list args; - va_start(args, format); - w = sldns_str_vprint(str, slen, format, args); - va_end(args); - return w; -} - -/** print hex format into text buffer for specified length */ -static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len) -{ - const char* hex = "0123456789ABCDEF"; - size_t i; - for(i=0; i>4], - hex[buf[i]&0x0f]); - } - return (int)len*2; -} - -/** print remainder of buffer in hex format with prefixed text */ -static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen, - char** s, size_t* slen) -{ - int w = 0; - w += sldns_str_print(s, slen, "%s", pref); - w += print_hex_buf(s, slen, *d, *dlen); - *d += *dlen; - *dlen = 0; - return w; -} - -int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) -{ - int w = 0, comprloop = 0; - unsigned qdcount, ancount, nscount, arcount, i; - uint8_t* pkt = *d; - size_t pktlen = *dlen; - if(*dlen >= LDNS_HEADER_SIZE) { - qdcount = (unsigned)LDNS_QDCOUNT(*d); - ancount = (unsigned)LDNS_ANCOUNT(*d); - nscount = (unsigned)LDNS_NSCOUNT(*d); - arcount = (unsigned)LDNS_ARCOUNT(*d); - } else { - qdcount = ancount = nscount = arcount = 0; - } - w += sldns_wire2str_header_scan(d, dlen, s, slen); - w += sldns_str_print(s, slen, "\n"); - w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n"); - for(i=0; i 0) { - w += print_remainder_hex(";; trailing garbage 0x", - d, dlen, s, slen); - w += sldns_str_print(s, slen, "\n"); - } - return w; -} - -/** scan type, class and ttl and printout, for rr */ -static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w = 0; - uint16_t t, c; - uint32_t ttl; - if(*dl < 8) { - if(*dl < 4) - return w + print_remainder_hex("; Error malformed 0x", - d, dl, s, sl); - /* these print values or 0x.. if none left */ - t = sldns_read_uint16(*d); - c = sldns_read_uint16((*d)+2); - (*d)+=4; - (*dl)-=4; - w += sldns_wire2str_class_print(s, sl, c); - w += sldns_str_print(s, sl, "\t"); - w += sldns_wire2str_type_print(s, sl, t); - if(*dl == 0) - return w + sldns_str_print(s, sl, "; Error no ttl"); - return w + print_remainder_hex( - "; Error malformed ttl 0x", d, dl, s, sl); - } - t = sldns_read_uint16(*d); - c = sldns_read_uint16((*d)+2); - ttl = sldns_read_uint32((*d)+4); - (*d)+=8; - (*dl)-=8; - w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl); - w += sldns_wire2str_class_print(s, sl, c); - w += sldns_str_print(s, sl, "\t"); - w += sldns_wire2str_type_print(s, sl, t); - return w; -} - -int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - uint8_t* pkt, size_t pktlen, int* comprloop) -{ - int w = 0; - uint8_t* rr = *d; - size_t rrlen = *dlen, dname_off, rdlen, ordlen; - uint16_t rrtype = 0; - - if(*dlen >= 3 && (*d)[0]==0 && - sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) { - /* perform EDNS OPT processing */ - return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen); - } - - /* try to scan the rdata with pretty-printing, but if that fails, then - * scan the rdata as an unknown RR type */ - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); - w += sldns_str_print(s, slen, "\t"); - dname_off = rrlen-(*dlen); - if(*dlen == 4) { - /* like a question-RR */ - uint16_t t = sldns_read_uint16(*d); - uint16_t c = sldns_read_uint16((*d)+2); - (*d)+=4; - (*dlen)-=4; - w += sldns_wire2str_class_print(s, slen, c); - w += sldns_str_print(s, slen, "\t"); - w += sldns_wire2str_type_print(s, slen, t); - w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n"); - return w; - } - if(*dlen < 8) { - if(*dlen == 0) - return w + sldns_str_print(s, slen, ";Error missing RR\n"); - w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - rrtype = sldns_read_uint16(*d); - w += sldns_rr_tcttl_scan(d, dlen, s, slen); - w += sldns_str_print(s, slen, "\t"); - - /* rdata */ - if(*dlen < 2) { - if(*dlen == 0) - return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); - w += print_remainder_hex(";Error missing rdatalen 0x", - d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - rdlen = sldns_read_uint16(*d); - ordlen = rdlen; - (*d)+=2; - (*dlen)-=2; - if(*dlen < rdlen) { - w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); - if(*dlen == 0) - return w + sldns_str_print(s, slen, ";Error missing rdata\n"); - w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen, - comprloop); - (*dlen) -= (ordlen-rdlen); - - /* default comment */ - w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off, - rrtype); - w += sldns_str_print(s, slen, "\n"); - return w; -} - -int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) -{ - int w = 0; - uint16_t t, c; - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); - w += sldns_str_print(s, slen, "\t"); - if(*dlen < 4) { - if(*dlen == 0) - return w + sldns_str_print(s, slen, "Error malformed\n"); - w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - t = sldns_read_uint16(*d); - c = sldns_read_uint16((*d)+2); - (*d)+=4; - (*dlen)-=4; - w += sldns_wire2str_class_print(s, slen, c); - w += sldns_str_print(s, slen, "\t"); - w += sldns_wire2str_type_print(s, slen, t); - w += sldns_str_print(s, slen, "\n"); - return w; -} - -int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) -{ - size_t rdlen, ordlen; - int w = 0; - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); - w += sldns_str_print(s, slen, "\t"); - w += sldns_rr_tcttl_scan(d, dlen, s, slen); - w += sldns_str_print(s, slen, "\t"); - if(*dlen < 2) { - if(*dlen == 0) - return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); - w += print_remainder_hex(";Error missing rdatalen 0x", - d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - rdlen = sldns_read_uint16(*d); - ordlen = rdlen; - (*d) += 2; - (*dlen) -= 2; - if(*dlen < rdlen) { - w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); - if(*dlen == 0) - return w + sldns_str_print(s, slen, ";Error missing rdata\n"); - w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); - return w + sldns_str_print(s, slen, "\n"); - } - w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen); - (*dlen) -= (ordlen-rdlen); - w += sldns_str_print(s, slen, "\n"); - return w; -} - -/** print rr comment for type DNSKEY */ -static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr, - size_t rrlen, size_t dname_off) -{ - size_t rdlen; - uint8_t* rdata; - int flags, w = 0; - if(rrlen < dname_off + 10) return 0; - rdlen = sldns_read_uint16(rr+dname_off+8); - if(rrlen < dname_off + 10 + rdlen) return 0; - if(rdlen < 2) return 0; - rdata = rr + dname_off + 10; - flags = (int)sldns_read_uint16(rdata); - w += sldns_str_print(s, slen, " ;{"); - - /* id */ - w += sldns_str_print(s, slen, "id = %u", - sldns_calc_keytag_raw(rdata, rdlen)); - - /* flags */ - if((flags&LDNS_KEY_ZONE_KEY)) { - if((flags&LDNS_KEY_SEP_KEY)) - w += sldns_str_print(s, slen, " (ksk)"); - else w += sldns_str_print(s, slen, " (zsk)"); - } - - /* keysize */ - if(rdlen > 4) { - w += sldns_str_print(s, slen, ", "); - w += sldns_str_print(s, slen, "size = %db", - (int)sldns_rr_dnskey_key_size_raw( - (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3]))); - } - - w += sldns_str_print(s, slen, "}"); - return w; -} - -/** print rr comment for type RRSIG */ -static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr, - size_t rrlen, size_t dname_off) -{ - size_t rdlen; - uint8_t* rdata; - if(rrlen < dname_off + 10) return 0; - rdlen = sldns_read_uint16(rr+dname_off+8); - if(rrlen < dname_off + 10 + rdlen) return 0; - rdata = rr + dname_off + 10; - if(rdlen < 18) return 0; - return sldns_str_print(s, slen, " ;{id = %d}", - (int)sldns_read_uint16(rdata+16)); -} - -/** print rr comment for type NSEC3 */ -static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr, - size_t rrlen, size_t dname_off) -{ - size_t rdlen; - uint8_t* rdata; - int w = 0; - if(rrlen < dname_off + 10) return 0; - rdlen = sldns_read_uint16(rr+dname_off+8); - if(rrlen < dname_off + 10 + rdlen) return 0; - rdata = rr + dname_off + 10; - if(rdlen < 2) return 0; - if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK)) - w += sldns_str_print(s, slen, " ;{flags: optout}"); - return w; -} - -int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr, - size_t rrlen, size_t dname_off, uint16_t rrtype) -{ - if(rrtype == LDNS_RR_TYPE_DNSKEY) { - return rr_comment_dnskey(s, slen, rr, rrlen, dname_off); - } else if(rrtype == LDNS_RR_TYPE_RRSIG) { - return rr_comment_rrsig(s, slen, rr, rrlen, dname_off); - } else if(rrtype == LDNS_RR_TYPE_NSEC3) { - return rr_comment_nsec3(s, slen, rr, rrlen, dname_off); - } - return 0; -} - -int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen) -{ - int w = 0; - int opcode, rcode; - w += sldns_str_print(s, slen, ";; ->>HEADER<<- "); - if(*dlen == 0) - return w+sldns_str_print(s, slen, "Error empty packet"); - if(*dlen < 4) - return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); - opcode = (int)LDNS_OPCODE_WIRE(*d); - rcode = (int)LDNS_RCODE_WIRE(*d); - w += sldns_str_print(s, slen, "opcode: "); - w += sldns_wire2str_opcode_print(s, slen, opcode); - w += sldns_str_print(s, slen, ", "); - w += sldns_str_print(s, slen, "rcode: "); - w += sldns_wire2str_rcode_print(s, slen, rcode); - w += sldns_str_print(s, slen, ", "); - w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d)); - w += sldns_str_print(s, slen, ";; flags:"); - if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr"); - if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa"); - if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc"); - if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd"); - if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd"); - if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra"); - if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad"); - if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z"); - w += sldns_str_print(s, slen, " ; "); - if(*dlen < LDNS_HEADER_SIZE) - return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); - w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d)); - w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d)); - w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d)); - w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d)); - *d += LDNS_HEADER_SIZE; - *dlen -= LDNS_HEADER_SIZE; - return w; -} - -int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen, - int* comprloop) -{ - /* try to prettyprint, but if that fails, use unknown format */ - uint8_t* origd = *d; - char* origs = *s; - size_t origdlen = *dlen, origslen = *slen; - size_t r_cnt, r_max; - sldns_rdf_type rdftype; - int w = 0, n; - - const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype); - if(!desc) /* unknown format */ - return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen); - /* dlen equals the rdatalen for the rdata */ - - r_max = sldns_rr_descriptor_maximum(desc); - for(r_cnt=0; r_cnt < r_max; r_cnt++) { - if(*dlen == 0) { - if(r_cnt < sldns_rr_descriptor_minimum(desc)) - goto failed; - break; /* nothing more to print */ - } - rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); - if(r_cnt != 0) - w += sldns_str_print(s, slen, " "); - n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype, - pkt, pktlen, comprloop); - if(n == -1) { - failed: - /* failed, use unknown format */ - *d = origd; *s = origs; - *dlen = origdlen; *slen = origslen; - return sldns_wire2str_rdata_unknown_scan(d, dlen, - s, slen); - } - w += n; - } - if(*dlen != 0) { - goto failed; - } - return w; -} - -int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen) -{ - int w = 0; - - /* print length */ - w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen); - - /* print rdlen in hex */ - if(*dlen != 0) - w += sldns_str_print(s, slen, " "); - w += print_hex_buf(s, slen, *d, *dlen); - (*d) += *dlen; - (*dlen) = 0; - return w; -} - -/** print and escape one character for a domain dname */ -static int dname_char_print(char** s, size_t* slen, uint8_t c) -{ - if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') - return sldns_str_print(s, slen, "\\%c", c); - else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c))) - return sldns_str_print(s, slen, "\\%03u", (unsigned)c); - /* plain printout */ - if(*slen) { - **s = (char)c; - (*s)++; - (*slen)--; - } - return 1; -} - -int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - uint8_t* pkt, size_t pktlen, int* comprloop) -{ - int w = 0; - /* spool labels onto the string, use compression if its there */ - uint8_t* pos = *d; - unsigned i, counter=0; - unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */ - int in_buf = 1; - size_t dname_len = 0; - if(comprloop) { - if(*comprloop != 0) - maxcompr = 30; /* for like ipv6 reverse name, per label */ - if(*comprloop > 4) - maxcompr = 4; /* just don't want to spend time, any more */ - } - if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); - if(*pos == 0) { - (*d)++; - (*dlen)--; - return sldns_str_print(s, slen, "."); - } - while((!pkt || pos < pkt+pktlen) && *pos) { - /* read label length */ - uint8_t labellen = *pos++; - if(in_buf) { (*d)++; (*dlen)--; } - - /* find out what sort of label we have */ - if((labellen&0xc0) == 0xc0) { - /* compressed */ - uint16_t target = 0; - if(in_buf && *dlen == 0) - return w + sldns_str_print(s, slen, - "ErrorPartialDname"); - else if(!in_buf && pos+1 > pkt+pktlen) - return w + sldns_str_print(s, slen, - "ErrorPartialDname"); - target = ((labellen&0x3f)<<8) | *pos; - if(in_buf) { (*d)++; (*dlen)--; } - /* move to target, if possible */ - if(!pkt || target >= pktlen) - return w + sldns_str_print(s, slen, - "ErrorComprPtrOutOfBounds"); - if(counter++ > maxcompr) { - if(comprloop && *comprloop < 10) - (*comprloop)++; - return w + sldns_str_print(s, slen, - "ErrorComprPtrLooped"); - } - in_buf = 0; - pos = pkt+target; - continue; - } else if((labellen&0xc0)) { - /* notimpl label type */ - w += sldns_str_print(s, slen, - "ErrorLABELTYPE%xIsUnknown", - (int)(labellen&0xc0)); - return w; - } - - /* spool label characters, end with '.' */ - if(in_buf && *dlen < (size_t)labellen) - labellen = (uint8_t)*dlen; - else if(!in_buf && pos+(size_t)labellen > pkt+pktlen) - labellen = (uint8_t)(pkt + pktlen - pos); - dname_len += ((size_t)labellen)+1; - if(dname_len > LDNS_MAX_DOMAINLEN) { - /* dname_len counts the uncompressed length we have - * seen so far, and the domain name has become too - * long, prevent the loop from printing overly long - * content. */ - w += sldns_str_print(s, slen, - "ErrorDomainNameTooLong"); - return w; - } - for(i=0; i<(unsigned)labellen; i++) { - w += dname_char_print(s, slen, *pos++); - } - if(in_buf) { - (*d) += labellen; - (*dlen) -= labellen; - if(*dlen == 0) break; - } - w += sldns_str_print(s, slen, "."); - } - /* skip over final root label */ - if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; } - /* in case we printed no labels, terminate dname */ - if(w == 0) w += sldns_str_print(s, slen, "."); - return w; -} - -int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode) -{ - sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode); - if (lt && lt->name) { - return sldns_str_print(s, slen, "%s", lt->name); - } - return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode); -} - -int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode) -{ - sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode); - if (lt && lt->name) { - return sldns_str_print(s, slen, "%s", lt->name); - } - return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode); -} - -int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass) -{ - sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes, - (int)rrclass); - if (lt && lt->name) { - return sldns_str_print(s, slen, "%s", lt->name); - } - return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass); -} - -int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype) -{ - const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype); - if (descriptor && descriptor->_name) { - return sldns_str_print(s, slen, "%s", descriptor->_name); - } - return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype); -} - -int sldns_wire2str_edns_option_code_print(char** s, size_t* slen, - uint16_t opcode) -{ - sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options, - (int)opcode); - if (lt && lt->name) { - return sldns_str_print(s, slen, "%s", lt->name); - } - return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode); -} - -int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) -{ - uint16_t c; - if(*dlen == 0) return 0; - if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); - c = sldns_read_uint16(*d); - (*d)+=2; - (*dlen)-=2; - return sldns_wire2str_class_print(s, slen, c); -} - -int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) -{ - uint16_t t; - if(*dlen == 0) return 0; - if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); - t = sldns_read_uint16(*d); - (*d)+=2; - (*dlen)-=2; - return sldns_wire2str_type_print(s, slen, t); -} - -int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) -{ - uint32_t ttl; - if(*dlen == 0) return 0; - if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); - ttl = sldns_read_uint32(*d); - (*d)+=4; - (*dlen)-=4; - return sldns_str_print(s, slen, "%u", (unsigned)ttl); -} - -static int -sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey) -{ - if (svcparamkey < SVCPARAMKEY_COUNT) { - return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]); - } - else { - return sldns_str_print(s, slen, "key%d", (int)svcparamkey); - } -} - -static int sldns_wire2str_svcparam_port2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - int w = 0; - - if (data_len != 2) - return -1; /* wireformat error, a short is 2 bytes */ - w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data)); - - return w; -} - -static int sldns_wire2str_svcparam_ipv4hint2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - char ip_str[INET_ADDRSTRLEN + 1]; - - int w = 0; - - assert(data_len > 0); - - if ((data_len % LDNS_IP4ADDRLEN) == 0) { - if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) - return -1; /* wireformat error, incorrect size or inet family */ - - w += sldns_str_print(s, slen, "=%s", ip_str); - data += LDNS_IP4ADDRLEN; - - while ((data_len -= LDNS_IP4ADDRLEN) > 0) { - if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) - return -1; /* wireformat error, incorrect size or inet family */ - - w += sldns_str_print(s, slen, ",%s", ip_str); - data += LDNS_IP4ADDRLEN; - } - } else - return -1; - - return w; -} - -static int sldns_wire2str_svcparam_ipv6hint2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - char ip_str[INET6_ADDRSTRLEN + 1]; - - int w = 0; - - assert(data_len > 0); - - if ((data_len % LDNS_IP6ADDRLEN) == 0) { - if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) - return -1; /* wireformat error, incorrect size or inet family */ - - w += sldns_str_print(s, slen, "=%s", ip_str); - data += LDNS_IP6ADDRLEN; - - while ((data_len -= LDNS_IP6ADDRLEN) > 0) { - if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) - return -1; /* wireformat error, incorrect size or inet family */ - - w += sldns_str_print(s, slen, ",%s", ip_str); - data += LDNS_IP6ADDRLEN; - } - } else - return -1; - - return w; -} - -static int sldns_wire2str_svcparam_mandatory2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - int w = 0; - - assert(data_len > 0); - - if (data_len % sizeof(uint16_t)) - return -1; /* wireformat error, data_len must be multiple of shorts */ - w += sldns_str_print(s, slen, "="); - w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); - data += 2; - - while ((data_len -= sizeof(uint16_t))) { - w += sldns_str_print(s, slen, ","); - w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); - data += 2; - } - - return w; -} - -static int sldns_wire2str_svcparam_alpn2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - uint8_t *dp = (void *)data; - int w = 0; - - assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ - - w += sldns_str_print(s, slen, "=\""); - while (data_len) { - /* alpn is list of length byte (str_len) followed by a string of that size */ - uint8_t i, str_len = *dp++; - - if (str_len > --data_len) - return -1; - - for (i = 0; i < str_len; i++) { - if (dp[i] == '"' || dp[i] == '\\') - w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]); - - else if (dp[i] == ',') - w += sldns_str_print(s, slen, "\\\\%c", dp[i]); - - else if (!isprint(dp[i])) - w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]); - - else - w += sldns_str_print(s, slen, "%c", dp[i]); - } - dp += str_len; - if ((data_len -= str_len)) - w += sldns_str_print(s, slen, "%s", ","); - } - w += sldns_str_print(s, slen, "\""); - - return w; -} - -static int sldns_wire2str_svcparam_ech2str(char** s, - size_t* slen, uint16_t data_len, uint8_t* data) -{ - int size; - int w = 0; - - assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ - - w += sldns_str_print(s, slen, "=\""); - - if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0) - return -1; - - (*s) += size; - (*slen) -= size; - - w += sldns_str_print(s, slen, "\""); - - return w + size; -} - -int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) -{ - uint8_t ch; - uint16_t svcparamkey, data_len; - int written_chars = 0; - int r, i; - - /* verify that we have enough data to read svcparamkey and data_len */ - if(*dlen < 4) - return -1; - - svcparamkey = sldns_read_uint16(*d); - data_len = sldns_read_uint16(*d+2); - *d += 4; - *dlen -= 4; - - /* verify that we have data_len data */ - if (data_len > *dlen) - return -1; - - written_chars += sldns_print_svcparamkey(s, slen, svcparamkey); - if (!data_len) { - - /* Some SvcParams MUST have values */ - switch (svcparamkey) { - case SVCB_KEY_ALPN: - case SVCB_KEY_PORT: - case SVCB_KEY_IPV4HINT: - case SVCB_KEY_IPV6HINT: - case SVCB_KEY_MANDATORY: - case SVCB_KEY_DOHPATH: - return -1; - default: - return written_chars; - } - } - - switch (svcparamkey) { - case SVCB_KEY_PORT: - r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d); - break; - case SVCB_KEY_IPV4HINT: - r = sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, *d); - break; - case SVCB_KEY_IPV6HINT: - r = sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, *d); - break; - case SVCB_KEY_MANDATORY: - r = sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, *d); - break; - case SVCB_KEY_NO_DEFAULT_ALPN: - return -1; /* wireformat error, should not have a value */ - case SVCB_KEY_ALPN: - r = sldns_wire2str_svcparam_alpn2str(s, slen, data_len, *d); - break; - case SVCB_KEY_ECH: - r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d); - break; - case SVCB_KEY_DOHPATH: - /* fallthrough */ - default: - r = sldns_str_print(s, slen, "=\""); - - for (i = 0; i < data_len; i++) { - ch = (*d)[i]; - - if (ch == '"' || ch == '\\') - r += sldns_str_print(s, slen, "\\%c", ch); - - else if (!isprint(ch)) - r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch); - - else - r += sldns_str_print(s, slen, "%c", ch); - - } - r += sldns_str_print(s, slen, "\""); - break; - } - if (r <= 0) - return -1; /* wireformat error */ - - written_chars += r; - *d += data_len; - *dlen -= data_len; - return written_chars; -} - -int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop) -{ - if(*dlen == 0) return 0; - switch(rdftype) { - case LDNS_RDF_TYPE_NONE: - return 0; - case LDNS_RDF_TYPE_DNAME: - return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); - case LDNS_RDF_TYPE_INT8: - return sldns_wire2str_int8_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_INT16: - return sldns_wire2str_int16_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_INT32: - return sldns_wire2str_int32_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_PERIOD: - return sldns_wire2str_period_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_TSIGTIME: - return sldns_wire2str_tsigtime_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_A: - return sldns_wire2str_a_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_AAAA: - return sldns_wire2str_aaaa_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_STR: - return sldns_wire2str_str_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_APL: - return sldns_wire2str_apl_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_B32_EXT: - return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_B64: - return sldns_wire2str_b64_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_HEX: - return sldns_wire2str_hex_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_NSEC: - return sldns_wire2str_nsec_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_NSEC3_SALT: - return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_TYPE: - return sldns_wire2str_type_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_CLASS: - return sldns_wire2str_class_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_CERT_ALG: - return sldns_wire2str_cert_alg_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_ALG: - return sldns_wire2str_alg_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_UNKNOWN: - return sldns_wire2str_unknown_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_TIME: - return sldns_wire2str_time_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_LOC: - return sldns_wire2str_loc_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_WKS: - case LDNS_RDF_TYPE_SERVICE: - return sldns_wire2str_wks_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_NSAP: - return sldns_wire2str_nsap_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_ATMA: - return sldns_wire2str_atma_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_IPSECKEY: - return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, - pktlen, comprloop); - case LDNS_RDF_TYPE_HIP: - return sldns_wire2str_hip_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_INT16_DATA: - return sldns_wire2str_int16_data_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: - return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_ILNP64: - return sldns_wire2str_ilnp64_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_EUI48: - return sldns_wire2str_eui48_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_EUI64: - return sldns_wire2str_eui64_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_TAG: - return sldns_wire2str_tag_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_LONG_STR: - return sldns_wire2str_long_str_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_SVCPARAM: - return sldns_wire2str_svcparam_scan(d, dlen, s, slen); - case LDNS_RDF_TYPE_TSIGERROR: - return sldns_wire2str_tsigerror_scan(d, dlen, s, slen); - } - /* unknown rdf type */ - return -1; -} - -int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 1) return -1; - w = sldns_str_print(s, sl, "%u", (unsigned)**d); - (*d)++; - (*dl)--; - return w; -} - -int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 2) return -1; - w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d)); - (*d)+=2; - (*dl)-=2; - return w; -} - -int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 4) return -1; - w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d)); - (*d)+=4; - (*dl)-=4; - return w; -} - -int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 4) return -1; - w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d)); - (*d)+=4; - (*dl)-=4; - return w; -} - -int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - /* tsigtime is 48 bits network order unsigned integer */ - int w; - uint64_t tsigtime = 0; - uint64_t d0, d1, d2, d3, d4, d5; - if(*dl < 6) return -1; - d0 = (*d)[0]; /* cast to uint64 for shift operations */ - d1 = (*d)[1]; - d2 = (*d)[2]; - d3 = (*d)[3]; - d4 = (*d)[4]; - d5 = (*d)[5]; - tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; -#ifndef USE_WINSOCK - w = sldns_str_print(s, sl, "%llu", (long long)tsigtime); -#else - w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime); -#endif - (*d)+=6; - (*dl)-=6; - return w; -} - -int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - char buf[32]; - int w; - if(*dl < 4) return -1; - if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf))) - return -1; - w = sldns_str_print(s, sl, "%s", buf); - (*d)+=4; - (*dl)-=4; - return w; -} - -int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ -#ifdef AF_INET6 - char buf[64]; - int w; - if(*dl < 16) return -1; - if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf))) - return -1; - w = sldns_str_print(s, sl, "%s", buf); - (*d)+=16; - (*dl)-=16; - return w; -#else - return -1; -#endif -} - -/** printout escaped TYPE_STR character */ -static int str_char_print(char** s, size_t* sl, uint8_t c) -{ - if(isprint((unsigned char)c) || c == '\t') { - if(c == '\"' || c == '\\') - return sldns_str_print(s, sl, "\\%c", c); - if(*sl) { - **s = (char)c; - (*s)++; - (*sl)--; - } - return 1; - } - return sldns_str_print(s, sl, "\\%03u", (unsigned)c); -} - -int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w = 0; - size_t i, len; - if(*dl < 1) return -1; - len = **d; - if(*dl < 1+len) return -1; - (*d)++; - (*dl)--; - w += sldns_str_print(s, sl, "\""); - for(i=0; i 0) - w += sldns_str_print(s, sl, "."); - if(i < (int)adflength) - w += sldns_str_print(s, sl, "%d", (*d)[4+i]); - else w += sldns_str_print(s, sl, "0"); - } - } else if(family == LDNS_APL_IP6) { - /* check if prefix <128 ? */ - /* address is variable length 0 - 16 */ - for(i=0; i<16; i++) { - if(i%2 == 0 && i>0) - w += sldns_str_print(s, sl, ":"); - if(i < (int)adflength) - w += sldns_str_print(s, sl, "%02x", (*d)[4+i]); - else w += sldns_str_print(s, sl, "00"); - } - } - w += sldns_str_print(s, sl, "/%u", (unsigned)prefix); - (*d) += 4+adflength; - (*dl) -= 4+adflength; - return w; -} - -int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - size_t datalen; - size_t sz; - if(*dl < 1) return -1; - datalen = (*d)[0]; - if(*dl < 1+datalen) return -1; - sz = sldns_b32_ntop_calculate_size(datalen); - if(*sl < sz+1) { - (*d) += datalen+1; - (*dl) -= (datalen+1); - return (int)sz; /* out of space really, but would need buffer - in order to truncate the output */ - } - sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl); - (*d) += datalen+1; - (*dl) -= (datalen+1); - (*s) += sz; - (*sl) -= sz; - return (int)sz; -} - -/** scan number of bytes from wire into b64 presentation format */ -static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s, - size_t* sl, size_t num) -{ - /* b64_ntop_calculate size includes null at the end */ - size_t sz = sldns_b64_ntop_calculate_size(num)-1; - if(*sl < sz+1) { - (*d) += num; - (*dl) -= num; - return (int)sz; /* out of space really, but would need buffer - in order to truncate the output */ - } - sldns_b64_ntop(*d, num, *s, *sl); - (*d) += num; - (*dl) -= num; - (*s) += sz; - (*sl) -= sz; - return (int)sz; -} - -int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - if(*dl == 0) { - return sldns_str_print(s, sl, "0"); - } - return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); -} - -int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - if(*dl == 0) { - return sldns_str_print(s, sl, "0"); - } - return print_remainder_hex("", d, dl, s, sl); -} - -int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - uint8_t* p = *d; - size_t pl = *dl; - unsigned i, bit, window, block_len; - uint16_t t; - int w = 0; - - /* check for errors */ - while(pl) { - if(pl < 2) return -1; - block_len = (unsigned)p[1]; - if(pl < 2+block_len) return -1; - p += block_len+2; - pl -= block_len+2; - } - - /* do it */ - p = *d; - pl = *dl; - while(pl) { - if(pl < 2) return -1; /* cannot happen */ - window = (unsigned)p[0]; - block_len = (unsigned)p[1]; - if(pl < 2+block_len) return -1; /* cannot happen */ - p += 2; - for(i=0; i>bit))) { - if(w) w += sldns_str_print(s, sl, " "); - w += sldns_wire2str_type_print(s, sl, - t+bit); - } - } - } - p += block_len; - pl -= block_len+2; - } - (*d) += *dl; - (*dl) = 0; - return w; -} - -int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - size_t salt_len; - int w; - if(*dl < 1) return -1; - salt_len = (size_t)(*d)[0]; - if(*dl < 1+salt_len) return -1; - (*d)++; - (*dl)--; - if(salt_len == 0) { - return sldns_str_print(s, sl, "-"); - } - w = print_hex_buf(s, sl, *d, salt_len); - (*dl)-=salt_len; - (*d)+=salt_len; - return w; -} - -int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - sldns_lookup_table *lt; - int data, w; - if(*dl < 2) return -1; - data = (int)sldns_read_uint16(*d); - lt = sldns_lookup_by_id(sldns_cert_algorithms, data); - if(lt && lt->name) - w = sldns_str_print(s, sl, "%s", lt->name); - else w = sldns_str_print(s, sl, "%d", data); - (*dl)-=2; - (*d)+=2; - return w; -} - -int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - /* don't use algorithm mnemonics in the presentation format - * this kind of got sneaked into the rfc's */ - return sldns_wire2str_int8_scan(d, dl, s, sl); -} - -int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl); -} - -int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - /* create a YYYYMMDDHHMMSS string if possible */ - struct tm tm; - char date_buf[16]; - uint32_t t; - memset(&tm, 0, sizeof(tm)); - if(*dl < 4) return -1; - t = sldns_read_uint32(*d); - date_buf[15]=0; - if(sldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) && - strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { - (*d) += 4; - (*dl) -= 4; - return sldns_str_print(s, sl, "%s", date_buf); - } - return -1; -} - -static int -loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent) -{ - int w = 0; - uint8_t i; - /* is it 0. ? */ - if(exponent < 2) { - if(exponent == 1) - mantissa *= 10; - return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); - } - /* always */ - w += sldns_str_print(str, sl, "%d", (int)mantissa); - for(i=0; i equator) { - northerness = 'N'; - latitude = latitude - equator; - } else { - northerness = 'S'; - latitude = equator - latitude; - } - h = latitude / (1000 * 60 * 60); - latitude = latitude % (1000 * 60 * 60); - m = latitude / (1000 * 60); - latitude = latitude % (1000 * 60); - s = (double) latitude / 1000.0; - w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", - h, m, s, northerness); - - if (longitude > equator) { - easterness = 'E'; - longitude = longitude - equator; - } else { - easterness = 'W'; - longitude = equator - longitude; - } - h = longitude / (1000 * 60 * 60); - longitude = longitude % (1000 * 60 * 60); - m = longitude / (1000 * 60); - longitude = longitude % (1000 * 60); - s = (double) longitude / (1000.0); - w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", - h, m, s, easterness); - - s = ((double) altitude) / 100; - s -= 100000; - - if(altitude%100 != 0) - w += sldns_str_print(str, sl, "%.2f", s); - else - w += sldns_str_print(str, sl, "%.0f", s); - - w += sldns_str_print(str, sl, "m "); - - w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f); - w += sldns_str_print(str, sl, "m "); - - w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4, - horizontal_precision & 0x0f); - w += sldns_str_print(str, sl, "m "); - - w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4, - vertical_precision & 0x0f); - w += sldns_str_print(str, sl, "m"); - - (*d)+=16; - (*dl)-=16; - return w; -} - -int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - /* protocol, followed by bitmap of services */ - const char* proto_name = NULL; - struct protoent *protocol; - struct servent *service; - uint8_t protocol_nr; - int bit, port, w = 0; - size_t i; - /* we cannot print with strings because they - * are not portable, the presentation format may - * not be able to be read in on another computer. */ - int print_symbols = 0; - - /* protocol */ - if(*dl < 1) return -1; - protocol_nr = (*d)[0]; - (*d)++; - (*dl)--; - protocol = getprotobynumber((int)protocol_nr); - if(protocol && (protocol->p_name != NULL)) { - w += sldns_str_print(s, sl, "%s", protocol->p_name); - proto_name = protocol->p_name; - } else if(protocol_nr == 6) { - w += sldns_str_print(s, sl, "tcp"); - } else if(protocol_nr == 17) { - w += sldns_str_print(s, sl, "udp"); - } else { - w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr); - } - - for(i=0; i<*dl; i++) { - if((*d)[i] == 0) - continue; - for(bit=0; bit<8; bit++) { - if(!(((*d)[i])&(0x80>>bit))) - continue; - port = (int)i*8 + bit; - - if(!print_symbols) - service = NULL; - else - service = getservbyport( - (int)htons((uint16_t)port), proto_name); - if(service && service->s_name) - w += sldns_str_print(s, sl, " %s", - service->s_name); - else w += sldns_str_print(s, sl, " %u", - (unsigned)port); - } - } - -#ifdef HAVE_ENDSERVENT - endservent(); -#endif -#ifdef HAVE_ENDPROTOENT - endprotoent(); -#endif - (*d) += *dl; - (*dl) = 0; - return w; -} - -int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - return print_remainder_hex("0x", d, dl, s, sl); -} - -int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - return print_remainder_hex("", d, dl, s, sl); -} - -/* internal scan routine that can modify arguments on failure */ -static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, - char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop) -{ - /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ - uint8_t precedence, gateway_type, algorithm; - int w = 0; - - if(*dl < 3) return -1; - precedence = (*d)[0]; - gateway_type = (*d)[1]; - algorithm = (*d)[2]; - if(gateway_type > 3) - return -1; /* unknown */ - (*d)+=3; - (*dl)-=3; - w += sldns_str_print(s, sl, "%d %d %d ", - (int)precedence, (int)gateway_type, (int)algorithm); - - switch(gateway_type) { - case 0: /* no gateway */ - w += sldns_str_print(s, sl, "."); - break; - case 1: /* ip4 */ - w += sldns_wire2str_a_scan(d, dl, s, sl); - break; - case 2: /* ip6 */ - w += sldns_wire2str_aaaa_scan(d, dl, s, sl); - break; - case 3: /* dname */ - w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop); - break; - default: /* unknown */ - return -1; - } - - if(*dl < 1) - return -1; - w += sldns_str_print(s, sl, " "); - w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); - return w; -} - -int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, - uint8_t* pkt, size_t pktlen, int* comprloop) -{ - uint8_t* od = *d; - char* os = *s; - size_t odl = *dl, osl = *sl; - int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop); - if(w == -1) { - *d = od; - *s = os; - *dl = odl; - *sl = osl; - return -1; - } - return w; -} - -int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - uint8_t algo, hitlen; - uint16_t pklen; - - /* read lengths */ - if(*dl < 4) - return -1; - hitlen = (*d)[0]; - algo = (*d)[1]; - pklen = sldns_read_uint16((*d)+2); - if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen) - return -1; - - /* write: algo hit pubkey */ - w = sldns_str_print(s, sl, "%u ", (unsigned)algo); - w += print_hex_buf(s, sl, (*d)+4, hitlen); - w += sldns_str_print(s, sl, " "); - (*d)+=4+hitlen; - (*dl)-= (4+hitlen); - w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen); - return w; -} - -int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - uint16_t n; - if(*dl < 2) - return -1; - n = sldns_read_uint16(*d); - if(*dl < 2+(size_t)n) - return -1; - (*d)+=2; - (*dl)-=2; - if(n == 0) { - return sldns_str_print(s, sl, "0"); - } - w = sldns_str_print(s, sl, "%u ", (unsigned)n); - w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n); - return w; -} - -int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, - size_t* sl) -{ - return sldns_wire2str_b32_ext_scan(d, dl, s, sl); -} - -int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 8) - return -1; - w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x", - sldns_read_uint16(*d), sldns_read_uint16((*d)+2), - sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6)); - (*d)+=8; - (*dl)-=8; - return w; -} - -int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 6) - return -1; - w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]); - (*d)+=6; - (*dl)-=6; - return w; -} - -int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - int w; - if(*dl < 8) - return -1; - w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", - (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5], - (*d)[6], (*d)[7]); - (*d)+=8; - (*dl)-=8; - return w; -} - -int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) -{ - size_t i, n; - int w = 0; - if(*dl < 1) - return -1; - n = (size_t)((*d)[0]); - if(*dl < 1+n) - return -1; - for(i=0; iname) - w = sldns_str_print(s, sl, "%s", lt->name); - else w = sldns_str_print(s, sl, "%d", data); - (*dl)-=2; - (*d)+=2; - return w; -} - -int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, - size_t len) -{ - /* LLQ constants */ - const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", - "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; - const unsigned int llq_errors_num = 7; - const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; - const unsigned int llq_opcodes_num = 3; - uint16_t version, llq_opcode, error_code; - uint64_t llq_id; - uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ - int w = 0; - - /* read the record */ - if(len != 18) { - w += sldns_str_print(s, sl, "malformed LLQ "); - w += print_hex_buf(s, sl, data, len); - return w; - } - version = sldns_read_uint16(data); - llq_opcode = sldns_read_uint16(data+2); - error_code = sldns_read_uint16(data+4); - memmove(&llq_id, data+6, sizeof(llq_id)); - lease_life = sldns_read_uint32(data+14); - - /* print it */ - w += sldns_str_print(s, sl, "v%d ", (int)version); - if(llq_opcode < llq_opcodes_num) - w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]); - else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode); - if(error_code < llq_errors_num) - w += sldns_str_print(s, sl, " %s", llq_errors[error_code]); - else w += sldns_str_print(s, sl, " error %d", (int)error_code); -#ifndef USE_WINSOCK - w += sldns_str_print(s, sl, " id %llx lease-life %lu", - (unsigned long long)llq_id, (unsigned long)lease_life); -#else - w += sldns_str_print(s, sl, " id %I64x lease-life %lu", - (unsigned long long)llq_id, (unsigned long)lease_life); -#endif - return w; -} - -int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data, - size_t len) -{ - uint32_t lease; - int w = 0; - if(len != 4) { - w += sldns_str_print(s, sl, "malformed UL "); - w += print_hex_buf(s, sl, data, len); - return w; - } - lease = sldns_read_uint32(data); - w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease); - return w; -} - -int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, - size_t len) -{ - int w = 0; - size_t i, printed=0; - w += print_hex_buf(s, sl, data, len); - for(i=0; iname) - w += sldns_str_print(s, sl, " %s", lt->name); - else w += sldns_str_print(s, sl, " %d", (int)data[i]); - } - return w; -} - -int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data, - size_t len) -{ - sldns_lookup_table *lt; - size_t i; - int w = 0; - for(i=0; iname) - w += sldns_str_print(s, sl, " %s", lt->name); - else w += sldns_str_print(s, sl, " %d", (int)data[i]); - } - return w; -} - -int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data, - size_t len) -{ - size_t i; - int w = 0; - for(i=0; i 4) { - w += sldns_str_print(s, sl, "trailingdata:"); - w += print_hex_buf(s, sl, data+4+4, len-4-4); - w += sldns_str_print(s, sl, " "); - len = 4+4; - } - memmove(ip4, data+4, len-4); - if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) { - w += sldns_str_print(s, sl, "ip4ntoperror "); - w += print_hex_buf(s, sl, data+4+4, len-4-4); - } else { - w += sldns_str_print(s, sl, "%s", buf); - } - } else if(family == 2) { - /* IP6 */ - char buf[64]; - uint8_t ip6[16]; - memset(ip6, 0, sizeof(ip6)); - if(len-4 > 16) { - w += sldns_str_print(s, sl, "trailingdata:"); - w += print_hex_buf(s, sl, data+4+16, len-4-16); - w += sldns_str_print(s, sl, " "); - len = 4+16; - } - memmove(ip6, data+4, len-4); -#ifdef AF_INET6 - if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) { - w += sldns_str_print(s, sl, "ip6ntoperror "); - w += print_hex_buf(s, sl, data+4+4, len-4-4); - } else { - w += sldns_str_print(s, sl, "%s", buf); - } -#else - w += print_hex_buf(s, sl, data+4+4, len-4-4); -#endif - } else { - /* unknown */ - w += sldns_str_print(s, sl, "family %d ", - (int)family); - w += print_hex_buf(s, sl, data, len); - } - w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope); - return w; -} - -static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, - uint8_t* data, size_t len) -{ - int w = 0; - uint16_t timeout; - if(!(len == 0 || len == 2)) { - w += sldns_str_print(s, sl, "malformed keepalive "); - w += print_hex_buf(s, sl, data, len); - return w; - } - if(len == 0 ) { - w += sldns_str_print(s, sl, "no timeout value (only valid for client option) "); - } else { - timeout = sldns_read_uint16(data); - w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout); - } - return w; -} - -int sldns_wire2str_edns_option_print(char** s, size_t* sl, - uint16_t option_code, uint8_t* optdata, size_t optlen) -{ - int w = 0; - w += sldns_wire2str_edns_option_code_print(s, sl, option_code); - w += sldns_str_print(s, sl, ": "); - switch(option_code) { - case LDNS_EDNS_LLQ: - w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_UL: - w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_NSID: - w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_DAU: - w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_DHU: - w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_N3U: - w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_CLIENT_SUBNET: - w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_KEEPALIVE: - w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen); - break; - case LDNS_EDNS_PADDING: - w += print_hex_buf(s, sl, optdata, optlen); - break; - default: - /* unknown option code */ - w += print_hex_buf(s, sl, optdata, optlen); - break; - } - return w; -} - -/** print the edns options to string */ -static int -print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen) -{ - uint16_t option_code, option_len; - int w = 0; - while(rdatalen > 0) { - /* option name */ - if(rdatalen < 4) { - w += sldns_str_print(s, sl, " ; malformed: "); - w += print_hex_buf(s, sl, rdata, rdatalen); - return w; - } - option_code = sldns_read_uint16(rdata); - option_len = sldns_read_uint16(rdata+2); - rdata += 4; - rdatalen -= 4; - - /* option value */ - if(rdatalen < (size_t)option_len) { - w += sldns_str_print(s, sl, " ; malformed "); - w += sldns_wire2str_edns_option_code_print(s, sl, - option_code); - w += sldns_str_print(s, sl, ": "); - w += print_hex_buf(s, sl, rdata, rdatalen); - return w; - } - w += sldns_str_print(s, sl, " ; "); - w += sldns_wire2str_edns_option_print(s, sl, option_code, - rdata, option_len); - rdata += option_len; - rdatalen -= option_len; - } - return w; -} - -int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen) -{ - int w = 0; - uint8_t ext_rcode, edns_version; - uint16_t udpsize, edns_bits, rdatalen; - w += sldns_str_print(str, str_len, "; EDNS:"); - - /* some input checks, domain name */ - if(*data_len < 1+10) - return w + print_remainder_hex("Error malformed 0x", - data, data_len, str, str_len); - if(*data[0] != 0) { - return w + print_remainder_hex("Error nonrootdname 0x", - data, data_len, str, str_len); - } - (*data)++; - (*data_len)--; - - /* check type and read fixed contents */ - if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) { - return w + print_remainder_hex("Error nottypeOPT 0x", - data, data_len, str, str_len); - } - udpsize = sldns_read_uint16((*data)+2); - ext_rcode = (*data)[4]; - edns_version = (*data)[5]; - edns_bits = sldns_read_uint16((*data)+6); - rdatalen = sldns_read_uint16((*data)+8); - (*data)+=10; - (*data_len)-=10; - - w += sldns_str_print(str, str_len, " version: %u;", - (unsigned)edns_version); - w += sldns_str_print(str, str_len, " flags:"); - if((edns_bits & LDNS_EDNS_MASK_DO_BIT)) - w += sldns_str_print(str, str_len, " do"); - /* the extended rcode is the value set, shifted four bits, - * and or'd with the original rcode */ - if(ext_rcode) { - int rc = ((int)ext_rcode)<<4; - if(pkt && pktlen >= LDNS_HEADER_SIZE) - rc |= LDNS_RCODE_WIRE(pkt); - w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc); - } - w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize); - - if(rdatalen) { - if((size_t)*data_len < rdatalen) { - w += sldns_str_print(str, str_len, - " ; Error EDNS rdata too short; "); - rdatalen = (uint16_t)*data_len; - } - w += print_edns_opts(str, str_len, *data, rdatalen); - (*data) += rdatalen; - (*data_len) -= rdatalen; - } - w += sldns_str_print(str, str_len, "\n"); - return w; -} diff --git a/crates/libunbound-sys/unbound/sldns/wire2str.h b/crates/libunbound-sys/unbound/sldns/wire2str.h deleted file mode 100644 index 548c6630..00000000 --- a/crates/libunbound-sys/unbound/sldns/wire2str.h +++ /dev/null @@ -1,1053 +0,0 @@ -/** - * wire2str.h - txt presentation of RRs - * - * (c) NLnet Labs, 2005-2006 - * - * See the file LICENSE for the license - */ - -/** - * \file - * - * Contains functions to translate the wireformat to text - * representation, as well as functions to print them. - */ - -#ifndef LDNS_WIRE2STR_H -#define LDNS_WIRE2STR_H - -#ifdef __cplusplus -extern "C" { -#endif -struct sldns_struct_lookup_table; - -/* lookup tables for standard DNS stuff */ -/** Taken from RFC 2535, section 7. */ -extern struct sldns_struct_lookup_table* sldns_algorithms; -/** DS record hash algorithms */ -extern struct sldns_struct_lookup_table* sldns_hashes; -/** Taken from RFC 2538, section 2.1. */ -extern struct sldns_struct_lookup_table* sldns_cert_algorithms; -/** Response codes */ -extern struct sldns_struct_lookup_table* sldns_rcodes; -/** Operation codes */ -extern struct sldns_struct_lookup_table* sldns_opcodes; -/** EDNS flags */ -extern struct sldns_struct_lookup_table* sldns_edns_flags; -/** EDNS option codes */ -extern struct sldns_struct_lookup_table* sldns_edns_options; -/** error string from wireparse */ -extern struct sldns_struct_lookup_table* sldns_wireparse_errors; -/** tsig errors are the rcodes with extra (higher) values */ -extern struct sldns_struct_lookup_table* sldns_tsig_errors; - -/** - * Convert wireformat packet to a string representation - * @param data: wireformat packet data (starting at ID bytes). - * @param len: length of packet. - * @return string(malloced) or NULL on failure. - */ -char* sldns_wire2str_pkt(uint8_t* data, size_t len); - -/** - * Convert wireformat RR to a string representation. - * @param rr: the wireformat RR, in uncompressed form. Starts at the domain - * name start, ends with the rdata of the RR. - * @param len: length of the rr wireformat. - * @return string(malloced) or NULL on failure. - */ -char* sldns_wire2str_rr(uint8_t* rr, size_t len); - -/** - * Convert wire dname to a string. - * @param dname: the dname in uncompressed wireformat. - * @param dname_len: length of the dname. - * @return string or NULL on failure. - */ -char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len); - -/** - * Convert wire RR type to a string, 'MX', 'TYPE1234'... - * @param rrtype: the RR type in host order. - * @return malloced string with the RR type or NULL on malloc failure. - */ -char* sldns_wire2str_type(uint16_t rrtype); - -/** - * Convert wire RR class to a string, 'IN', 'CLASS1'. - * @param rrclass: the RR class in host order. - * @return malloced string with the RR class or NULL on malloc failure. - */ -char* sldns_wire2str_class(uint16_t rrclass); - -/** - * Convert wire packet rcode to a string, 'NOERROR', 'NXDOMAIN'... - * @param rcode: as integer, host order - * @return malloced string with the rcode or NULL on malloc failure. - */ -char* sldns_wire2str_rcode(int rcode); - -/** - * Print to string, move string along for next content. With va_list. - * @param str: string buffer. Adjusted at end to after the output. - * @param slen: length of the string buffer. Adjusted at end. - * @param format: printf format string. - * @param args: arguments for printf. - * @return number of characters needed. Can be larger than slen. - */ -int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args); - -/** - * Print to string, move string along for next content. - * @param str: string buffer. Adjusted at end to after the output. - * @param slen: length of the string buffer. Adjusted at end. - * @param format: printf format string and arguments for it. - * @return number of characters needed. Can be larger than slen. - */ -int sldns_str_print(char** str, size_t* slen, const char* format, ...) - ATTR_FORMAT(printf, 3, 4); - -/** - * Convert wireformat packet to a string representation with user buffer - * It appends every RR with default comments. - * For more formatter options use the function: TBD(TODO) - * @param data: wireformat packet data (starting at ID bytes). - * @param data_len: length of packet. - * @param str: the string buffer for the output. - * If you pass NULL as the str the return value of the function is - * the str_len you need for the entire packet. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str, - size_t str_len); - -/** - * Scan wireformat packet to a string representation with user buffer - * It appends every RR with default comments. - * For more formatter options use the function: TBD(TODO) - * @param data: wireformat packet data (starting at ID bytes). - * @param data_len: length of packet. - * @param str: the string buffer for the output. - * @param str_len: the size of the string buffer. - * @return number of characters for string. - * returns the number of characters that are needed (except terminating null), - * so it may return a value larger than str_len. - * On error you get less output (i.e. shorter output in str (null terminated)) - * On exit the data, data_len, str and str_len values are adjusted to move them - * from their original position along the input and output for the content - * that has been consumed (and produced) by this function. If the end of the - * output string is reached, *str_len is set to 0. The output string is null - * terminated (shortening the output if necessary). If the end of the input - * is reached *data_len is set to 0. - */ -int sldns_wire2str_pkt_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat rr to string, with user buffers. It shifts the arguments - * to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rr_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen, int* comprloop); - -/** - * Scan wireformat question rr to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rrquestion_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen, int* comprloop); - -/** - * Scan wireformat RR to string in unknown RR format, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rr_unknown_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen, int* comprloop); - -/** - * Print to string the RR-information comment in default format, - * with user buffers. Moves string along. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rr: wireformat data. - * @param rrlen: length of data buffer. - * @param dname_off: offset in buffer behind owner dname, the compressed size - * of the owner name. - * @param rrtype: type of the RR, host format. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rr_comment_print(char** str, size_t* str_len, uint8_t* rr, - size_t rrlen, size_t dname_off, uint16_t rrtype); - -/** - * Scan wireformat packet header to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_header_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat rdata to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. The length of the rdata in the - * buffer. The rdatalen itself has already been scanned, the data - * points to the rdata after the rdatalen. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rrtype: RR type of Rdata, host format. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rdata_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint16_t rrtype, uint8_t* pkt, size_t pktlen, - int* comprloop); - -/** - * Scan wireformat rdata to string in unknown format, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer, the length of the rdata in buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rdata_unknown_scan(uint8_t** data, size_t* data_len, - char** str, size_t* str_len); - -/** - * Scan wireformat domain name to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: inout bool, that is set true if compression loop failure - * happens. Pass in 0, if passsed in as true, a lower bound is set - * on compression loops to stop arbitrary long packet parse times. - * This is meant so you can set it to 0 at the start of a list of dnames, - * and then scan all of them in sequence, if a loop happens, it becomes - * true and then it becomes more strict for the next dnames in the list. - * You can leave it at NULL if there is no pkt (pkt is NULL too). - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_dname_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen, int* comprloop); - -/** - * Scan wireformat rr type to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_type_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat rr class to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_class_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat rr ttl to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_ttl_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - - -/** - * Print host format rr type to string. Moves string along, user buffers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rrtype: host format rr type. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_type_print(char** str, size_t* str_len, uint16_t rrtype); - -/** - * Print host format rr class to string. Moves string along, user buffers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rrclass: host format rr class. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_class_print(char** str, size_t* str_len, uint16_t rrclass); - -/** - * Print host format rcode to string. Moves string along, user buffers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rcode: host format rcode number. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_rcode_print(char** str, size_t* str_len, int rcode); - -/** - * Print host format opcode to string. Moves string along, user buffers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param opcode: host format opcode number. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_opcode_print(char** str, size_t* str_len, int opcode); - -/** - * Print host format EDNS0 option to string. Moves string along, user buffers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param opcode: host format option number. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_option_code_print(char** str, size_t* str_len, - uint16_t opcode); - -/** - * Convert RR to string presentation format, on one line. User buffer. - * @param rr: wireformat RR data - * @param rr_len: length of the rr wire data. - * @param str: the string buffer to write to. - * If you pass NULL as the str, the return value of the function is - * the str_len you need for the entire packet. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str, - size_t str_len); - -/** - * Convert question RR to string presentation format, on one line. User buffer. - * @param rr: wireformat RR data - * @param rr_len: length of the rr wire data. - * @param str: the string buffer to write to. - * If you pass NULL as the str, the return value of the function is - * the str_len you need for the entire packet. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rrquestion_buf(uint8_t* rr, size_t rr_len, char* str, - size_t str_len); - -/** - * 3597 printout of an RR in unknown rr format. - * There are more format and comment options available for printout - * with the function: TBD(TODO) - * @param rr: wireformat RR data - * @param rr_len: length of the rr wire data. - * @param str: the string buffer to write to. - * If you pass NULL as the str, the return value of the function is - * the str_len you need for the entire rr. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str, - size_t str_len); - -/** - * This creates the comment to print after the RR. ; keytag=... , and other - * basic comments for RRs. - * There are more format and comment options available for printout - * with the function: TBD(TODO) - * @param rr: wireformat RR data - * @param rr_len: length of the rr wire data. - * @param dname_len: length of the dname in front of the RR. - * @param str: the string buffer to write to. - * If you pass NULL as the str, the return value of the function is - * the str_len you need for the entire comment. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len, - char* str, size_t str_len); - -/** - * Convert RDATA to string presentation format, on one line. User buffer. - * @param rdata: wireformat rdata part of an RR. - * @param rdata_len: length of the rr wire data. - * @param str: the string buffer to write to. - * If you pass NULL as the str, the return value of the function is - * the str_len you need for the entire packet. It does not include - * the 0 byte at the end. - * @param str_len: the size of the string buffer. If more is needed, it'll - * silently truncate the output to fit in the buffer. - * @param rrtype: rr type of the data - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, - size_t str_len, uint16_t rrtype); - -/** - * Convert wire RR type to a string, 'MX', 'TYPE12'. With user buffer. - * @param rrtype: the RR type in host order. - * @param str: the string to write to. - * @param len: length of str. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len); - -/** - * Convert wire RR class to a string, 'IN', 'CLASS12'. With user buffer. - * @param rrclass: the RR class in host order. - * @param str: the string to write to. - * @param len: length of str. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len); - -/** - * Convert wire RR rcode to a string, 'NOERROR', 'NXDOMAIN'. With user buffer. - * @param rcode: rcode as integer in host order - * @param str: the string to write to. - * @param len: length of str. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len); - -/** - * Convert host format opcode to a string. 'QUERY', 'NOTIFY', 'UPDATE'. - * With user buffer. - * @param opcode: opcode as integer in host order - * @param str: the string to write to. - * @param len: length of str. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_opcode_buf(int opcode, char* str, size_t len); - -/** - * Convert wire dname to a string, "example.com.". With user buffer. - * @param dname: the dname in uncompressed wireformat. - * @param dname_len: length of the dname. - * @param str: the string to write to. - * @param len: length of string. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str, - size_t len); - -/** - * Convert wire SVCB to a string with user buffer. - * @param d: the SVCB data in uncompressed wireformat. - * @param dlen: length of the SVCB data. - * @param s: the string to write to. - * @param slen: length of string. - * @return the number of characters for this element, excluding zerobyte. - * Is larger or equal than str_len if output was truncated. - */ -int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen); - -/** - * Scan wireformat rdf field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param rdftype: the type of the rdata field, enum sldns_rdf_type. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_rdf_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, int rdftype, uint8_t* pkt, size_t pktlen, - int* comprloop); - -/** - * Scan wireformat int8 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_int8_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat int16 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_int16_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat int32 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_int32_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat period field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_period_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat tsigtime field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_tsigtime_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat ip4 A field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_a_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat ip6 AAAA field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_aaaa_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat str field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_str_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat apl field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_apl_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat b32_ext field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_b32_ext_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat b64 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_b64_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat hex field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_hex_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat nsec bitmap field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_nsec_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat nsec3_salt field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_nsec3_salt_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat cert_alg field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_cert_alg_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat alg field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_alg_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat type unknown field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_unknown_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat time field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_time_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat LOC field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_loc_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat WKS field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_wks_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat NSAP field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_nsap_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat ATMA field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_atma_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat IPSECKEY field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet for decompression, if NULL no decompression. - * @param pktlen: length of packet buffer. - * @param comprloop: if pkt, bool detects compression loops. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_ipseckey_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen, int* comprloop); - -/** - * Scan wireformat HIP (algo, HIT, pubkey) field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_hip_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat int16_data field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_int16_data_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat tsigerror field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_tsigerror_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat nsec3_next_owner field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_nsec3_next_owner_scan(uint8_t** data, size_t* data_len, - char** str, size_t* str_len); - -/** - * Scan wireformat ILNP64 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_ilnp64_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat EUI48 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_eui48_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat EUI64 field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat TAG field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_tag_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Scan wireformat long_str field to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @return number of characters (except null) needed to print. - * Can return -1 on failure. - */ -int sldns_wire2str_long_str_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len); - -/** - * Print EDNS LLQ option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_llq_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS UL option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_ul_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS NSID option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_nsid_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS DAU option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_dau_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS DHU option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_dhu_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS N3U option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_n3u_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print EDNS SUBNET option data to string. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len, - uint8_t* option_data, size_t option_len); - -/** - * Print an EDNS option as OPT: VALUE. User buffers, moves string pointers. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param option_code: host format EDNS option code. - * @param option_data: buffer with EDNS option code data. - * @param option_len: length of the data for this option. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_option_print(char** str, size_t* str_len, - uint16_t option_code, uint8_t* option_data, size_t option_len); - -/** - * Scan wireformat EDNS OPT to string, with user buffers. - * It shifts the arguments to move along (see sldns_wire2str_pkt_scan). - * @param data: wireformat data. - * @param data_len: length of data buffer. - * @param str: string buffer. - * @param str_len: length of string buffer. - * @param pkt: packet with header and other info (may be NULL) - * @param pktlen: length of packet buffer. - * @return number of characters (except null) needed to print. - */ -int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, - size_t* str_len, uint8_t* pkt, size_t pktlen); - -#ifdef __cplusplus -} -#endif - -#endif /* LDNS_WIRE2STR_H */ diff --git a/crates/libunbound-sys/unbound/util/alloc.c b/crates/libunbound-sys/unbound/util/alloc.c deleted file mode 100644 index 7e961893..00000000 --- a/crates/libunbound-sys/unbound/util/alloc.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * util/alloc.c - memory allocation service. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains memory allocation functions. - */ - -#include "config.h" -#include "util/alloc.h" -#include "util/regional.h" -#include "util/data/packed_rrset.h" -#include "util/fptr_wlist.h" - -/** custom size of cached regional blocks */ -#define ALLOC_REG_SIZE 16384 -/** number of bits for ID part of uint64, rest for number of threads. */ -#define THRNUM_SHIFT 48 /* for 65k threads, 2^48 rrsets per thr. */ - -/** setup new special type */ -static void -alloc_setup_special(alloc_special_type* t) -{ - memset(t, 0, sizeof(*t)); - lock_rw_init(&t->entry.lock); - t->entry.key = t; -} - -/** prealloc some entries in the cache. To minimize contention. - * Result is 1 lock per alloc_max newly created entries. - * @param alloc: the structure to fill up. - */ -static void -prealloc_setup(struct alloc_cache* alloc) -{ - alloc_special_type* p; - int i; - for(i=0; iquar); - alloc->quar = p; - alloc->num_quar++; - } -} - -/** prealloc region blocks */ -static void -prealloc_blocks(struct alloc_cache* alloc, size_t num) -{ - size_t i; - struct regional* r; - for(i=0; inext = (char*)alloc->reg_list; - alloc->reg_list = r; - alloc->num_reg_blocks ++; - } -} - -void -alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, - int thread_num) -{ - memset(alloc, 0, sizeof(*alloc)); - alloc->super = super; - alloc->thread_num = thread_num; - alloc->next_id = (uint64_t)thread_num; /* in steps, so that type */ - alloc->next_id <<= THRNUM_SHIFT; /* of *_id is used. */ - alloc->last_id = 1; /* so no 64bit constants, */ - alloc->last_id <<= THRNUM_SHIFT; /* or implicit 'int' ops. */ - alloc->last_id -= 1; /* for compiler portability. */ - alloc->last_id |= alloc->next_id; - alloc->next_id += 1; /* because id=0 is special. */ - alloc->max_reg_blocks = 100; - alloc->num_reg_blocks = 0; - alloc->reg_list = NULL; - alloc->cleanup = NULL; - alloc->cleanup_arg = NULL; - if(alloc->super) - prealloc_blocks(alloc, alloc->max_reg_blocks); - if(!alloc->super) { - lock_quick_init(&alloc->lock); - lock_protect(&alloc->lock, alloc, sizeof(*alloc)); - } -} - -/** free the special list */ -static void -alloc_clear_special_list(struct alloc_cache* alloc) -{ - alloc_special_type* p, *np; - /* free */ - p = alloc->quar; - while(p) { - np = alloc_special_next(p); - /* deinit special type */ - lock_rw_destroy(&p->entry.lock); - free(p); - p = np; - } -} - -void -alloc_clear_special(struct alloc_cache* alloc) -{ - if(!alloc->super) { - lock_quick_lock(&alloc->lock); - } - alloc_clear_special_list(alloc); - alloc->quar = 0; - alloc->num_quar = 0; - if(!alloc->super) { - lock_quick_unlock(&alloc->lock); - } -} - -void -alloc_clear(struct alloc_cache* alloc) -{ - alloc_special_type* p; - struct regional* r, *nr; - if(!alloc) - return; - if(!alloc->super) { - lock_quick_destroy(&alloc->lock); - } - if(alloc->super && alloc->quar) { - /* push entire list into super */ - p = alloc->quar; - while(alloc_special_next(p)) /* find last */ - p = alloc_special_next(p); - lock_quick_lock(&alloc->super->lock); - alloc_set_special_next(p, alloc->super->quar); - alloc->super->quar = alloc->quar; - alloc->super->num_quar += alloc->num_quar; - lock_quick_unlock(&alloc->super->lock); - } else { - alloc_clear_special_list(alloc); - } - alloc->quar = 0; - alloc->num_quar = 0; - r = alloc->reg_list; - while(r) { - nr = (struct regional*)r->next; - free(r); - r = nr; - } - alloc->reg_list = NULL; - alloc->num_reg_blocks = 0; -} - -uint64_t -alloc_get_id(struct alloc_cache* alloc) -{ - uint64_t id = alloc->next_id++; - if(id == alloc->last_id) { - log_warn("rrset alloc: out of 64bit ids. Clearing cache."); - fptr_ok(fptr_whitelist_alloc_cleanup(alloc->cleanup)); - (*alloc->cleanup)(alloc->cleanup_arg); - - /* start back at first number */ /* like in alloc_init*/ - alloc->next_id = (uint64_t)alloc->thread_num; - alloc->next_id <<= THRNUM_SHIFT; /* in steps for comp. */ - alloc->next_id += 1; /* portability. */ - /* and generate new and safe id */ - id = alloc->next_id++; - } - return id; -} - -alloc_special_type* -alloc_special_obtain(struct alloc_cache* alloc) -{ - alloc_special_type* p; - log_assert(alloc); - /* see if in local cache */ - if(alloc->quar) { - p = alloc->quar; - alloc->quar = alloc_special_next(p); - alloc->num_quar--; - p->id = alloc_get_id(alloc); - return p; - } - /* see if in global cache */ - if(alloc->super) { - /* could maybe grab alloc_max/2 entries in one go, - * but really, isn't that just as fast as this code? */ - lock_quick_lock(&alloc->super->lock); - if((p = alloc->super->quar)) { - alloc->super->quar = alloc_special_next(p); - alloc->super->num_quar--; - } - lock_quick_unlock(&alloc->super->lock); - if(p) { - p->id = alloc_get_id(alloc); - return p; - } - } - /* allocate new */ - prealloc_setup(alloc); - if(!(p = (alloc_special_type*)malloc(sizeof(alloc_special_type)))) { - log_err("alloc_special_obtain: out of memory"); - return NULL; - } - alloc_setup_special(p); - p->id = alloc_get_id(alloc); - return p; -} - -/** push mem and some more items to the super */ -static void -pushintosuper(struct alloc_cache* alloc, alloc_special_type* mem) -{ - int i; - alloc_special_type *p = alloc->quar; - log_assert(p); - log_assert(alloc && alloc->super && - alloc->num_quar >= ALLOC_SPECIAL_MAX); - /* push ALLOC_SPECIAL_MAX/2 after mem */ - alloc_set_special_next(mem, alloc->quar); - for(i=1; iquar = alloc_special_next(p); - alloc->num_quar -= ALLOC_SPECIAL_MAX/2; - - /* dump mem+list into the super quar list */ - lock_quick_lock(&alloc->super->lock); - alloc_set_special_next(p, alloc->super->quar); - alloc->super->quar = mem; - alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1; - lock_quick_unlock(&alloc->super->lock); - /* so 1 lock per mem+alloc/2 deletes */ -} - -void -alloc_special_release(struct alloc_cache* alloc, alloc_special_type* mem) -{ - log_assert(alloc); - if(!mem) - return; - if(!alloc->super) { - lock_quick_lock(&alloc->lock); /* superalloc needs locking */ - } - - alloc_special_clean(mem); - if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) { - /* push it to the super structure */ - pushintosuper(alloc, mem); - return; - } - - alloc_set_special_next(mem, alloc->quar); - alloc->quar = mem; - alloc->num_quar++; - if(!alloc->super) { - lock_quick_unlock(&alloc->lock); - } -} - -void -alloc_stats(struct alloc_cache* alloc) -{ - log_info("%salloc: %d in cache, %d blocks.", alloc->super?"":"sup", - (int)alloc->num_quar, (int)alloc->num_reg_blocks); -} - -size_t alloc_get_mem(struct alloc_cache* alloc) -{ - alloc_special_type* p; - size_t s = sizeof(*alloc); - if(!alloc->super) { - lock_quick_lock(&alloc->lock); /* superalloc needs locking */ - } - s += sizeof(alloc_special_type) * alloc->num_quar; - for(p = alloc->quar; p; p = alloc_special_next(p)) { - s += lock_get_mem(&p->entry.lock); - } - s += alloc->num_reg_blocks * ALLOC_REG_SIZE; - if(!alloc->super) { - lock_quick_unlock(&alloc->lock); - } - return s; -} - -struct regional* -alloc_reg_obtain(struct alloc_cache* alloc) -{ - if(alloc->num_reg_blocks > 0) { - struct regional* r = alloc->reg_list; - alloc->reg_list = (struct regional*)r->next; - r->next = NULL; - alloc->num_reg_blocks--; - return r; - } - return regional_create_custom(ALLOC_REG_SIZE); -} - -void -alloc_reg_release(struct alloc_cache* alloc, struct regional* r) -{ - if(alloc->num_reg_blocks >= alloc->max_reg_blocks) { - regional_destroy(r); - return; - } - if(!r) return; - regional_free_all(r); - log_assert(r->next == NULL); - r->next = (char*)alloc->reg_list; - alloc->reg_list = r; - alloc->num_reg_blocks++; -} - -void -alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), - void* arg) -{ - alloc->cleanup = cleanup; - alloc->cleanup_arg = arg; -} - -/** global debug value to keep track of total memory mallocs */ -size_t unbound_mem_alloc = 0; -/** global debug value to keep track of total memory frees */ -size_t unbound_mem_freed = 0; -#ifdef UNBOUND_ALLOC_STATS -/** special value to know if the memory is being tracked */ -uint64_t mem_special = (uint64_t)0xfeed43327766abcdLL; -#ifdef malloc -#undef malloc -#endif -/** malloc with stats */ -void *unbound_stat_malloc(size_t size) -{ - void* res; - if(size == 0) size = 1; - log_assert(size <= SIZE_MAX-16); - res = malloc(size+16); - if(!res) return NULL; - unbound_mem_alloc += size; - log_info("stat %p=malloc(%u)", res+16, (unsigned)size); - memcpy(res, &size, sizeof(size)); - memcpy(res+8, &mem_special, sizeof(mem_special)); - return res+16; -} -#ifdef calloc -#undef calloc -#endif -#ifndef INT_MAX -#define INT_MAX (((int)-1)>>1) -#endif -/** calloc with stats */ -void *unbound_stat_calloc(size_t nmemb, size_t size) -{ - size_t s; - void* res; - if(nmemb != 0 && INT_MAX/nmemb < size) - return NULL; /* integer overflow check */ - s = (nmemb*size==0)?(size_t)1:nmemb*size; - log_assert(s <= SIZE_MAX-16); - res = calloc(1, s+16); - if(!res) return NULL; - log_info("stat %p=calloc(%u, %u)", res+16, (unsigned)nmemb, (unsigned)size); - unbound_mem_alloc += s; - memcpy(res, &s, sizeof(s)); - memcpy(res+8, &mem_special, sizeof(mem_special)); - return res+16; -} -#ifdef free -#undef free -#endif -/** free with stats */ -void unbound_stat_free(void *ptr) -{ - size_t s; - if(!ptr) return; - if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) { - free(ptr); - return; - } - ptr-=16; - memcpy(&s, ptr, sizeof(s)); - log_info("stat free(%p) size %u", ptr+16, (unsigned)s); - memset(ptr+8, 0, 8); - unbound_mem_freed += s; - free(ptr); -} -#ifdef realloc -#undef realloc -#endif -/** realloc with stats */ -void *unbound_stat_realloc(void *ptr, size_t size) -{ - size_t cursz; - void* res; - if(!ptr) return unbound_stat_malloc(size); - if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) { - return realloc(ptr, size); - } - if(size==0) { - unbound_stat_free(ptr); - return NULL; - } - ptr -= 16; - memcpy(&cursz, ptr, sizeof(cursz)); - if(cursz == size) { - /* nothing changes */ - return ptr; - } - log_assert(size <= SIZE_MAX-16); - res = malloc(size+16); - if(!res) return NULL; - unbound_mem_alloc += size; - unbound_mem_freed += cursz; - log_info("stat realloc(%p, %u) from %u", ptr+16, (unsigned)size, (unsigned)cursz); - if(cursz > size) { - memcpy(res+16, ptr+16, size); - } else if(size > cursz) { - memcpy(res+16, ptr+16, cursz); - } - memset(ptr+8, 0, 8); - free(ptr); - memcpy(res, &size, sizeof(size)); - memcpy(res+8, &mem_special, sizeof(mem_special)); - return res+16; -} - -/** log to file where alloc was done */ -void *unbound_stat_malloc_log(size_t size, const char* file, int line, - const char* func) -{ - log_info("%s:%d %s malloc(%u)", file, line, func, (unsigned)size); - return unbound_stat_malloc(size); -} - -/** log to file where alloc was done */ -void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, - int line, const char* func) -{ - log_info("%s:%d %s calloc(%u, %u)", file, line, func, - (unsigned) nmemb, (unsigned)size); - return unbound_stat_calloc(nmemb, size); -} - -/** log to file where free was done */ -void unbound_stat_free_log(void *ptr, const char* file, int line, - const char* func) -{ - if(ptr && memcmp(ptr-8, &mem_special, sizeof(mem_special)) == 0) { - size_t s; - memcpy(&s, ptr-16, sizeof(s)); - log_info("%s:%d %s free(%p) size %u", - file, line, func, ptr, (unsigned)s); - } else - log_info("%s:%d %s unmatched free(%p)", file, line, func, ptr); - unbound_stat_free(ptr); -} - -/** log to file where alloc was done */ -void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, - int line, const char* func) -{ - log_info("%s:%d %s realloc(%p, %u)", file, line, func, - ptr, (unsigned)size); - return unbound_stat_realloc(ptr, size); -} - -#endif /* UNBOUND_ALLOC_STATS */ -#ifdef UNBOUND_ALLOC_LITE -#undef malloc -#undef calloc -#undef free -#undef realloc -/** length of prefix and suffix */ -static size_t lite_pad = 16; -/** prefix value to check */ -static char* lite_pre = "checkfront123456"; -/** suffix value to check */ -static char* lite_post= "checkafter123456"; - -void *unbound_stat_malloc_lite(size_t size, const char* file, int line, - const char* func) -{ - /* [prefix .. len .. actual data .. suffix] */ - void* res; - log_assert(size <= SIZE_MAX-(lite_pad*2+sizeof(size_t))); - res = malloc(size+lite_pad*2+sizeof(size_t)); - if(!res) return NULL; - memmove(res, lite_pre, lite_pad); - memmove(res+lite_pad, &size, sizeof(size_t)); - memset(res+lite_pad+sizeof(size_t), 0x1a, size); /* init the memory */ - memmove(res+lite_pad+size+sizeof(size_t), lite_post, lite_pad); - return res+lite_pad+sizeof(size_t); -} - -void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file, - int line, const char* func) -{ - size_t req; - void* res; - if(nmemb != 0 && INT_MAX/nmemb < size) - return NULL; /* integer overflow check */ - req = nmemb * size; - log_assert(req <= SIZE_MAX-(lite_pad*2+sizeof(size_t))); - res = malloc(req+lite_pad*2+sizeof(size_t)); - if(!res) return NULL; - memmove(res, lite_pre, lite_pad); - memmove(res+lite_pad, &req, sizeof(size_t)); - memset(res+lite_pad+sizeof(size_t), 0, req); - memmove(res+lite_pad+req+sizeof(size_t), lite_post, lite_pad); - return res+lite_pad+sizeof(size_t); -} - -void unbound_stat_free_lite(void *ptr, const char* file, int line, - const char* func) -{ - void* real; - size_t orig = 0; - if(!ptr) return; - real = ptr-lite_pad-sizeof(size_t); - if(memcmp(real, lite_pre, lite_pad) != 0) { - log_err("free(): prefix failed %s:%d %s", file, line, func); - log_hex("prefix here", real, lite_pad); - log_hex(" should be", lite_pre, lite_pad); - fatal_exit("alloc assertion failed"); - } - memmove(&orig, real+lite_pad, sizeof(size_t)); - if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){ - log_err("free(): suffix failed %s:%d %s", file, line, func); - log_err("alloc size is %d", (int)orig); - log_hex("suffix here", real+lite_pad+orig+sizeof(size_t), - lite_pad); - log_hex(" should be", lite_post, lite_pad); - fatal_exit("alloc assertion failed"); - } - memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */ - free(real); -} - -void *unbound_stat_realloc_lite(void *ptr, size_t size, const char* file, - int line, const char* func) -{ - /* always free and realloc (no growing) */ - void* real, *newa; - size_t orig = 0; - if(!ptr) { - /* like malloc() */ - return unbound_stat_malloc_lite(size, file, line, func); - } - if(!size) { - /* like free() */ - unbound_stat_free_lite(ptr, file, line, func); - return NULL; - } - /* change allocation size and copy */ - real = ptr-lite_pad-sizeof(size_t); - if(memcmp(real, lite_pre, lite_pad) != 0) { - log_err("realloc(): prefix failed %s:%d %s", file, line, func); - log_hex("prefix here", real, lite_pad); - log_hex(" should be", lite_pre, lite_pad); - fatal_exit("alloc assertion failed"); - } - memmove(&orig, real+lite_pad, sizeof(size_t)); - if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){ - log_err("realloc(): suffix failed %s:%d %s", file, line, func); - log_err("alloc size is %d", (int)orig); - log_hex("suffix here", real+lite_pad+orig+sizeof(size_t), - lite_pad); - log_hex(" should be", lite_post, lite_pad); - fatal_exit("alloc assertion failed"); - } - /* new alloc and copy over */ - newa = unbound_stat_malloc_lite(size, file, line, func); - if(!newa) - return NULL; - if(orig < size) - memmove(newa, ptr, orig); - else memmove(newa, ptr, size); - memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */ - free(real); - return newa; -} - -char* unbound_strdup_lite(const char* s, const char* file, int line, - const char* func) -{ - /* this routine is made to make sure strdup() uses the malloc_lite */ - size_t l = strlen(s)+1; - char* n = (char*)unbound_stat_malloc_lite(l, file, line, func); - if(!n) return NULL; - memmove(n, s, l); - return n; -} - -char* unbound_lite_wrapstr(char* s) -{ - char* n = unbound_strdup_lite(s, __FILE__, __LINE__, __func__); - free(s); - return n; -} - -#undef sldns_pkt2wire -sldns_status unbound_lite_pkt2wire(uint8_t **dest, const sldns_pkt *p, - size_t *size) -{ - uint8_t* md = NULL; - size_t ms = 0; - sldns_status s = sldns_pkt2wire(&md, p, &ms); - if(md) { - *dest = unbound_stat_malloc_lite(ms, __FILE__, __LINE__, - __func__); - *size = ms; - if(!*dest) { free(md); return LDNS_STATUS_MEM_ERR; } - memcpy(*dest, md, ms); - free(md); - } else { - *dest = NULL; - *size = 0; - } - return s; -} - -#undef i2d_DSA_SIG -int unbound_lite_i2d_DSA_SIG(DSA_SIG* dsasig, unsigned char** sig) -{ - unsigned char* n = NULL; - int r= i2d_DSA_SIG(dsasig, &n); - if(n) { - *sig = unbound_stat_malloc_lite((size_t)r, __FILE__, __LINE__, - __func__); - if(!*sig) return -1; - memcpy(*sig, n, (size_t)r); - free(n); - return r; - } - *sig = NULL; - return r; -} - -#endif /* UNBOUND_ALLOC_LITE */ diff --git a/crates/libunbound-sys/unbound/util/alloc.h b/crates/libunbound-sys/unbound/util/alloc.h deleted file mode 100644 index ee03b074..00000000 --- a/crates/libunbound-sys/unbound/util/alloc.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * util/alloc.h - memory allocation service. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains memory allocation functions. - * - * The reasons for this service are: - * o Avoid locking costs of getting global lock to call malloc(). - * o The packed rrset type needs to be kept on special freelists, - * so that they are reused for other packet rrset allocations. - * - */ - -#ifndef UTIL_ALLOC_H -#define UTIL_ALLOC_H - -#include "util/locks.h" -struct ub_packed_rrset_key; -struct regional; - -/** The special type, packed rrset. Not allowed to be used for other memory */ -typedef struct ub_packed_rrset_key alloc_special_type; -/** clean the special type. Pass pointer. */ -#define alloc_special_clean(x) (x)->id = 0; -/** access next pointer. (in available spot). Pass pointer. */ -#define alloc_special_next(x) ((alloc_special_type*)((x)->entry.overflow_next)) -/** set next pointer. (in available spot). Pass pointers. */ -#define alloc_set_special_next(x, y) \ - ((x)->entry.overflow_next) = (struct lruhash_entry*)(y); - -/** how many blocks to cache locally. */ -#define ALLOC_SPECIAL_MAX 10 - -/** - * Structure that provides allocation. Use one per thread. - * The one on top has a NULL super pointer. - */ -struct alloc_cache { - /** lock, only used for the super. */ - lock_quick_type lock; - /** global allocator above this one. NULL for none (malloc/free) */ - struct alloc_cache* super; - /** singly linked lists of special type. These are free for use. */ - alloc_special_type* quar; - /** number of items in quarantine. */ - size_t num_quar; - /** thread number for id creation */ - int thread_num; - /** next id number to pass out */ - uint64_t next_id; - /** last id number possible */ - uint64_t last_id; - /** what function to call to cleanup when last id is reached */ - void (*cleanup)(void*); - /** user arg for cleanup */ - void* cleanup_arg; - - /** how many regional blocks to keep back max */ - size_t max_reg_blocks; - /** how many regional blocks are kept now */ - size_t num_reg_blocks; - /** linked list of regional blocks, using regional->next */ - struct regional* reg_list; -}; - -/** - * Init alloc (zeroes the struct). - * @param alloc: this parameter is allocated by the caller. - * @param super: super to use (init that before with super_init). - * Pass this argument NULL to init the toplevel alloc structure. - * @param thread_num: thread number for id creation of special type. - */ -void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, - int thread_num); - -/** - * Free the alloc. Pushes all the cached items into the super structure. - * Or deletes them if alloc->super is NULL. - * Does not free the alloc struct itself (it was also allocated by caller). - * @param alloc: is almost zeroed on exit (except some stats). - */ -void alloc_clear(struct alloc_cache* alloc); - -/** - * Free the special alloced items. The rrset and message caches must be - * empty, there must be no more references to rrset pointers into the - * rrset cache. - * @param alloc: the special allocs are freed. - */ -void alloc_clear_special(struct alloc_cache* alloc); - -/** - * Get a new special_type element. - * @param alloc: where to alloc it. - * @return: memory block. Will not return NULL (instead fatal_exit). - * The block is zeroed. - */ -alloc_special_type* alloc_special_obtain(struct alloc_cache* alloc); - -/** - * Return special_type back to pool. - * The block is cleaned up (zeroed) which also invalidates the ID inside. - * @param alloc: where to alloc it. - * @param mem: block to free. - */ -void alloc_special_release(struct alloc_cache* alloc, alloc_special_type* mem); - -/** - * Set ID number of special type to a fresh new ID number. - * In case of ID number overflow, the rrset cache has to be cleared. - * @param alloc: the alloc cache - * @return: fresh id is returned. - */ -uint64_t alloc_get_id(struct alloc_cache* alloc); - -/** - * Get memory size of alloc cache, alloc structure including special types. - * @param alloc: on what alloc. - * @return size in bytes. - */ -size_t alloc_get_mem(struct alloc_cache* alloc); - -/** - * Print debug information (statistics). - * @param alloc: on what alloc. - */ -void alloc_stats(struct alloc_cache* alloc); - -/** - * Get a new regional for query states - * @param alloc: where to alloc it. - * @return regional for use or NULL on alloc failure. - */ -struct regional* alloc_reg_obtain(struct alloc_cache* alloc); - -/** - * Put regional for query states back into alloc cache. - * @param alloc: where to alloc it. - * @param r: regional to put back. - */ -void alloc_reg_release(struct alloc_cache* alloc, struct regional* r); - -/** - * Set cleanup on ID overflow callback function. This should remove all - * RRset ID references from the program. Clear the caches. - * @param alloc: the alloc - * @param cleanup: the callback function, called as cleanup(arg). - * @param arg: user argument to callback function. - */ -void alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), - void* arg); - -#ifdef UNBOUND_ALLOC_LITE -# include -# include -# ifdef HAVE_OPENSSL_SSL_H -# include -# endif -# define malloc(s) unbound_stat_malloc_lite(s, __FILE__, __LINE__, __func__) -# define calloc(n,s) unbound_stat_calloc_lite(n, s, __FILE__, __LINE__, __func__) -# define free(p) unbound_stat_free_lite(p, __FILE__, __LINE__, __func__) -# define realloc(p,s) unbound_stat_realloc_lite(p, s, __FILE__, __LINE__, __func__) -void *unbound_stat_malloc_lite(size_t size, const char* file, int line, - const char* func); -void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file, - int line, const char* func); -void unbound_stat_free_lite(void *ptr, const char* file, int line, - const char* func); -void *unbound_stat_realloc_lite(void *ptr, size_t size, const char* file, - int line, const char* func); -# ifdef strdup -# undef strdup -# endif -# define strdup(s) unbound_strdup_lite(s, __FILE__, __LINE__, __func__) -char* unbound_strdup_lite(const char* s, const char* file, int line, - const char* func); -char* unbound_lite_wrapstr(char* s); -# define sldns_rr2str(rr) unbound_lite_wrapstr(sldns_rr2str(rr)) -# define sldns_rdf2str(rdf) unbound_lite_wrapstr(sldns_rdf2str(rdf)) -# define sldns_rr_type2str(t) unbound_lite_wrapstr(sldns_rr_type2str(t)) -# define sldns_rr_class2str(c) unbound_lite_wrapstr(sldns_rr_class2str(c)) -# define sldns_rr_list2str(r) unbound_lite_wrapstr(sldns_rr_list2str(r)) -# define sldns_pkt2str(p) unbound_lite_wrapstr(sldns_pkt2str(p)) -# define sldns_pkt_rcode2str(r) unbound_lite_wrapstr(sldns_pkt_rcode2str(r)) -# define sldns_pkt2wire(a, r, s) unbound_lite_pkt2wire(a, r, s) -sldns_status unbound_lite_pkt2wire(uint8_t **dest, const sldns_pkt *p, size_t *size); -# define i2d_DSA_SIG(d, s) unbound_lite_i2d_DSA_SIG(d, s) -int unbound_lite_i2d_DSA_SIG(DSA_SIG* dsasig, unsigned char** sig); -#endif /* UNBOUND_ALLOC_LITE */ - -#endif /* UTIL_ALLOC_H */ diff --git a/crates/libunbound-sys/unbound/util/as112.c b/crates/libunbound-sys/unbound/util/as112.c deleted file mode 100644 index 6ee69404..00000000 --- a/crates/libunbound-sys/unbound/util/as112.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * util/as112.c - list of local zones. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file provides a list of lan zones. - */ - -#include "util/as112.h" - -static const char* as112_zone_array[] = { - "10.in-addr.arpa.", - "16.172.in-addr.arpa.", - "17.172.in-addr.arpa.", - "18.172.in-addr.arpa.", - "19.172.in-addr.arpa.", - "20.172.in-addr.arpa.", - "21.172.in-addr.arpa.", - "22.172.in-addr.arpa.", - "23.172.in-addr.arpa.", - "24.172.in-addr.arpa.", - "25.172.in-addr.arpa.", - "26.172.in-addr.arpa.", - "27.172.in-addr.arpa.", - "28.172.in-addr.arpa.", - "29.172.in-addr.arpa.", - "30.172.in-addr.arpa.", - "31.172.in-addr.arpa.", - "168.192.in-addr.arpa.", - "0.in-addr.arpa.", - "64.100.in-addr.arpa.", - "65.100.in-addr.arpa.", - "66.100.in-addr.arpa.", - "67.100.in-addr.arpa.", - "68.100.in-addr.arpa.", - "69.100.in-addr.arpa.", - "70.100.in-addr.arpa.", - "71.100.in-addr.arpa.", - "72.100.in-addr.arpa.", - "73.100.in-addr.arpa.", - "74.100.in-addr.arpa.", - "75.100.in-addr.arpa.", - "76.100.in-addr.arpa.", - "77.100.in-addr.arpa.", - "78.100.in-addr.arpa.", - "79.100.in-addr.arpa.", - "80.100.in-addr.arpa.", - "81.100.in-addr.arpa.", - "82.100.in-addr.arpa.", - "83.100.in-addr.arpa.", - "84.100.in-addr.arpa.", - "85.100.in-addr.arpa.", - "86.100.in-addr.arpa.", - "87.100.in-addr.arpa.", - "88.100.in-addr.arpa.", - "89.100.in-addr.arpa.", - "90.100.in-addr.arpa.", - "91.100.in-addr.arpa.", - "92.100.in-addr.arpa.", - "93.100.in-addr.arpa.", - "94.100.in-addr.arpa.", - "95.100.in-addr.arpa.", - "96.100.in-addr.arpa.", - "97.100.in-addr.arpa.", - "98.100.in-addr.arpa.", - "99.100.in-addr.arpa.", - "100.100.in-addr.arpa.", - "101.100.in-addr.arpa.", - "102.100.in-addr.arpa.", - "103.100.in-addr.arpa.", - "104.100.in-addr.arpa.", - "105.100.in-addr.arpa.", - "106.100.in-addr.arpa.", - "107.100.in-addr.arpa.", - "108.100.in-addr.arpa.", - "109.100.in-addr.arpa.", - "110.100.in-addr.arpa.", - "111.100.in-addr.arpa.", - "112.100.in-addr.arpa.", - "113.100.in-addr.arpa.", - "114.100.in-addr.arpa.", - "115.100.in-addr.arpa.", - "116.100.in-addr.arpa.", - "117.100.in-addr.arpa.", - "118.100.in-addr.arpa.", - "119.100.in-addr.arpa.", - "120.100.in-addr.arpa.", - "121.100.in-addr.arpa.", - "122.100.in-addr.arpa.", - "123.100.in-addr.arpa.", - "124.100.in-addr.arpa.", - "125.100.in-addr.arpa.", - "126.100.in-addr.arpa.", - "127.100.in-addr.arpa.", - "254.169.in-addr.arpa.", - "2.0.192.in-addr.arpa.", - "100.51.198.in-addr.arpa.", - "113.0.203.in-addr.arpa.", - "255.255.255.255.in-addr.arpa.", - "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", - "d.f.ip6.arpa.", - "8.e.f.ip6.arpa.", - "9.e.f.ip6.arpa.", - "a.e.f.ip6.arpa.", - "b.e.f.ip6.arpa.", - "8.b.d.0.1.0.0.2.ip6.arpa.", - 0 -}; - -const char** as112_zones = as112_zone_array; diff --git a/crates/libunbound-sys/unbound/util/as112.h b/crates/libunbound-sys/unbound/util/as112.h deleted file mode 100644 index 7d0329e8..00000000 --- a/crates/libunbound-sys/unbound/util/as112.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * util/as112.c - list of local zones. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file provides a list of lan zones - */ - -#ifndef UTIL_AS112_H -#define UTIL_AS112_H - -/** - * Array of text-format domain names of the AS112 zones. - * The array ends with NULL. "AS112" is a service on the internet that - * that this array is named after. The names in this list (or some of them) - * are null-routed by this service to avoid load on central servers caused by - * mistaken lookups for local content on the global internet. - * - * This is the list of names that unbound should not normally be sending - * on towards the internet, because they are local-use. - */ -extern const char** as112_zones; - -#endif diff --git a/crates/libunbound-sys/unbound/util/config_file.c b/crates/libunbound-sys/unbound/util/config_file.c deleted file mode 100644 index 45409634..00000000 --- a/crates/libunbound-sys/unbound/util/config_file.c +++ /dev/null @@ -1,2711 +0,0 @@ -/* - * util/config_file.c - reads and stores the config file for unbound. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for the config file. - */ - -#include "config.h" -#include -#include -#ifdef HAVE_TIME_H -#include -#endif -#include "util/log.h" -#include "util/configyyrename.h" -#include "util/config_file.h" -#include "util/configparser.h" -#include "util/net_help.h" -#include "util/data/msgparse.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/fptr_wlist.h" -#include "util/data/dname.h" -#include "util/random.h" -#include "util/rtt.h" -#include "services/cache/infra.h" -#include "sldns/wire2str.h" -#include "sldns/parseutil.h" -#include "iterator/iterator.h" -#ifdef HAVE_GLOB_H -# include -#endif -#ifdef CLIENT_SUBNET -#include "edns-subnet/edns-subnet.h" -#endif -#ifdef HAVE_PWD_H -#include -#endif - -/** from cfg username, after daemonize setup performed */ -uid_t cfg_uid = (uid_t)-1; -/** from cfg username, after daemonize setup performed */ -gid_t cfg_gid = (gid_t)-1; -/** for debug allow small timeout values for fast rollovers */ -int autr_permit_small_holddown = 0; -/** size (in bytes) of stream wait buffers max */ -size_t stream_wait_max = 4 * 1024 * 1024; -size_t http2_query_buffer_max = 4 * 1024 * 1024; -size_t http2_response_buffer_max = 4 * 1024 * 1024; - -/** global config during parsing */ -struct config_parser_state* cfg_parser = 0; - -/** init ports possible for use */ -static void init_outgoing_availports(int* array, int num); - -/** init cookie with random data */ -static void init_cookie_secret(uint8_t* cookie_secret, size_t cookie_secret_len); - -struct config_file* -config_create(void) -{ - struct config_file* cfg; - cfg = (struct config_file*)calloc(1, sizeof(struct config_file)); - if(!cfg) - return NULL; - /* the defaults if no config is present */ - cfg->verbosity = 1; - cfg->stat_interval = 0; - cfg->stat_cumulative = 0; - cfg->stat_extended = 0; - cfg->stat_inhibit_zero = 1; - cfg->num_threads = 1; - cfg->port = UNBOUND_DNS_PORT; - cfg->do_ip4 = 1; - cfg->do_ip6 = 1; - cfg->do_udp = 1; - cfg->do_tcp = 1; - cfg->tcp_reuse_timeout = 60 * 1000; /* 60s in milisecs */ - cfg->max_reuse_tcp_queries = 200; - cfg->tcp_upstream = 0; - cfg->udp_upstream_without_downstream = 0; - cfg->tcp_mss = 0; - cfg->outgoing_tcp_mss = 0; - cfg->tcp_idle_timeout = 30 * 1000; /* 30s in millisecs */ - cfg->tcp_auth_query_timeout = 3 * 1000; /* 3s in millisecs */ - cfg->do_tcp_keepalive = 0; - cfg->tcp_keepalive_timeout = 120 * 1000; /* 120s in millisecs */ - cfg->sock_queue_timeout = 0; /* do not check timeout */ - cfg->ssl_service_key = NULL; - cfg->ssl_service_pem = NULL; - cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT; - cfg->ssl_upstream = 0; - cfg->tls_cert_bundle = NULL; - cfg->tls_win_cert = 0; - cfg->tls_use_sni = 1; - cfg->https_port = UNBOUND_DNS_OVER_HTTPS_PORT; - if(!(cfg->http_endpoint = strdup("/dns-query"))) goto error_exit; - cfg->http_max_streams = 100; - cfg->http_query_buffer_size = 4*1024*1024; - cfg->http_response_buffer_size = 4*1024*1024; - cfg->http_nodelay = 1; - cfg->use_syslog = 1; - cfg->log_identity = NULL; /* changed later with argv[0] */ - cfg->log_time_ascii = 0; - cfg->log_queries = 0; - cfg->log_replies = 0; - cfg->log_tag_queryreply = 0; - cfg->log_local_actions = 0; - cfg->log_servfail = 0; -#ifndef USE_WINSOCK -# ifdef USE_MINI_EVENT - /* select max 1024 sockets */ - cfg->outgoing_num_ports = 960; - cfg->num_queries_per_thread = 512; -# else - /* libevent can use many sockets */ - cfg->outgoing_num_ports = 4096; - cfg->num_queries_per_thread = 1024; -# endif - cfg->outgoing_num_tcp = 10; - cfg->incoming_num_tcp = 10; -#else - cfg->outgoing_num_ports = 48; /* windows is limited in num fds */ - cfg->num_queries_per_thread = 24; - cfg->outgoing_num_tcp = 2; /* leaves 64-52=12 for: 4if,1stop,thread4 */ - cfg->incoming_num_tcp = 2; -#endif - cfg->stream_wait_size = 4 * 1024 * 1024; - cfg->edns_buffer_size = 1232; /* from DNS flagday recommendation */ - cfg->msg_buffer_size = 65552; /* 64 k + a small margin */ - cfg->msg_cache_size = 4 * 1024 * 1024; - cfg->msg_cache_slabs = 4; - cfg->jostle_time = 200; - cfg->rrset_cache_size = 4 * 1024 * 1024; - cfg->rrset_cache_slabs = 4; - cfg->host_ttl = 900; - cfg->bogus_ttl = 60; - cfg->min_ttl = 0; - cfg->max_ttl = 3600 * 24; - cfg->max_negative_ttl = 3600; - cfg->prefetch = 0; - cfg->prefetch_key = 0; - cfg->deny_any = 0; - cfg->infra_cache_slabs = 4; - cfg->infra_cache_numhosts = 10000; - cfg->infra_cache_min_rtt = 50; - cfg->infra_cache_max_rtt = 120000; - cfg->infra_keep_probing = 0; - cfg->delay_close = 0; - cfg->udp_connect = 1; - if(!(cfg->outgoing_avail_ports = (int*)calloc(65536, sizeof(int)))) - goto error_exit; - init_outgoing_availports(cfg->outgoing_avail_ports, 65536); - if(!(cfg->username = strdup(UB_USERNAME))) goto error_exit; -#ifdef HAVE_CHROOT - if(!(cfg->chrootdir = strdup(CHROOT_DIR))) goto error_exit; -#endif - if(!(cfg->directory = strdup(RUN_DIR))) goto error_exit; - if(!(cfg->logfile = strdup(""))) goto error_exit; - if(!(cfg->pidfile = strdup(PIDFILE))) goto error_exit; - if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit; - cfg->fast_server_permil = 0; - cfg->fast_server_num = 3; - cfg->donotqueryaddrs = NULL; - cfg->donotquery_localhost = 1; - cfg->root_hints = NULL; - cfg->use_systemd = 0; - cfg->do_daemonize = 1; - cfg->if_automatic = 0; - cfg->if_automatic_ports = NULL; - cfg->so_rcvbuf = 0; - cfg->so_sndbuf = 0; - cfg->so_reuseport = REUSEPORT_DEFAULT; - cfg->ip_transparent = 0; - cfg->ip_freebind = 0; - cfg->ip_dscp = 0; - cfg->num_ifs = 0; - cfg->ifs = NULL; - cfg->num_out_ifs = 0; - cfg->out_ifs = NULL; - cfg->stubs = NULL; - cfg->forwards = NULL; - cfg->auths = NULL; -#ifdef CLIENT_SUBNET - cfg->client_subnet = NULL; - cfg->client_subnet_zone = NULL; - cfg->client_subnet_opcode = LDNS_EDNS_CLIENT_SUBNET; - cfg->client_subnet_always_forward = 0; - cfg->max_client_subnet_ipv4 = 24; - cfg->max_client_subnet_ipv6 = 56; - cfg->min_client_subnet_ipv4 = 0; - cfg->min_client_subnet_ipv6 = 0; - cfg->max_ecs_tree_size_ipv4 = 100; - cfg->max_ecs_tree_size_ipv6 = 100; -#endif - cfg->views = NULL; - cfg->acls = NULL; - cfg->tcp_connection_limits = NULL; - cfg->harden_short_bufsize = 1; - cfg->harden_large_queries = 0; - cfg->harden_glue = 1; - cfg->harden_dnssec_stripped = 1; - cfg->harden_below_nxdomain = 1; - cfg->harden_referral_path = 0; - cfg->harden_algo_downgrade = 0; - cfg->harden_unknown_additional = 0; - cfg->use_caps_bits_for_id = 0; - cfg->caps_whitelist = NULL; - cfg->private_address = NULL; - cfg->private_domain = NULL; - cfg->unwanted_threshold = 0; - cfg->hide_identity = 0; - cfg->hide_version = 0; - cfg->hide_trustanchor = 0; - cfg->hide_http_user_agent = 0; - cfg->identity = NULL; - cfg->version = NULL; - cfg->http_user_agent = NULL; - cfg->nsid_cfg_str = NULL; - cfg->nsid = NULL; - cfg->nsid_len = 0; - cfg->auto_trust_anchor_file_list = NULL; - cfg->trust_anchor_file_list = NULL; - cfg->trust_anchor_list = NULL; - cfg->trusted_keys_file_list = NULL; - cfg->trust_anchor_signaling = 1; - cfg->root_key_sentinel = 1; - cfg->domain_insecure = NULL; - cfg->val_date_override = 0; - cfg->val_sig_skew_min = 3600; /* at least daylight savings trouble */ - cfg->val_sig_skew_max = 86400; /* at most timezone settings trouble */ - cfg->val_max_restart = 5; - cfg->val_clean_additional = 1; - cfg->val_log_level = 0; - cfg->val_log_squelch = 0; - cfg->val_permissive_mode = 0; - cfg->aggressive_nsec = 1; - cfg->ignore_cd = 0; - cfg->serve_expired = 0; - cfg->serve_expired_ttl = 0; - cfg->serve_expired_ttl_reset = 0; - cfg->serve_expired_reply_ttl = 30; - cfg->serve_expired_client_timeout = 0; - cfg->ede_serve_expired = 0; - cfg->serve_original_ttl = 0; - cfg->zonemd_permissive_mode = 0; - cfg->add_holddown = 30*24*3600; - cfg->del_holddown = 30*24*3600; - cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */ - cfg->permit_small_holddown = 0; - cfg->key_cache_size = 4 * 1024 * 1024; - cfg->key_cache_slabs = 4; - cfg->neg_cache_size = 1 * 1024 * 1024; - cfg->local_zones = NULL; - cfg->local_zones_nodefault = NULL; -#ifdef USE_IPSET - cfg->local_zones_ipset = NULL; -#endif - cfg->local_zones_disable_default = 0; - cfg->local_data = NULL; - cfg->local_zone_overrides = NULL; - cfg->unblock_lan_zones = 0; - cfg->insecure_lan_zones = 0; - cfg->python_script = NULL; - cfg->dynlib_file = NULL; - cfg->remote_control_enable = 0; - cfg->control_ifs.first = NULL; - cfg->control_ifs.last = NULL; - cfg->control_port = UNBOUND_CONTROL_PORT; - cfg->control_use_cert = 1; - cfg->minimal_responses = 1; - cfg->rrset_roundrobin = 1; - cfg->unknown_server_time_limit = 376; - cfg->max_udp_size = 1232; /* value taken from edns_buffer_size */ - if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key"))) - goto error_exit; - if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem"))) - goto error_exit; - if(!(cfg->control_key_file = strdup(RUN_DIR"/unbound_control.key"))) - goto error_exit; - if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem"))) - goto error_exit; - -#ifdef CLIENT_SUBNET - if(!(cfg->module_conf = strdup("subnetcache validator iterator"))) goto error_exit; -#else - if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit; -#endif - if(!(cfg->val_nsec3_key_iterations = - strdup("1024 150 2048 150 4096 150"))) goto error_exit; -#if defined(DNSTAP_SOCKET_PATH) - if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH))) - goto error_exit; -#endif - cfg->dnstap_bidirectional = 1; - cfg->dnstap_tls = 1; - cfg->disable_dnssec_lame_check = 0; - cfg->ip_ratelimit_cookie = 0; - cfg->ip_ratelimit = 0; - cfg->ratelimit = 0; - cfg->ip_ratelimit_slabs = 4; - cfg->ratelimit_slabs = 4; - cfg->ip_ratelimit_size = 4*1024*1024; - cfg->ratelimit_size = 4*1024*1024; - cfg->ratelimit_for_domain = NULL; - cfg->ratelimit_below_domain = NULL; - cfg->ip_ratelimit_factor = 10; - cfg->ratelimit_factor = 10; - cfg->ip_ratelimit_backoff = 0; - cfg->ratelimit_backoff = 0; - cfg->outbound_msg_retry = 5; - cfg->max_sent_count = 32; - cfg->max_query_restarts = 11; - cfg->qname_minimisation = 1; - cfg->qname_minimisation_strict = 0; - cfg->shm_enable = 0; - cfg->shm_key = 11777; - cfg->edns_client_strings = NULL; - cfg->edns_client_string_opcode = 65001; - cfg->dnscrypt = 0; - cfg->dnscrypt_port = 0; - cfg->dnscrypt_provider = NULL; - cfg->dnscrypt_provider_cert = NULL; - cfg->dnscrypt_provider_cert_rotated = NULL; - cfg->dnscrypt_secret_key = NULL; - cfg->dnscrypt_shared_secret_cache_size = 4*1024*1024; - cfg->dnscrypt_shared_secret_cache_slabs = 4; - cfg->dnscrypt_nonce_cache_size = 4*1024*1024; - cfg->dnscrypt_nonce_cache_slabs = 4; - cfg->pad_responses = 1; - cfg->pad_responses_block_size = 468; /* from RFC8467 */ - cfg->pad_queries = 1; - cfg->pad_queries_block_size = 128; /* from RFC8467 */ -#ifdef USE_IPSECMOD - cfg->ipsecmod_enabled = 1; - cfg->ipsecmod_ignore_bogus = 0; - cfg->ipsecmod_hook = NULL; - cfg->ipsecmod_max_ttl = 3600; - cfg->ipsecmod_whitelist = NULL; - cfg->ipsecmod_strict = 0; -#endif - cfg->do_answer_cookie = 0; - memset(cfg->cookie_secret, 0, sizeof(cfg->cookie_secret)); - cfg->cookie_secret_len = 16; - init_cookie_secret(cfg->cookie_secret, cfg->cookie_secret_len); -#ifdef USE_CACHEDB - if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit; - if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit; -#ifdef USE_REDIS - if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit; - cfg->redis_server_path = NULL; - cfg->redis_server_password = NULL; - cfg->redis_timeout = 100; - cfg->redis_server_port = 6379; - cfg->redis_expire_records = 0; -#endif /* USE_REDIS */ -#endif /* USE_CACHEDB */ -#ifdef USE_IPSET - cfg->ipset_name_v4 = NULL; - cfg->ipset_name_v6 = NULL; -#endif - cfg->ede = 0; - return cfg; -error_exit: - config_delete(cfg); - return NULL; -} - -struct config_file* config_create_forlib(void) -{ - struct config_file* cfg = config_create(); - if(!cfg) return NULL; - /* modifications for library use, less verbose, less memory */ - free(cfg->chrootdir); - cfg->chrootdir = NULL; - cfg->verbosity = 0; - cfg->outgoing_num_ports = 16; /* in library use, this is 'reasonable' - and probably within the ulimit(maxfds) of the user */ - cfg->outgoing_num_tcp = 2; - cfg->msg_cache_size = 1024*1024; - cfg->msg_cache_slabs = 1; - cfg->rrset_cache_size = 1024*1024; - cfg->rrset_cache_slabs = 1; - cfg->infra_cache_slabs = 1; - cfg->use_syslog = 0; - cfg->key_cache_size = 1024*1024; - cfg->key_cache_slabs = 1; - cfg->neg_cache_size = 100 * 1024; - cfg->donotquery_localhost = 0; /* allow, so that you can ask a - forward nameserver running on localhost */ - cfg->val_log_level = 2; /* to fill why_bogus with */ - cfg->val_log_squelch = 1; - cfg->minimal_responses = 0; - cfg->harden_short_bufsize = 1; - return cfg; -} - -/** check that the value passed is >= 0 */ -#define IS_NUMBER_OR_ZERO \ - if(atoi(val) == 0 && strcmp(val, "0") != 0) return 0 -/** check that the value passed is > 0 */ -#define IS_NONZERO_NUMBER \ - if(atoi(val) == 0) return 0 -/** check that the value passed is not 0 and a power of 2 */ -#define IS_POW2_NUMBER \ - if(atoi(val) == 0 || !is_pow2((size_t)atoi(val))) return 0 -/** check that the value passed is yes or no */ -#define IS_YES_OR_NO \ - if(strcmp(val, "yes") != 0 && strcmp(val, "no") != 0) return 0 -/** put integer_or_zero into variable */ -#define S_NUMBER_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ - { IS_NUMBER_OR_ZERO; cfg->var = atoi(val); } -/** put integer_nonzero into variable */ -#define S_NUMBER_NONZERO(str, var) if(strcmp(opt, str) == 0) \ - { IS_NONZERO_NUMBER; cfg->var = atoi(val); } -/** put integer_or_zero into unsigned */ -#define S_UNSIGNED_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ - { IS_NUMBER_OR_ZERO; cfg->var = (unsigned)atoi(val); } -/** put integer_or_zero into size_t */ -#define S_SIZET_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ - { IS_NUMBER_OR_ZERO; cfg->var = (size_t)atoi(val); } -/** put integer_nonzero into size_t */ -#define S_SIZET_NONZERO(str, var) if(strcmp(opt, str) == 0) \ - { IS_NONZERO_NUMBER; cfg->var = (size_t)atoi(val); } -/** put yesno into variable */ -#define S_YNO(str, var) if(strcmp(opt, str) == 0) \ - { IS_YES_OR_NO; cfg->var = (strcmp(val, "yes") == 0); } -/** put memsize into variable */ -#define S_MEMSIZE(str, var) if(strcmp(opt, str)==0) \ - { return cfg_parse_memsize(val, &cfg->var); } -/** put pow2 number into variable */ -#define S_POW2(str, var) if(strcmp(opt, str)==0) \ - { IS_POW2_NUMBER; cfg->var = (size_t)atoi(val); } -/** put string into variable */ -#define S_STR(str, var) if(strcmp(opt, str)==0) \ - { free(cfg->var); return (cfg->var = strdup(val)) != NULL; } -/** put string into strlist */ -#define S_STRLIST(str, var) if(strcmp(opt, str)==0) \ - { return cfg_strlist_insert(&cfg->var, strdup(val)); } -/** put string into strlist if not present yet*/ -#define S_STRLIST_UNIQ(str, var) if(strcmp(opt, str)==0) \ - { if(cfg_strlist_find(cfg->var, val)) { return 0;} \ - return cfg_strlist_insert(&cfg->var, strdup(val)); } -/** append string to strlist */ -#define S_STRLIST_APPEND(str, var) if(strcmp(opt, str)==0) \ - { return cfg_strlist_append(&cfg->var, strdup(val)); } - -int config_set_option(struct config_file* cfg, const char* opt, - const char* val) -{ - char buf[64]; - if(!opt) return 0; - if(opt[strlen(opt)-1] != ':' && strlen(opt)+2stat_interval = 0; - else if(atoi(val) == 0) - return 0; - else cfg->stat_interval = atoi(val); - } else if(strcmp(opt, "num-threads:") == 0) { - /* not supported, library must have 1 thread in bgworker */ - return 0; - } else if(strcmp(opt, "outgoing-port-permit:") == 0) { - return cfg_mark_ports(val, 1, - cfg->outgoing_avail_ports, 65536); - } else if(strcmp(opt, "outgoing-port-avoid:") == 0) { - return cfg_mark_ports(val, 0, - cfg->outgoing_avail_ports, 65536); - } else if(strcmp(opt, "local-zone:") == 0) { - return cfg_parse_local_zone(cfg, val); - } else if(strcmp(opt, "val-override-date:") == 0) { - if(strcmp(val, "") == 0 || strcmp(val, "0") == 0) { - cfg->val_date_override = 0; - } else if(strlen(val) == 14) { - cfg->val_date_override = cfg_convert_timeval(val); - return cfg->val_date_override != 0; - } else { - if(atoi(val) == 0) return 0; - cfg->val_date_override = (uint32_t)atoi(val); - } - } else if(strcmp(opt, "local-data-ptr:") == 0) { - char* ptr = cfg_ptr_reverse((char*)opt); - return cfg_strlist_insert(&cfg->local_data, ptr); - } else if(strcmp(opt, "logfile:") == 0) { - cfg->use_syslog = 0; - free(cfg->logfile); - return (cfg->logfile = strdup(val)) != NULL; - } - else if(strcmp(opt, "log-time-ascii:") == 0) - { IS_YES_OR_NO; cfg->log_time_ascii = (strcmp(val, "yes") == 0); - log_set_time_asc(cfg->log_time_ascii); } - else S_SIZET_NONZERO("max-udp-size:", max_udp_size) - else S_YNO("use-syslog:", use_syslog) - else S_STR("log-identity:", log_identity) - else S_YNO("extended-statistics:", stat_extended) - else S_YNO("statistics-inhibit-zero:", stat_inhibit_zero) - else S_YNO("statistics-cumulative:", stat_cumulative) - else S_YNO("shm-enable:", shm_enable) - else S_NUMBER_OR_ZERO("shm-key:", shm_key) - else S_YNO("do-ip4:", do_ip4) - else S_YNO("do-ip6:", do_ip6) - else S_YNO("do-udp:", do_udp) - else S_YNO("do-tcp:", do_tcp) - else S_YNO("prefer-ip4:", prefer_ip4) - else S_YNO("prefer-ip6:", prefer_ip6) - else S_YNO("tcp-upstream:", tcp_upstream) - else S_YNO("udp-upstream-without-downstream:", - udp_upstream_without_downstream) - else S_NUMBER_NONZERO("tcp-mss:", tcp_mss) - else S_NUMBER_NONZERO("outgoing-tcp-mss:", outgoing_tcp_mss) - else S_NUMBER_NONZERO("tcp-auth-query-timeout:", tcp_auth_query_timeout) - else S_NUMBER_NONZERO("tcp-idle-timeout:", tcp_idle_timeout) - else S_NUMBER_NONZERO("max-reuse-tcp-queries:", max_reuse_tcp_queries) - else S_NUMBER_NONZERO("tcp-reuse-timeout:", tcp_reuse_timeout) - else S_YNO("edns-tcp-keepalive:", do_tcp_keepalive) - else S_NUMBER_NONZERO("edns-tcp-keepalive-timeout:", tcp_keepalive_timeout) - else S_NUMBER_OR_ZERO("sock-queue-timeout:", sock_queue_timeout) - else S_YNO("ssl-upstream:", ssl_upstream) - else S_YNO("tls-upstream:", ssl_upstream) - else S_STR("ssl-service-key:", ssl_service_key) - else S_STR("tls-service-key:", ssl_service_key) - else S_STR("ssl-service-pem:", ssl_service_pem) - else S_STR("tls-service-pem:", ssl_service_pem) - else S_NUMBER_NONZERO("ssl-port:", ssl_port) - else S_NUMBER_NONZERO("tls-port:", ssl_port) - else S_STR("ssl-cert-bundle:", tls_cert_bundle) - else S_STR("tls-cert-bundle:", tls_cert_bundle) - else S_YNO("tls-win-cert:", tls_win_cert) - else S_YNO("tls-system-cert:", tls_win_cert) - else S_STRLIST("additional-ssl-port:", tls_additional_port) - else S_STRLIST("additional-tls-port:", tls_additional_port) - else S_STRLIST("tls-additional-ports:", tls_additional_port) - else S_STRLIST("tls-additional-port:", tls_additional_port) - else S_STRLIST_APPEND("tls-session-ticket-keys:", tls_session_ticket_keys) - else S_STR("tls-ciphers:", tls_ciphers) - else S_STR("tls-ciphersuites:", tls_ciphersuites) - else S_YNO("tls-use-sni:", tls_use_sni) - else S_NUMBER_NONZERO("https-port:", https_port) - else S_STR("http-endpoint:", http_endpoint) - else S_NUMBER_NONZERO("http-max-streams:", http_max_streams) - else S_MEMSIZE("http-query-buffer-size:", http_query_buffer_size) - else S_MEMSIZE("http-response-buffer-size:", http_response_buffer_size) - else S_YNO("http-nodelay:", http_nodelay) - else S_YNO("http-notls-downstream:", http_notls_downstream) - else S_YNO("interface-automatic:", if_automatic) - else S_STR("interface-automatic-ports:", if_automatic_ports) - else S_YNO("use-systemd:", use_systemd) - else S_YNO("do-daemonize:", do_daemonize) - else S_NUMBER_NONZERO("port:", port) - else S_NUMBER_NONZERO("outgoing-range:", outgoing_num_ports) - else S_SIZET_OR_ZERO("outgoing-num-tcp:", outgoing_num_tcp) - else S_SIZET_OR_ZERO("incoming-num-tcp:", incoming_num_tcp) - else S_MEMSIZE("stream-wait-size:", stream_wait_size) - else S_SIZET_NONZERO("edns-buffer-size:", edns_buffer_size) - else S_SIZET_NONZERO("msg-buffer-size:", msg_buffer_size) - else S_MEMSIZE("msg-cache-size:", msg_cache_size) - else S_POW2("msg-cache-slabs:", msg_cache_slabs) - else S_SIZET_NONZERO("num-queries-per-thread:",num_queries_per_thread) - else S_SIZET_OR_ZERO("jostle-timeout:", jostle_time) - else S_MEMSIZE("so-rcvbuf:", so_rcvbuf) - else S_MEMSIZE("so-sndbuf:", so_sndbuf) - else S_YNO("so-reuseport:", so_reuseport) - else S_YNO("ip-transparent:", ip_transparent) - else S_YNO("ip-freebind:", ip_freebind) - else S_NUMBER_OR_ZERO("ip-dscp:", ip_dscp) - else S_MEMSIZE("rrset-cache-size:", rrset_cache_size) - else S_POW2("rrset-cache-slabs:", rrset_cache_slabs) - else S_YNO("prefetch:", prefetch) - else S_YNO("prefetch-key:", prefetch_key) - else S_YNO("deny-any:", deny_any) - else if(strcmp(opt, "cache-max-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->max_ttl = atoi(val); MAX_TTL=(time_t)cfg->max_ttl;} - else if(strcmp(opt, "cache-max-negative-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->max_negative_ttl = atoi(val); MAX_NEG_TTL=(time_t)cfg->max_negative_ttl;} - else if(strcmp(opt, "cache-min-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->min_ttl = atoi(val); MIN_TTL=(time_t)cfg->min_ttl;} - else if(strcmp(opt, "infra-cache-min-rtt:") == 0) { - IS_NUMBER_OR_ZERO; cfg->infra_cache_min_rtt = atoi(val); - RTT_MIN_TIMEOUT=cfg->infra_cache_min_rtt; - } - else if(strcmp(opt, "infra-cache-max-rtt:") == 0) { - IS_NUMBER_OR_ZERO; cfg->infra_cache_max_rtt = atoi(val); - RTT_MAX_TIMEOUT=cfg->infra_cache_max_rtt; - USEFUL_SERVER_TOP_TIMEOUT = RTT_MAX_TIMEOUT; - BLACKLIST_PENALTY = USEFUL_SERVER_TOP_TIMEOUT*4; - } - else S_YNO("infra-keep-probing:", infra_keep_probing) - else S_NUMBER_OR_ZERO("infra-host-ttl:", host_ttl) - else S_POW2("infra-cache-slabs:", infra_cache_slabs) - else S_SIZET_NONZERO("infra-cache-numhosts:", infra_cache_numhosts) - else S_NUMBER_OR_ZERO("delay-close:", delay_close) - else S_YNO("udp-connect:", udp_connect) - else S_STR("chroot:", chrootdir) - else S_STR("username:", username) - else S_STR("directory:", directory) - else S_STR("pidfile:", pidfile) - else S_YNO("hide-identity:", hide_identity) - else S_YNO("hide-version:", hide_version) - else S_YNO("hide-trustanchor:", hide_trustanchor) - else S_YNO("hide-http-user-agent:", hide_http_user_agent) - else S_STR("identity:", identity) - else S_STR("version:", version) - else S_STR("http-user-agent:", http_user_agent) - else if(strcmp(opt, "nsid:") == 0) { - free(cfg->nsid_cfg_str); - if (!(cfg->nsid_cfg_str = strdup(val))) - return 0; - /* Empty string is just validly unsetting nsid */ - if (*val == 0) { - free(cfg->nsid); - cfg->nsid = NULL; - cfg->nsid_len = 0; - return 1; - } - cfg->nsid = cfg_parse_nsid(val, &cfg->nsid_len); - return cfg->nsid != NULL; - } - else S_STRLIST("root-hints:", root_hints) - else S_STR("target-fetch-policy:", target_fetch_policy) - else S_YNO("harden-glue:", harden_glue) - else S_YNO("harden-short-bufsize:", harden_short_bufsize) - else S_YNO("harden-large-queries:", harden_large_queries) - else S_YNO("harden-dnssec-stripped:", harden_dnssec_stripped) - else S_YNO("harden-below-nxdomain:", harden_below_nxdomain) - else S_YNO("harden-referral-path:", harden_referral_path) - else S_YNO("harden-algo-downgrade:", harden_algo_downgrade) - else S_YNO("harden-unknown-additional:", harden_unknown_additional) - else S_YNO("use-caps-for-id:", use_caps_bits_for_id) - else S_STRLIST("caps-whitelist:", caps_whitelist) - else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold) - else S_STRLIST("private-address:", private_address) - else S_STRLIST("private-domain:", private_domain) - else S_YNO("do-not-query-localhost:", donotquery_localhost) - else S_STRLIST("do-not-query-address:", donotqueryaddrs) - else S_STRLIST("auto-trust-anchor-file:", auto_trust_anchor_file_list) - else S_STRLIST("trust-anchor-file:", trust_anchor_file_list) - else S_STRLIST("trust-anchor:", trust_anchor_list) - else S_STRLIST("trusted-keys-file:", trusted_keys_file_list) - else S_YNO("trust-anchor-signaling:", trust_anchor_signaling) - else S_YNO("root-key-sentinel:", root_key_sentinel) - else S_STRLIST("domain-insecure:", domain_insecure) - else S_NUMBER_OR_ZERO("val-bogus-ttl:", bogus_ttl) - else S_YNO("val-clean-additional:", val_clean_additional) - else S_NUMBER_OR_ZERO("val-log-level:", val_log_level) - else S_YNO("val-log-squelch:", val_log_squelch) - else S_YNO("log-queries:", log_queries) - else S_YNO("log-replies:", log_replies) - else S_YNO("log-tag-queryreply:", log_tag_queryreply) - else S_YNO("log-local-actions:", log_local_actions) - else S_YNO("log-servfail:", log_servfail) - else S_YNO("val-permissive-mode:", val_permissive_mode) - else S_YNO("aggressive-nsec:", aggressive_nsec) - else S_YNO("ignore-cd-flag:", ignore_cd) - else if(strcmp(opt, "serve-expired:") == 0) - { IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0); - SERVE_EXPIRED = cfg->serve_expired; } - else if(strcmp(opt, "serve-expired-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->serve_expired_ttl = atoi(val); SERVE_EXPIRED_TTL=(time_t)cfg->serve_expired_ttl;} - else S_YNO("serve-expired-ttl-reset:", serve_expired_ttl_reset) - else if(strcmp(opt, "serve-expired-reply-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;} - else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout) - else S_YNO("ede:", ede) - else S_YNO("ede-serve-expired:", ede_serve_expired) - else S_YNO("serve-original-ttl:", serve_original_ttl) - else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations) - else S_YNO("zonemd-permissive-mode:", zonemd_permissive_mode) - else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown) - else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown) - else S_UNSIGNED_OR_ZERO("keep-missing:", keep_missing) - else if(strcmp(opt, "permit-small-holddown:") == 0) - { IS_YES_OR_NO; cfg->permit_small_holddown = (strcmp(val, "yes") == 0); - autr_permit_small_holddown = cfg->permit_small_holddown; } - else S_MEMSIZE("key-cache-size:", key_cache_size) - else S_POW2("key-cache-slabs:", key_cache_slabs) - else S_MEMSIZE("neg-cache-size:", neg_cache_size) - else S_YNO("minimal-responses:", minimal_responses) - else S_YNO("rrset-roundrobin:", rrset_roundrobin) - else S_NUMBER_OR_ZERO("unknown-server-time-limit:", unknown_server_time_limit) - else S_STRLIST("local-data:", local_data) - else S_YNO("unblock-lan-zones:", unblock_lan_zones) - else S_YNO("insecure-lan-zones:", insecure_lan_zones) - else S_YNO("control-enable:", remote_control_enable) - else S_STRLIST_APPEND("control-interface:", control_ifs) - else S_NUMBER_NONZERO("control-port:", control_port) - else S_STR("server-key-file:", server_key_file) - else S_STR("server-cert-file:", server_cert_file) - else S_STR("control-key-file:", control_key_file) - else S_STR("control-cert-file:", control_cert_file) - else S_STR("module-config:", module_conf) - else S_STRLIST("python-script:", python_script) - else S_STRLIST("dynlib-file:", dynlib_file) - else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check) -#ifdef CLIENT_SUBNET - /* Can't set max subnet prefix here, since that value is used when - * generating the address tree. */ - /* No client-subnet-always-forward here, module registration depends on - * this option. */ -#endif -#ifdef USE_DNSTAP - else S_YNO("dnstap-enable:", dnstap) - else S_YNO("dnstap-bidirectional:", dnstap_bidirectional) - else S_STR("dnstap-socket-path:", dnstap_socket_path) - else S_STR("dnstap-ip:", dnstap_ip) - else S_YNO("dnstap-tls:", dnstap_tls) - else S_STR("dnstap-tls-server-name:", dnstap_tls_server_name) - else S_STR("dnstap-tls-cert-bundle:", dnstap_tls_cert_bundle) - else S_STR("dnstap-tls-client-key-file:", dnstap_tls_client_key_file) - else S_STR("dnstap-tls-client-cert-file:", - dnstap_tls_client_cert_file) - else S_YNO("dnstap-send-identity:", dnstap_send_identity) - else S_YNO("dnstap-send-version:", dnstap_send_version) - else S_STR("dnstap-identity:", dnstap_identity) - else S_STR("dnstap-version:", dnstap_version) - else S_YNO("dnstap-log-resolver-query-messages:", - dnstap_log_resolver_query_messages) - else S_YNO("dnstap-log-resolver-response-messages:", - dnstap_log_resolver_response_messages) - else S_YNO("dnstap-log-client-query-messages:", - dnstap_log_client_query_messages) - else S_YNO("dnstap-log-client-response-messages:", - dnstap_log_client_response_messages) - else S_YNO("dnstap-log-forwarder-query-messages:", - dnstap_log_forwarder_query_messages) - else S_YNO("dnstap-log-forwarder-response-messages:", - dnstap_log_forwarder_response_messages) -#endif -#ifdef USE_DNSCRYPT - else S_YNO("dnscrypt-enable:", dnscrypt) - else S_NUMBER_NONZERO("dnscrypt-port:", dnscrypt_port) - else S_STR("dnscrypt-provider:", dnscrypt_provider) - else S_STRLIST_UNIQ("dnscrypt-provider-cert:", dnscrypt_provider_cert) - else S_STRLIST("dnscrypt-provider-cert-rotated:", dnscrypt_provider_cert_rotated) - else S_STRLIST_UNIQ("dnscrypt-secret-key:", dnscrypt_secret_key) - else S_MEMSIZE("dnscrypt-shared-secret-cache-size:", - dnscrypt_shared_secret_cache_size) - else S_POW2("dnscrypt-shared-secret-cache-slabs:", - dnscrypt_shared_secret_cache_slabs) - else S_MEMSIZE("dnscrypt-nonce-cache-size:", - dnscrypt_nonce_cache_size) - else S_POW2("dnscrypt-nonce-cache-slabs:", - dnscrypt_nonce_cache_slabs) -#endif - else if(strcmp(opt, "ip-ratelimit-cookie:") == 0) { - IS_NUMBER_OR_ZERO; cfg->ip_ratelimit_cookie = atoi(val); - infra_ip_ratelimit_cookie=cfg->ip_ratelimit_cookie; - } - else if(strcmp(opt, "ip-ratelimit:") == 0) { - IS_NUMBER_OR_ZERO; cfg->ip_ratelimit = atoi(val); - infra_ip_ratelimit=cfg->ip_ratelimit; - } - else if(strcmp(opt, "ratelimit:") == 0) { - IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val); - infra_dp_ratelimit=cfg->ratelimit; - } - else S_MEMSIZE("ip-ratelimit-size:", ip_ratelimit_size) - else S_MEMSIZE("ratelimit-size:", ratelimit_size) - else S_POW2("ip-ratelimit-slabs:", ip_ratelimit_slabs) - else S_POW2("ratelimit-slabs:", ratelimit_slabs) - else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor) - else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor) - else S_YNO("ip-ratelimit-backoff:", ip_ratelimit_backoff) - else S_YNO("ratelimit-backoff:", ratelimit_backoff) - else S_NUMBER_NONZERO("outbound-msg-retry:", outbound_msg_retry) - else S_NUMBER_NONZERO("max-sent-count:", max_sent_count) - else S_NUMBER_NONZERO("max-query-restarts:", max_query_restarts) - else S_SIZET_NONZERO("fast-server-num:", fast_server_num) - else S_NUMBER_OR_ZERO("fast-server-permil:", fast_server_permil) - else S_YNO("qname-minimisation:", qname_minimisation) - else S_YNO("qname-minimisation-strict:", qname_minimisation_strict) - else S_YNO("pad-responses:", pad_responses) - else S_SIZET_NONZERO("pad-responses-block-size:", pad_responses_block_size) - else S_YNO("pad-queries:", pad_queries) - else S_SIZET_NONZERO("pad-queries-block-size:", pad_queries_block_size) - else S_STRLIST("proxy-protocol-port:", proxy_protocol_port) -#ifdef USE_IPSECMOD - else S_YNO("ipsecmod-enabled:", ipsecmod_enabled) - else S_YNO("ipsecmod-ignore-bogus:", ipsecmod_ignore_bogus) - else if(strcmp(opt, "ipsecmod-max-ttl:") == 0) - { IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); } - else S_YNO("ipsecmod-strict:", ipsecmod_strict) -#endif - else if(strcmp(opt, "define-tag:") ==0) { - return config_add_tag(cfg, val); - /* val_sig_skew_min, max and val_max_restart are copied into val_env - * during init so this does not update val_env with set_option */ - } else if(strcmp(opt, "val-sig-skew-min:") == 0) - { IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); } - else if(strcmp(opt, "val-sig-skew-max:") == 0) - { IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); } - else if(strcmp(opt, "val-max-restart:") == 0) - { IS_NUMBER_OR_ZERO; cfg->val_max_restart = (int32_t)atoi(val); } - else if (strcmp(opt, "outgoing-interface:") == 0) { - char* d = strdup(val); - char** oi = - (char**)reallocarray(NULL, (size_t)cfg->num_out_ifs+1, sizeof(char*)); - if(!d || !oi) { free(d); free(oi); return -1; } - if(cfg->out_ifs && cfg->num_out_ifs) { - memmove(oi, cfg->out_ifs, cfg->num_out_ifs*sizeof(char*)); - free(cfg->out_ifs); - } - oi[cfg->num_out_ifs++] = d; - cfg->out_ifs = oi; - } else { - /* unknown or unsupported (from the set_option interface): - * interface, outgoing-interface, access-control, - * stub-zone, name, stub-addr, stub-host, stub-prime - * forward-first, stub-first, forward-ssl-upstream, - * stub-ssl-upstream, forward-zone, auth-zone - * name, forward-addr, forward-host, - * ratelimit-for-domain, ratelimit-below-domain, - * local-zone-tag, access-control-view, interface-*, - * send-client-subnet, client-subnet-always-forward, - * max-client-subnet-ipv4, max-client-subnet-ipv6, - * min-client-subnet-ipv4, min-client-subnet-ipv6, - * max-ecs-tree-size-ipv4, max-ecs-tree-size-ipv6, ipsecmod_hook, - * ipsecmod_whitelist. */ - return 0; - } - return 1; -} - -void config_print_func(char* line, void* arg) -{ - FILE* f = (FILE*)arg; - (void)fprintf(f, "%s\n", line); -} - -/** collate func arg */ -struct config_collate_arg { - /** list of result items */ - struct config_strlist_head list; - /** if a malloc error occurred, 0 is OK */ - int status; -}; - -void config_collate_func(char* line, void* arg) -{ - struct config_collate_arg* m = (struct config_collate_arg*)arg; - if(m->status) - return; - if(!cfg_strlist_append(&m->list, strdup(line))) - m->status = 1; -} - -int config_get_option_list(struct config_file* cfg, const char* opt, - struct config_strlist** list) -{ - struct config_collate_arg m; - memset(&m, 0, sizeof(m)); - *list = NULL; - if(!config_get_option(cfg, opt, config_collate_func, &m)) - return 1; - if(m.status) { - config_delstrlist(m.list.first); - return 2; - } - *list = m.list.first; - return 0; -} - -int -config_get_option_collate(struct config_file* cfg, const char* opt, char** str) -{ - struct config_strlist* list = NULL; - int r; - *str = NULL; - if((r = config_get_option_list(cfg, opt, &list)) != 0) - return r; - *str = config_collate_cat(list); - config_delstrlist(list); - if(!*str) return 2; - return 0; -} - -char* -config_collate_cat(struct config_strlist* list) -{ - size_t total = 0, left; - struct config_strlist* s; - char *r, *w; - if(!list) /* no elements */ - return strdup(""); - if(list->next == NULL) /* one element , no newline at end. */ - return strdup(list->str); - /* count total length */ - for(s=list; s; s=s->next) - total += strlen(s->str) + 1; /* len + newline */ - left = total+1; /* one extra for nul at end */ - r = malloc(left); - if(!r) - return NULL; - w = r; - for(s=list; s; s=s->next) { - size_t this = strlen(s->str); - if(this+2 > left) { /* sanity check */ - free(r); - return NULL; - } - snprintf(w, left, "%s\n", s->str); - this = strlen(w); - w += this; - left -= this; - } - return r; -} - -/** compare and print decimal option */ -#define O_DEC(opt, str, var) if(strcmp(opt, str)==0) \ - {snprintf(buf, len, "%d", (int)cfg->var); \ - func(buf, arg);} -/** compare and print unsigned option */ -#define O_UNS(opt, str, var) if(strcmp(opt, str)==0) \ - {snprintf(buf, len, "%u", (unsigned)cfg->var); \ - func(buf, arg);} -/** compare and print yesno option */ -#define O_YNO(opt, str, var) if(strcmp(opt, str)==0) \ - {func(cfg->var?"yes":"no", arg);} -/** compare and print string option */ -#define O_STR(opt, str, var) if(strcmp(opt, str)==0) \ - {func(cfg->var?cfg->var:"", arg);} -/** compare and print array option */ -#define O_IFC(opt, str, num, arr) if(strcmp(opt, str)==0) \ - {int i; for(i=0; inum; i++) func(cfg->arr[i], arg);} -/** compare and print memorysize option */ -#define O_MEM(opt, str, var) if(strcmp(opt, str)==0) { \ - if(cfg->var > 1024*1024*1024) { \ - size_t f=cfg->var/(size_t)1000000, b=cfg->var%(size_t)1000000; \ - snprintf(buf, len, "%u%6.6u", (unsigned)f, (unsigned)b); \ - } else snprintf(buf, len, "%u", (unsigned)cfg->var); \ - func(buf, arg);} -/** compare and print list option */ -#define O_LST(opt, name, lst) if(strcmp(opt, name)==0) { \ - struct config_strlist* p = cfg->lst; \ - for(p = cfg->lst; p; p = p->next) \ - func(p->str, arg); \ - } -/** compare and print list option */ -#define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \ - struct config_str2list* p = cfg->lst; \ - for(p = cfg->lst; p; p = p->next) { \ - snprintf(buf, len, "%s %s", p->str, p->str2); \ - func(buf, arg); \ - } \ - } -/** compare and print list option */ -#define O_LS3(opt, name, lst) if(strcmp(opt, name)==0) { \ - struct config_str3list* p = cfg->lst; \ - for(p = cfg->lst; p; p = p->next) { \ - snprintf(buf, len, "%s %s %s", p->str, p->str2, p->str3); \ - func(buf, arg); \ - } \ - } -/** compare and print taglist option */ -#define O_LTG(opt, name, lst) if(strcmp(opt, name)==0) { \ - char* tmpstr = NULL; \ - struct config_strbytelist *p = cfg->lst; \ - for(p = cfg->lst; p; p = p->next) {\ - tmpstr = config_taglist2str(cfg, p->str2, p->str2len); \ - if(tmpstr) {\ - snprintf(buf, len, "%s %s", p->str, tmpstr); \ - func(buf, arg); \ - free(tmpstr); \ - } \ - } \ - } - -int -config_get_option(struct config_file* cfg, const char* opt, - void (*func)(char*,void*), void* arg) -{ - char buf[1024], nopt[64]; - size_t len = sizeof(buf); - if(!opt) return 0; - if(opt && opt[strlen(opt)-1] == ':' && strlen(opt)filename = filename; - cfg_parser->line = 1; - cfg_parser->errors = 0; - cfg_parser->cfg = cfg; - cfg_parser->chroot = chroot; - cfg_parser->started_toplevel = 0; - init_cfg_parse(); -} - -int -config_read(struct config_file* cfg, const char* filename, const char* chroot) -{ - FILE *in; - char *fname = (char*)filename; -#ifdef HAVE_GLOB - glob_t g; - size_t i; - int r, flags; -#endif - if(!fname) - return 1; - - /* check for wildcards */ -#ifdef HAVE_GLOB - if(!(!strchr(fname, '*') && !strchr(fname, '?') && !strchr(fname, '[') && - !strchr(fname, '{') && !strchr(fname, '~'))) { - verbose(VERB_QUERY, "wildcard found, processing %s", fname); - flags = 0 -#ifdef GLOB_ERR - | GLOB_ERR -#endif -#ifdef GLOB_NOSORT - | GLOB_NOSORT -#endif -#ifdef GLOB_BRACE - | GLOB_BRACE -#endif -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif - ; - memset(&g, 0, sizeof(g)); - r = glob(fname, flags, NULL, &g); - if(r) { - /* some error */ - globfree(&g); - if(r == GLOB_NOMATCH) { - verbose(VERB_QUERY, "include: " - "no matches for %s", fname); - return 1; - } else if(r == GLOB_NOSPACE) { - log_err("include: %s: " - "fnametern out of memory", fname); - } else if(r == GLOB_ABORTED) { - log_err("wildcard include: %s: expansion " - "aborted (%s)", fname, strerror(errno)); - } else { - log_err("wildcard include: %s: expansion " - "failed (%s)", fname, strerror(errno)); - } - /* ignore globs that yield no files */ - return 1; - } - /* process files found, if any */ - for(i=0; i<(size_t)g.gl_pathc; i++) { - if(!config_read(cfg, g.gl_pathv[i], chroot)) { - log_err("error reading wildcard " - "include: %s", g.gl_pathv[i]); - globfree(&g); - return 0; - } - } - globfree(&g); - return 1; - } -#endif /* HAVE_GLOB */ - - in = fopen(fname, "r"); - if(!in) { - log_err("Could not open %s: %s", fname, strerror(errno)); - return 0; - } - create_cfg_parser(cfg, fname, chroot); - ub_c_in = in; - ub_c_parse(); - fclose(in); - - if(!cfg->dnscrypt) cfg->dnscrypt_port = 0; - - if(cfg_parser->errors != 0) { - fprintf(stderr, "read %s failed: %d errors in configuration file\n", - fname, cfg_parser->errors); - errno=EINVAL; - return 0; - } - - return 1; -} - -struct config_stub* cfg_stub_find(struct config_stub*** pp, const char* nm) -{ - struct config_stub* p = *(*pp); - while(p) { - if(strcmp(p->name, nm) == 0) - return p; - (*pp) = &p->next; - p = p->next; - } - return NULL; -} - -void -config_delstrlist(struct config_strlist* p) -{ - struct config_strlist *np; - while(p) { - np = p->next; - free(p->str); - free(p); - p = np; - } -} - -void -config_deldblstrlist(struct config_str2list* p) -{ - struct config_str2list *np; - while(p) { - np = p->next; - free(p->str); - free(p->str2); - free(p); - p = np; - } -} - -void -config_deltrplstrlist(struct config_str3list* p) -{ - struct config_str3list *np; - while(p) { - np = p->next; - free(p->str); - free(p->str2); - free(p->str3); - free(p); - p = np; - } -} - -void -config_delauth(struct config_auth* p) -{ - if(!p) return; - free(p->name); - config_delstrlist(p->masters); - config_delstrlist(p->urls); - config_delstrlist(p->allow_notify); - free(p->zonefile); - free(p->rpz_taglist); - free(p->rpz_action_override); - free(p->rpz_cname); - free(p->rpz_log_name); - free(p); -} - -void -config_delauths(struct config_auth* p) -{ - struct config_auth* np; - while(p) { - np = p->next; - config_delauth(p); - p = np; - } -} - -void -config_delstub(struct config_stub* p) -{ - if(!p) return; - free(p->name); - config_delstrlist(p->hosts); - config_delstrlist(p->addrs); - free(p); -} - -void -config_delstubs(struct config_stub* p) -{ - struct config_stub* np; - while(p) { - np = p->next; - config_delstub(p); - p = np; - } -} - -void -config_delview(struct config_view* p) -{ - if(!p) return; - free(p->name); - config_deldblstrlist(p->local_zones); - config_delstrlist(p->local_zones_nodefault); -#ifdef USE_IPSET - config_delstrlist(p->local_zones_ipset); -#endif - config_delstrlist(p->local_data); - free(p); -} - -void -config_delviews(struct config_view* p) -{ - struct config_view* np; - while(p) { - np = p->next; - config_delview(p); - p = np; - } -} - -void -config_del_strarray(char** array, int num) -{ - int i; - if(!array) - return; - for(i=0; inext; - free(p->str); - free(p->str2); - free(p); - p = np; - } -} - -void -config_delete(struct config_file* cfg) -{ - if(!cfg) return; - free(cfg->username); - free(cfg->chrootdir); - free(cfg->directory); - free(cfg->logfile); - free(cfg->pidfile); - free(cfg->if_automatic_ports); - free(cfg->target_fetch_policy); - free(cfg->ssl_service_key); - free(cfg->ssl_service_pem); - free(cfg->tls_cert_bundle); - config_delstrlist(cfg->tls_additional_port); - config_delstrlist(cfg->tls_session_ticket_keys.first); - free(cfg->tls_ciphers); - free(cfg->tls_ciphersuites); - free(cfg->http_endpoint); - if(cfg->log_identity) { - log_ident_revert_to_default(); - free(cfg->log_identity); - } - config_del_strarray(cfg->ifs, cfg->num_ifs); - config_del_strarray(cfg->out_ifs, cfg->num_out_ifs); - config_delstubs(cfg->stubs); - config_delstubs(cfg->forwards); - config_delauths(cfg->auths); - config_delviews(cfg->views); - config_delstrlist(cfg->donotqueryaddrs); - config_delstrlist(cfg->root_hints); -#ifdef CLIENT_SUBNET - config_delstrlist(cfg->client_subnet); - config_delstrlist(cfg->client_subnet_zone); -#endif - free(cfg->identity); - free(cfg->version); - free(cfg->http_user_agent); - free(cfg->nsid_cfg_str); - free(cfg->nsid); - free(cfg->module_conf); - free(cfg->outgoing_avail_ports); - config_delstrlist(cfg->caps_whitelist); - config_delstrlist(cfg->private_address); - config_delstrlist(cfg->private_domain); - config_delstrlist(cfg->auto_trust_anchor_file_list); - config_delstrlist(cfg->trust_anchor_file_list); - config_delstrlist(cfg->trusted_keys_file_list); - config_delstrlist(cfg->trust_anchor_list); - config_delstrlist(cfg->domain_insecure); - config_deldblstrlist(cfg->acls); - config_deldblstrlist(cfg->tcp_connection_limits); - free(cfg->val_nsec3_key_iterations); - config_deldblstrlist(cfg->local_zones); - config_delstrlist(cfg->local_zones_nodefault); -#ifdef USE_IPSET - config_delstrlist(cfg->local_zones_ipset); -#endif - config_delstrlist(cfg->local_data); - config_deltrplstrlist(cfg->local_zone_overrides); - config_del_strarray(cfg->tagname, cfg->num_tags); - config_del_strbytelist(cfg->local_zone_tags); - config_del_strbytelist(cfg->respip_tags); - config_deldblstrlist(cfg->acl_view); - config_del_strbytelist(cfg->acl_tags); - config_deltrplstrlist(cfg->acl_tag_actions); - config_deltrplstrlist(cfg->acl_tag_datas); - config_deldblstrlist(cfg->interface_actions); - config_deldblstrlist(cfg->interface_view); - config_del_strbytelist(cfg->interface_tags); - config_deltrplstrlist(cfg->interface_tag_actions); - config_deltrplstrlist(cfg->interface_tag_datas); - config_delstrlist(cfg->control_ifs.first); - free(cfg->server_key_file); - free(cfg->server_cert_file); - free(cfg->control_key_file); - free(cfg->control_cert_file); - free(cfg->nat64_prefix); - free(cfg->dns64_prefix); - config_delstrlist(cfg->dns64_ignore_aaaa); - free(cfg->dnstap_socket_path); - free(cfg->dnstap_ip); - free(cfg->dnstap_tls_server_name); - free(cfg->dnstap_tls_cert_bundle); - free(cfg->dnstap_tls_client_key_file); - free(cfg->dnstap_tls_client_cert_file); - free(cfg->dnstap_identity); - free(cfg->dnstap_version); - config_deldblstrlist(cfg->ratelimit_for_domain); - config_deldblstrlist(cfg->ratelimit_below_domain); - config_delstrlist(cfg->python_script); - config_delstrlist(cfg->dynlib_file); - config_deldblstrlist(cfg->edns_client_strings); - config_delstrlist(cfg->proxy_protocol_port); -#ifdef USE_IPSECMOD - free(cfg->ipsecmod_hook); - config_delstrlist(cfg->ipsecmod_whitelist); -#endif -#ifdef USE_CACHEDB - free(cfg->cachedb_backend); - free(cfg->cachedb_secret); -#ifdef USE_REDIS - free(cfg->redis_server_host); - free(cfg->redis_server_path); - free(cfg->redis_server_password); -#endif /* USE_REDIS */ -#endif /* USE_CACHEDB */ -#ifdef USE_IPSET - free(cfg->ipset_name_v4); - free(cfg->ipset_name_v6); -#endif - free(cfg); -} - -static void -init_cookie_secret(uint8_t* cookie_secret, size_t cookie_secret_len) -{ - struct ub_randstate *rand = ub_initstate(NULL); - - if (!rand) - fatal_exit("could not init random generator"); - while (cookie_secret_len) { - *cookie_secret++ = (uint8_t)ub_random(rand); - cookie_secret_len--; - } - ub_randfree(rand); -} - -static void -init_outgoing_availports(int* a, int num) -{ - /* generated with make iana_update */ - const int iana_assigned[] = { -#include "util/iana_ports.inc" - -1 }; /* end marker to put behind trailing comma */ - - int i; - /* do not use <1024, that could be trouble with the system, privs */ - for(i=1024; i= (int)sizeof(buf) ) { - log_err("cannot parse port number '%s'", str); - return 0; - } - if(mid > str) - memcpy(buf, str, (size_t)(mid-str)); - buf[mid-str] = 0; - low = atoi(buf); - if(low == 0 && strcmp(buf, "0") != 0) { - log_err("cannot parse port number '%s'", buf); - return 0; - } - for(i=low; i<=high; i++) { - if(i < num) - avail[i] = (allow?i:0); - } - return 1; - } - return 1; -} - -int -cfg_scan_ports(int* avail, int num) -{ - int i; - int count = 0; - for(i=0; ioutgoing_avail_ports, 65536); - int i, at = 0; - *avail = NULL; - if(num == 0) - return 0; - *avail = (int*)reallocarray(NULL, (size_t)num, sizeof(int)); - if(!*avail) - return 0; - for(i=0; i<65536; i++) { - if(cfg->outgoing_avail_ports[i]) - (*avail)[at++] = cfg->outgoing_avail_ports[i]; - } - log_assert(at == num); - return num; -} - -void cfg_apply_local_port_policy(struct config_file* cfg, int num) { -(void)cfg; -(void)num; -#ifdef USE_LINUX_IP_LOCAL_PORT_RANGE - { - int i = 0; - FILE* range_fd; - if ((range_fd = fopen(LINUX_IP_LOCAL_PORT_RANGE_PATH, "r")) != NULL) { - int min_port = 0; - int max_port = num - 1; - if (fscanf(range_fd, "%d %d", &min_port, &max_port) == 2) { - for(i=0; ioutgoing_avail_ports[i] = 0; - } - for(i=max_port+1; ioutgoing_avail_ports[i] = 0; - } - } else { - log_err("unexpected port range in %s", - LINUX_IP_LOCAL_PORT_RANGE_PATH); - } - fclose(range_fd); - } else { - log_err("failed to read from file: %s (%s)", - LINUX_IP_LOCAL_PORT_RANGE_PATH, - strerror(errno)); - } - } -#endif -} - -/** print error with file and line number */ -static void ub_c_error_va_list(const char *fmt, va_list args) -{ - cfg_parser->errors++; - fprintf(stderr, "%s:%d: error: ", cfg_parser->filename, - cfg_parser->line); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); -} - -/** print error with file and line number */ -void ub_c_error_msg(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - ub_c_error_va_list(fmt, args); - va_end(args); -} - -void ub_c_error(const char *str) -{ - cfg_parser->errors++; - if(strcmp(str, "syntax error")==0 && cfg_parser->started_toplevel ==0) - str = "syntax error, is there no section start after an " - "include-toplevel directive perhaps."; - fprintf(stderr, "%s:%d: error: %s\n", cfg_parser->filename, - cfg_parser->line, str); -} - -int ub_c_wrap(void) -{ - return 1; -} - -int cfg_strlist_append(struct config_strlist_head* list, char* item) -{ - struct config_strlist *s; - if(!item || !list) { - free(item); - return 0; - } - s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); - if(!s) { - free(item); - return 0; - } - s->str = item; - s->next = NULL; - if(list->last) - list->last->next = s; - else - list->first = s; - list->last = s; - return 1; -} - -int -cfg_region_strlist_insert(struct regional* region, - struct config_strlist** head, char* item) -{ - struct config_strlist *s; - if(!item || !head) - return 0; - s = (struct config_strlist*)regional_alloc_zero(region, - sizeof(struct config_strlist)); - if(!s) - return 0; - s->str = item; - s->next = *head; - *head = s; - return 1; -} - -struct config_strlist* -cfg_strlist_find(struct config_strlist* head, const char *item) -{ - struct config_strlist *s = head; - if(!head){ - return NULL; - } - while(s) { - if(strcmp(s->str, item) == 0) { - return s; - } - s = s->next; - } - return NULL; -} - -int -cfg_strlist_insert(struct config_strlist** head, char* item) -{ - struct config_strlist *s; - if(!item || !head) { - free(item); - return 0; - } - s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); - if(!s) { - free(item); - return 0; - } - s->str = item; - s->next = *head; - *head = s; - return 1; -} - -int -cfg_strlist_append_ex(struct config_strlist** head, char* item) -{ - struct config_strlist *s; - if(!item || !head) - return 0; - s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); - if(!s) - return 0; - s->str = item; - s->next = NULL; - - if (*head==NULL) { - *head = s; - } else { - struct config_strlist *last = *head; - while (last->next!=NULL) { - last = last->next; - } - last->next = s; - } - - return 1; -} - -int -cfg_str2list_insert(struct config_str2list** head, char* item, char* i2) -{ - struct config_str2list *s; - if(!item || !i2 || !head) { - free(item); - free(i2); - return 0; - } - s = (struct config_str2list*)calloc(1, sizeof(struct config_str2list)); - if(!s) { - free(item); - free(i2); - return 0; - } - s->str = item; - s->str2 = i2; - s->next = *head; - *head = s; - return 1; -} - -int -cfg_str3list_insert(struct config_str3list** head, char* item, char* i2, - char* i3) -{ - struct config_str3list *s; - if(!item || !i2 || !i3 || !head) - return 0; - s = (struct config_str3list*)calloc(1, sizeof(struct config_str3list)); - if(!s) - return 0; - s->str = item; - s->str2 = i2; - s->str3 = i3; - s->next = *head; - *head = s; - return 1; -} - -int -cfg_strbytelist_insert(struct config_strbytelist** head, char* item, - uint8_t* i2, size_t i2len) -{ - struct config_strbytelist* s; - if(!item || !i2 || !head) - return 0; - s = (struct config_strbytelist*)calloc(1, sizeof(*s)); - if(!s) - return 0; - s->str = item; - s->str2 = i2; - s->str2len = i2len; - s->next = *head; - *head = s; - return 1; -} - -time_t -cfg_convert_timeval(const char* str) -{ - time_t t; - struct tm tm; - memset(&tm, 0, sizeof(tm)); - if(strlen(str) < 14) - return 0; - if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, - &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) - return 0; - tm.tm_year -= 1900; - tm.tm_mon--; - /* Check values */ - if (tm.tm_year < 70) return 0; - if (tm.tm_mon < 0 || tm.tm_mon > 11) return 0; - if (tm.tm_mday < 1 || tm.tm_mday > 31) return 0; - if (tm.tm_hour < 0 || tm.tm_hour > 23) return 0; - if (tm.tm_min < 0 || tm.tm_min > 59) return 0; - if (tm.tm_sec < 0 || tm.tm_sec > 59) return 0; - /* call ldns conversion function */ - t = sldns_mktime_from_utc(&tm); - return t; -} - -int -cfg_count_numbers(const char* s) -{ - /* format ::= (sp num)+ sp */ - /* num ::= [-](0-9)+ */ - /* sp ::= (space|tab)* */ - int num = 0; - while(*s) { - while(*s && isspace((unsigned char)*s)) - s++; - if(!*s) /* end of string */ - break; - if(*s == '-') - s++; - if(!*s) /* only - not allowed */ - return 0; - if(!isdigit((unsigned char)*s)) /* bad character */ - return 0; - while(*s && isdigit((unsigned char)*s)) - s++; - num++; - } - return num; -} - -/** all digit number */ -static int isalldigit(const char* str, size_t l) -{ - size_t i; - for(i=0; i0 && str[len-1]==' ') - len--; - if(len > 1 && str[len-1] == 'b') - len--; - else if(len > 1 && str[len-1] == 'B') - len--; - - if(len > 1 && tolower((unsigned char)str[len-1]) == 'g') - mult = 1024*1024*1024; - else if(len > 1 && tolower((unsigned char)str[len-1]) == 'm') - mult = 1024*1024; - else if(len > 1 && tolower((unsigned char)str[len-1]) == 'k') - mult = 1024; - else if(len > 0 && isdigit((unsigned char)str[len-1])) - mult = 1; - else { - log_err("unknown size specifier: '%s'", str); - return 0; - } - while(len>1 && str[len-2]==' ') - len--; - - if(!isalldigit(str, len-1)) { - log_err("unknown size specifier: '%s'", str); - return 0; - } - *res = ((size_t)atol(str)) * mult; - return 1; -} - -int -find_tag_id(struct config_file* cfg, const char* tag) -{ - int i; - for(i=0; inum_tags; i++) { - if(strcmp(cfg->tagname[i], tag) == 0) - return i; - } - return -1; -} - -int -config_add_tag(struct config_file* cfg, const char* tag) -{ - char** newarray; - char* newtag; - if(find_tag_id(cfg, tag) != -1) - return 1; /* nothing to do */ - newarray = (char**)malloc(sizeof(char*)*(cfg->num_tags+1)); - if(!newarray) - return 0; - newtag = strdup(tag); - if(!newtag) { - free(newarray); - return 0; - } - if(cfg->tagname) { - memcpy(newarray, cfg->tagname, sizeof(char*)*cfg->num_tags); - free(cfg->tagname); - } - newarray[cfg->num_tags++] = newtag; - cfg->tagname = newarray; - return 1; -} - -/** set a bit in a bit array */ -static void -cfg_set_bit(uint8_t* bitlist, size_t len, int id) -{ - int pos = id/8; - log_assert((size_t)pos < len); - (void)len; - bitlist[pos] |= 1<<(id%8); -} - -uint8_t* config_parse_taglist(struct config_file* cfg, char* str, - size_t* listlen) -{ - uint8_t* taglist = NULL; - size_t len = 0; - char* p, *s; - - /* allocate */ - if(cfg->num_tags == 0) { - log_err("parse taglist, but no tags defined"); - return 0; - } - len = (size_t)(cfg->num_tags+7)/8; - taglist = calloc(1, len); - if(!taglist) { - log_err("out of memory"); - return 0; - } - - /* parse */ - s = str; - while((p=strsep(&s, " \t\n")) != NULL) { - if(*p) { - int id = find_tag_id(cfg, p); - /* set this bit in the bitlist */ - if(id == -1) { - log_err("unknown tag: %s", p); - free(taglist); - return 0; - } - cfg_set_bit(taglist, len, id); - } - } - - *listlen = len; - return taglist; -} - -uint8_t* cfg_parse_nsid(const char* str, uint16_t* nsid_len) -{ - uint8_t* nsid = NULL; - - if (strncasecmp(str, "ascii_", 6) == 0) { - if ((nsid = (uint8_t *)strdup(str + 6))) - *nsid_len = strlen(str + 6); - - } else if (strlen(str) % 2) { - ; /* hex string has even number of characters */ - } - - else if (*str && (nsid = calloc(1, strlen(str) / 2))) { - const char *ch; - uint8_t *dp; - - for ( ch = str, dp = nsid - ; isxdigit(ch[0]) && isxdigit(ch[1]) - ; ch += 2, dp++) { - *dp = (uint8_t)sldns_hexdigit_to_int(ch[0]) * 16; - *dp += (uint8_t)sldns_hexdigit_to_int(ch[1]); - } - if (*ch) { - free(nsid); - nsid = NULL; - } else - *nsid_len = strlen(str) / 2; - } - return nsid; -} - - -char* config_taglist2str(struct config_file* cfg, uint8_t* taglist, - size_t taglen) -{ - char buf[10240]; - size_t i, j, len = 0; - buf[0] = 0; - for(i=0; itagname[id]); - len += strlen(buf+len); - } - } - } - return strdup(buf); -} - -int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2, - size_t list2len) -{ - size_t i; - if(!list1 || !list2) - return 0; - for(i=0; imax_ttl; - MIN_TTL = (time_t)config->min_ttl; - SERVE_EXPIRED = config->serve_expired; - SERVE_EXPIRED_TTL = (time_t)config->serve_expired_ttl; - SERVE_EXPIRED_REPLY_TTL = (time_t)config->serve_expired_reply_ttl; - SERVE_ORIGINAL_TTL = config->serve_original_ttl; - MAX_NEG_TTL = (time_t)config->max_negative_ttl; - RTT_MIN_TIMEOUT = config->infra_cache_min_rtt; - RTT_MAX_TIMEOUT = config->infra_cache_max_rtt; - EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size; - MINIMAL_RESPONSES = config->minimal_responses; - RRSET_ROUNDROBIN = config->rrset_roundrobin; - LOG_TAG_QUERYREPLY = config->log_tag_queryreply; - UNKNOWN_SERVER_NICENESS = config->unknown_server_time_limit; - USEFUL_SERVER_TOP_TIMEOUT = RTT_MAX_TIMEOUT; - BLACKLIST_PENALTY = USEFUL_SERVER_TOP_TIMEOUT*4; - log_set_time_asc(config->log_time_ascii); - autr_permit_small_holddown = config->permit_small_holddown; - stream_wait_max = config->stream_wait_size; - http2_query_buffer_max = config->http_query_buffer_size; - http2_response_buffer_max = config->http_response_buffer_size; -} - -void config_lookup_uid(struct config_file* cfg) -{ -#ifdef HAVE_GETPWNAM - /* translate username into uid and gid */ - if(cfg->username && cfg->username[0]) { - struct passwd *pwd; - if((pwd = getpwnam(cfg->username)) != NULL) { - cfg_uid = pwd->pw_uid; - cfg_gid = pwd->pw_gid; - } - } -#else - (void)cfg; -#endif -} - -/** - * Calculate string length of full pathname in original filesys - * @param fname: the path name to convert. - * Must not be null or empty. - * @param cfg: config struct for chroot and chdir (if set). - * @param use_chdir: if false, only chroot is applied. - * @return length of string. - * remember to allocate one more for 0 at end in mallocs. - */ -static size_t -strlen_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) -{ - size_t len = 0; - int slashit = 0; - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { - /* already full pathname, return it */ - return strlen(fname); - } - /* chroot */ - if(cfg->chrootdir && cfg->chrootdir[0]) { - /* start with chrootdir */ - len += strlen(cfg->chrootdir); - slashit = 1; - } - /* chdir */ -#ifdef UB_ON_WINDOWS - if(fname[0] != 0 && fname[1] == ':') { - /* full path, no chdir */ - } else -#endif - if(fname[0] == '/' || !use_chdir) { - /* full path, no chdir */ - } else if(cfg->directory && cfg->directory[0]) { - /* prepend chdir */ - if(slashit && cfg->directory[0] != '/') - len++; - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(cfg->chrootdir, cfg->directory, - strlen(cfg->chrootdir)) == 0) - len += strlen(cfg->directory)-strlen(cfg->chrootdir); - else len += strlen(cfg->directory); - slashit = 1; - } - /* fname */ - if(slashit && fname[0] != '/') - len++; - len += strlen(fname); - return len; -} - -char* -fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) -{ - size_t len = strlen_after_chroot(fname, cfg, use_chdir)+1; - int slashit = 0; - char* buf = (char*)malloc(len); - if(!buf) - return NULL; - buf[0] = 0; - /* is fname already in chroot ? */ - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { - /* already full pathname, return it */ - (void)strlcpy(buf, fname, len); - buf[len-1] = 0; - return buf; - } - /* chroot */ - if(cfg->chrootdir && cfg->chrootdir[0]) { - /* start with chrootdir */ - (void)strlcpy(buf, cfg->chrootdir, len); - slashit = 1; - } -#ifdef UB_ON_WINDOWS - if(fname[0] != 0 && fname[1] == ':') { - /* full path, no chdir */ - } else -#endif - /* chdir */ - if(fname[0] == '/' || !use_chdir) { - /* full path, no chdir */ - } else if(cfg->directory && cfg->directory[0]) { - /* prepend chdir */ - if(slashit && cfg->directory[0] != '/') - (void)strlcat(buf, "/", len); - /* is the directory already in the chroot? */ - if(cfg->chrootdir && cfg->chrootdir[0] && - strncmp(cfg->chrootdir, cfg->directory, - strlen(cfg->chrootdir)) == 0) - (void)strlcat(buf, cfg->directory+strlen(cfg->chrootdir), - len); - else (void)strlcat(buf, cfg->directory, len); - slashit = 1; - } - /* fname */ - if(slashit && fname[0] != '/') - (void)strlcat(buf, "/", len); - (void)strlcat(buf, fname, len); - buf[len-1] = 0; - return buf; -} - -/** return next space character in string */ -static char* next_space_pos(const char* str) -{ - char* sp = strchr(str, ' '); - char* tab = strchr(str, '\t'); - if(!tab && !sp) - return NULL; - if(!sp) return tab; - if(!tab) return sp; - return (sptab)?sp:tab; -} - -int -cfg_parse_local_zone(struct config_file* cfg, const char* val) -{ - const char *type, *name_end, *name; - char buf[256]; - - /* parse it as: [zone_name] [between stuff] [zone_type] */ - name = val; - while(*name && isspace((unsigned char)*name)) - name++; - if(!*name) { - log_err("syntax error: too short: %s", val); - return 0; - } - name_end = next_space_pos(name); - if(!name_end || !*name_end) { - log_err("syntax error: expected zone type: %s", val); - return 0; - } - if (name_end - name > 255) { - log_err("syntax error: bad zone name: %s", val); - return 0; - } - (void)strlcpy(buf, name, sizeof(buf)); - buf[name_end-name] = '\0'; - - type = last_space_pos(name_end); - while(type && *type && isspace((unsigned char)*type)) - type++; - if(!type || !*type) { - log_err("syntax error: expected zone type: %s", val); - return 0; - } - - if(strcmp(type, "nodefault")==0) { - return cfg_strlist_insert(&cfg->local_zones_nodefault, - strdup(name)); -#ifdef USE_IPSET - } else if(strcmp(type, "ipset")==0) { - return cfg_strlist_insert(&cfg->local_zones_ipset, - strdup(name)); -#endif - } else { - return cfg_str2list_insert(&cfg->local_zones, strdup(buf), - strdup(type)); - } -} - -char* cfg_ptr_reverse(char* str) -{ - char* ip, *ip_end; - char* name; - char* result; - char buf[1024]; - struct sockaddr_storage addr; - socklen_t addrlen; - - /* parse it as: [IP] [between stuff] [name] */ - ip = str; - while(*ip && isspace((unsigned char)*ip)) - ip++; - if(!*ip) { - log_err("syntax error: too short: %s", str); - return NULL; - } - ip_end = next_space_pos(ip); - if(!ip_end || !*ip_end) { - log_err("syntax error: expected name: %s", str); - return NULL; - } - - name = last_space_pos(ip_end); - if(!name || !*name) { - log_err("syntax error: expected name: %s", str); - return NULL; - } - - sscanf(ip, "%100s", buf); - buf[sizeof(buf)-1]=0; - - if(!ipstrtoaddr(buf, UNBOUND_DNS_PORT, &addr, &addrlen)) { - log_err("syntax error: cannot parse address: %s", str); - return NULL; - } - - /* reverse IPv4: - * ddd.ddd.ddd.ddd.in-addr-arpa. - * IPv6: (h.){32}.ip6.arpa. */ - - if(addr_is_ip6(&addr, addrlen)) { - uint8_t ad[16]; - const char* hex = "0123456789abcdef"; - char *p = buf; - int i; - memmove(ad, &((struct sockaddr_in6*)&addr)->sin6_addr, - sizeof(ad)); - for(i=15; i>=0; i--) { - uint8_t b = ad[i]; - *p++ = hex[ (b&0x0f) ]; - *p++ = '.'; - *p++ = hex[ (b&0xf0) >> 4 ]; - *p++ = '.'; - } - snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa. "); - } else { - uint8_t ad[4]; - memmove(ad, &((struct sockaddr_in*)&addr)->sin_addr, - sizeof(ad)); - snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa. ", - (unsigned)ad[3], (unsigned)ad[2], - (unsigned)ad[1], (unsigned)ad[0]); - } - - /* printed the reverse address, now the between goop and name on end */ - while(*ip_end && isspace((unsigned char)*ip_end)) - ip_end++; - if(name>ip_end) { - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%.*s", - (int)(name-ip_end), ip_end); - } - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), " PTR %s", name); - - result = strdup(buf); - if(!result) { - log_err("out of memory parsing %s", str); - return NULL; - } - return result; -} - -#ifdef UB_ON_WINDOWS -char* -w_lookup_reg_str(const char* key, const char* name) -{ - HKEY hk = NULL; - DWORD type = 0; - BYTE buf[1024]; - DWORD len = (DWORD)sizeof(buf); - LONG ret; - char* result = NULL; - ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk); - if(ret == ERROR_FILE_NOT_FOUND) - return NULL; /* key does not exist */ - else if(ret != ERROR_SUCCESS) { - log_err("RegOpenKeyEx failed"); - return NULL; - } - ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len); - if(RegCloseKey(hk)) - log_err("RegCloseKey"); - if(ret == ERROR_FILE_NOT_FOUND) - return NULL; /* name does not exist */ - else if(ret != ERROR_SUCCESS) { - log_err("RegQueryValueEx failed"); - return NULL; - } - if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { - buf[sizeof(buf)-1] = 0; - buf[sizeof(buf)-2] = 0; /* for multi_sz */ - result = strdup((char*)buf); - if(!result) log_err("out of memory"); - } - return result; -} - -void w_config_adjust_directory(struct config_file* cfg) -{ - if(cfg->directory && cfg->directory[0]) { - TCHAR dirbuf[2*MAX_PATH+4]; - if(strcmp(cfg->directory, "%EXECUTABLE%") == 0) { - /* get executable path, and if that contains - * directories, snip off the filename part */ - dirbuf[0] = 0; - if(!GetModuleFileName(NULL, dirbuf, MAX_PATH)) - log_err("could not GetModuleFileName"); - if(strrchr(dirbuf, '\\')) { - (strrchr(dirbuf, '\\'))[0] = 0; - } else log_err("GetModuleFileName had no path"); - if(dirbuf[0]) { - /* adjust directory for later lookups to work*/ - free(cfg->directory); - cfg->directory = memdup(dirbuf, strlen(dirbuf)+1); - } - } - } -} -#endif /* UB_ON_WINDOWS */ - -int options_remote_is_address(struct config_file* cfg) -{ - if(!cfg->remote_control_enable) return 0; - if(!cfg->control_ifs.first) return 1; - if(!cfg->control_ifs.first->str) return 1; - if(cfg->control_ifs.first->str[0] == 0) return 1; - return (cfg->control_ifs.first->str[0] != '/'); -} - -/** see if interface is https, its port number == the https port number */ -int -if_is_https(const char* ifname, const char* port, int https_port) -{ - char* p = strchr(ifname, '@'); - if(!p && atoi(port) == https_port) - return 1; - if(p && atoi(p+1) == https_port) - return 1; - return 0; -} - -/** see if config contains https turned on */ -int cfg_has_https(struct config_file* cfg) -{ - int i; - char portbuf[32]; - snprintf(portbuf, sizeof(portbuf), "%d", cfg->port); - for(i = 0; inum_ifs; i++) { - if(if_is_https(cfg->ifs[i], portbuf, cfg->https_port)) - return 1; - } - return 0; -} - -/** see if interface is PROXYv2, its port number == the proxy port number */ -int -if_is_pp2(const char* ifname, const char* port, - struct config_strlist* proxy_protocol_port) -{ - struct config_strlist* s; - char* p = strchr(ifname, '@'); - for(s = proxy_protocol_port; s; s = s->next) { - if(p && atoi(p+1) == atoi(s->str)) - return 1; - if(!p && atoi(port) == atoi(s->str)) - return 1; - } - return 0; -} - -/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */ -int -if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port) -{ -#ifdef USE_DNSCRYPT - return ((strchr(ifname, '@') && - atoi(strchr(ifname, '@')+1) == dnscrypt_port) || - (!strchr(ifname, '@') && atoi(port) == dnscrypt_port)); -#else - (void)ifname; - (void)port; - (void)dnscrypt_port; - return 0; -#endif -} diff --git a/crates/libunbound-sys/unbound/util/config_file.h b/crates/libunbound-sys/unbound/util/config_file.h deleted file mode 100644 index 452f3c6a..00000000 --- a/crates/libunbound-sys/unbound/util/config_file.h +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * util/config_file.h - reads and stores the config file for unbound. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for the config file. - */ - -#ifndef UTIL_CONFIG_FILE_H -#define UTIL_CONFIG_FILE_H -#include "sldns/rrdef.h" -struct config_stub; -struct config_auth; -struct config_view; -struct config_strlist; -struct config_str2list; -struct config_str3list; -struct config_strbytelist; -struct module_qstate; -struct sock_list; -struct ub_packed_rrset_key; -struct regional; - -/** List head for strlist processing, used for append operation. */ -struct config_strlist_head { - /** first in list of text items */ - struct config_strlist* first; - /** last in list of text items */ - struct config_strlist* last; -}; - -/** - * The configuration options. - * Strings are malloced. - */ -struct config_file { - /** verbosity level as specified in the config file */ - int verbosity; - - /** statistics interval (in seconds) */ - int stat_interval; - /** if false, statistics values are reset after printing them */ - int stat_cumulative; - /** if true, the statistics are kept in greater detail */ - int stat_extended; - /** if true, inhibits a lot of =0 lines from the extended stats output */ - int stat_inhibit_zero; - - /** number of threads to create */ - int num_threads; - - /** port on which queries are answered. */ - int port; - /** do ip4 query support. */ - int do_ip4; - /** do ip6 query support. */ - int do_ip6; - /** do nat64 on queries */ - int do_nat64; - /** prefer ip4 upstream queries. */ - int prefer_ip4; - /** prefer ip6 upstream queries. */ - int prefer_ip6; - /** do udp query support. */ - int do_udp; - /** do tcp query support. */ - int do_tcp; - /** max number of queries on a reuse connection. */ - size_t max_reuse_tcp_queries; - /** timeout for REUSE entries in milliseconds. */ - int tcp_reuse_timeout; - /** timeout in milliseconds for TCP queries to auth servers. */ - int tcp_auth_query_timeout; - /** tcp upstream queries (no UDP upstream queries) */ - int tcp_upstream; - /** udp upstream enabled when no UDP downstream is enabled (do_udp no)*/ - int udp_upstream_without_downstream; - /** maximum segment size of tcp socket which queries are answered */ - int tcp_mss; - /** maximum segment size of tcp socket for outgoing queries */ - int outgoing_tcp_mss; - /** tcp idle timeout, in msec */ - int tcp_idle_timeout; - /** do edns tcp keepalive */ - int do_tcp_keepalive; - /** tcp keepalive timeout, in msec */ - int tcp_keepalive_timeout; - /** timeout of packets sitting in the socket queue */ - int sock_queue_timeout; - /** proxy protocol ports */ - struct config_strlist* proxy_protocol_port; - - /** private key file for dnstcp-ssl service (enabled if not NULL) */ - char* ssl_service_key; - /** public key file for dnstcp-ssl service */ - char* ssl_service_pem; - /** port on which to provide ssl service */ - int ssl_port; - /** if outgoing tcp connections use SSL */ - int ssl_upstream; - /** cert bundle for outgoing connections */ - char* tls_cert_bundle; - /** should the system certificate store get added to the cert bundle */ - int tls_win_cert; - /** additional tls ports */ - struct config_strlist* tls_additional_port; - /** secret key used to encrypt and decrypt TLS session ticket */ - struct config_strlist_head tls_session_ticket_keys; - /** TLS ciphers */ - char* tls_ciphers; - /** TLS chiphersuites (TLSv1.3) */ - char* tls_ciphersuites; - /** if SNI is to be used */ - int tls_use_sni; - - /** port on which to provide DNS over HTTPS service */ - int https_port; - /** endpoint for HTTP service */ - char* http_endpoint; - /** MAX_CONCURRENT_STREAMS HTTP/2 setting */ - uint32_t http_max_streams; - /** maximum size of all HTTP2 query buffers combined. */ - size_t http_query_buffer_size; - /** maximum size of all HTTP2 response buffers combined. */ - size_t http_response_buffer_size; - /** set TCP_NODELAY option for http sockets */ - int http_nodelay; - /** Disable TLS for http sockets downstream */ - int http_notls_downstream; - - /** outgoing port range number of ports (per thread) */ - int outgoing_num_ports; - /** number of outgoing tcp buffers per (per thread) */ - size_t outgoing_num_tcp; - /** number of incoming tcp buffers per (per thread) */ - size_t incoming_num_tcp; - /** allowed udp port numbers, array with 0 if not allowed */ - int* outgoing_avail_ports; - - /** EDNS buffer size to use */ - size_t edns_buffer_size; - /** size of the stream wait buffers, max */ - size_t stream_wait_size; - /** number of bytes buffer size for DNS messages */ - size_t msg_buffer_size; - /** size of the message cache */ - size_t msg_cache_size; - /** slabs in the message cache. */ - size_t msg_cache_slabs; - /** number of queries every thread can service */ - size_t num_queries_per_thread; - /** number of msec to wait before items can be jostled out */ - size_t jostle_time; - /** size of the rrset cache */ - size_t rrset_cache_size; - /** slabs in the rrset cache */ - size_t rrset_cache_slabs; - /** host cache ttl in seconds */ - int host_ttl; - /** number of slabs in the infra host cache */ - size_t infra_cache_slabs; - /** max number of hosts in the infra cache */ - size_t infra_cache_numhosts; - /** min value for infra cache rtt (min retransmit timeout) */ - int infra_cache_min_rtt; - /** max value for infra cache rtt (max retransmit timeout) */ - int infra_cache_max_rtt; - /** keep probing hosts that are down */ - int infra_keep_probing; - /** delay close of udp-timeouted ports, if 0 no delayclose. in msec */ - int delay_close; - /** udp_connect enable uses UDP connect to mitigate ICMP side channel */ - int udp_connect; - - /** the target fetch policy for the iterator */ - char* target_fetch_policy; - /** percent*10, how many times in 1000 to pick from the fastest - * destinations */ - int fast_server_permil; - /** number of fastest server to select from */ - size_t fast_server_num; - - /** automatic interface for incoming messages. Uses ipv6 remapping, - * and recvmsg/sendmsg ancillary data to detect interfaces, boolean */ - int if_automatic; - /** extra ports to open if if_automatic enabled, or NULL for default */ - char* if_automatic_ports; - /** SO_RCVBUF size to set on port 53 UDP socket */ - size_t so_rcvbuf; - /** SO_SNDBUF size to set on port 53 UDP socket */ - size_t so_sndbuf; - /** SO_REUSEPORT requested on port 53 sockets */ - int so_reuseport; - /** IP_TRANSPARENT socket option requested on port 53 sockets */ - int ip_transparent; - /** IP_FREEBIND socket option request on port 53 sockets */ - int ip_freebind; - /** IP_TOS socket option requested on port 53 sockets */ - int ip_dscp; - - /** number of interfaces to open. If 0 default all interfaces. */ - int num_ifs; - /** interface description strings (IP addresses) */ - char **ifs; - - /** number of outgoing interfaces to open. - * If 0 default all interfaces. */ - int num_out_ifs; - /** outgoing interface description strings (IP addresses) */ - char **out_ifs; - - /** the root hints */ - struct config_strlist* root_hints; - /** the stub definitions, linked list */ - struct config_stub* stubs; - /** the forward zone definitions, linked list */ - struct config_stub* forwards; - /** the auth zone definitions, linked list */ - struct config_auth* auths; - /** the views definitions, linked list */ - struct config_view* views; - /** list of donotquery addresses, linked list */ - struct config_strlist* donotqueryaddrs; -#ifdef CLIENT_SUBNET - /** list of servers we send edns-client-subnet option to and - * accept option from, linked list */ - struct config_strlist* client_subnet; - /** list of zones we send edns-client-subnet option for */ - struct config_strlist* client_subnet_zone; - /** opcode assigned by IANA for edns0-client-subnet option */ - uint16_t client_subnet_opcode; - /** Do not check whitelist if incoming query contains an ECS record */ - int client_subnet_always_forward; - /** Subnet length we are willing to give up privacy for */ - uint8_t max_client_subnet_ipv4; - uint8_t max_client_subnet_ipv6; - /** Minimum subnet length we are willing to answer */ - uint8_t min_client_subnet_ipv4; - uint8_t min_client_subnet_ipv6; - /** Max number of nodes in the ECS radix tree */ - uint32_t max_ecs_tree_size_ipv4; - uint32_t max_ecs_tree_size_ipv6; -#endif - /** list of access control entries, linked list */ - struct config_str2list* acls; - /** use default localhost donotqueryaddr entries */ - int donotquery_localhost; - - /** list of tcp connection limitss, linked list */ - struct config_str2list* tcp_connection_limits; - - /** harden against very small edns buffer sizes */ - int harden_short_bufsize; - /** harden against very large query sizes */ - int harden_large_queries; - /** harden against spoofed glue (out of zone data) */ - int harden_glue; - /** harden against receiving no DNSSEC data for trust anchor */ - int harden_dnssec_stripped; - /** harden against queries that fall under known nxdomain names */ - int harden_below_nxdomain; - /** harden the referral path, query for NS,A,AAAA and validate */ - int harden_referral_path; - /** harden against algorithm downgrade */ - int harden_algo_downgrade; - /** harden against unknown records in the authority section and in - * the additional section */ - int harden_unknown_additional; - /** use 0x20 bits in query as random ID bits */ - int use_caps_bits_for_id; - /** 0x20 whitelist, domains that do not use capsforid */ - struct config_strlist* caps_whitelist; - /** strip away these private addrs from answers, no DNS Rebinding */ - struct config_strlist* private_address; - /** allow domain (and subdomains) to use private address space */ - struct config_strlist* private_domain; - /** what threshold for unwanted action. */ - size_t unwanted_threshold; - /** the number of seconds maximal TTL used for RRsets and messages */ - int max_ttl; - /** the number of seconds minimum TTL used for RRsets and messages */ - int min_ttl; - /** the number of seconds maximal negative TTL for SOA in auth */ - int max_negative_ttl; - /** if prefetching of messages should be performed. */ - int prefetch; - /** if prefetching of DNSKEYs should be performed. */ - int prefetch_key; - /** deny queries of type ANY with an empty answer */ - int deny_any; - - /** chrootdir, if not "" or chroot will be done */ - char* chrootdir; - /** username to change to, if not "". */ - char* username; - /** working directory */ - char* directory; - /** filename to log to. */ - char* logfile; - /** pidfile to write pid to. */ - char* pidfile; - - /** should log messages be sent to syslogd */ - int use_syslog; - /** log timestamp in ascii UTC */ - int log_time_ascii; - /** log queries with one line per query */ - int log_queries; - /** log replies with one line per reply */ - int log_replies; - /** tag log_queries and log_replies for filtering */ - int log_tag_queryreply; - /** log every local-zone hit **/ - int log_local_actions; - /** log servfails with a reason */ - int log_servfail; - /** log identity to report */ - char* log_identity; - - /** do not report identity (id.server, hostname.bind) */ - int hide_identity; - /** do not report version (version.server, version.bind) */ - int hide_version; - /** do not report trustanchor (trustanchor.unbound) */ - int hide_trustanchor; - /** do not report the User-Agent HTTP header */ - int hide_http_user_agent; - /** identity, hostname is returned if "". */ - char* identity; - /** version, package version returned if "". */ - char* version; - /** User-Agent for HTTP header */ - char* http_user_agent; - /** nsid */ - char *nsid_cfg_str; - uint8_t *nsid; - uint16_t nsid_len; - - /** the module configuration string */ - char* module_conf; - - /** files with trusted DS and DNSKEYs in zonefile format, list */ - struct config_strlist* trust_anchor_file_list; - /** list of trustanchor keys, linked list */ - struct config_strlist* trust_anchor_list; - /** files with 5011 autotrust tracked keys */ - struct config_strlist* auto_trust_anchor_file_list; - /** files with trusted DNSKEYs in named.conf format, list */ - struct config_strlist* trusted_keys_file_list; - /** insecure domain list */ - struct config_strlist* domain_insecure; - /** send key tag query */ - int trust_anchor_signaling; - /** enable root key sentinel */ - int root_key_sentinel; - - /** if not 0, this value is the validation date for RRSIGs */ - int32_t val_date_override; - /** the minimum for signature clock skew */ - int32_t val_sig_skew_min; - /** the maximum for signature clock skew */ - int32_t val_sig_skew_max; - /** max number of query restarts, number of IPs to probe */ - int32_t val_max_restart; - /** this value sets the number of seconds before revalidating bogus */ - int bogus_ttl; - /** should validator clean additional section for secure msgs */ - int val_clean_additional; - /** log bogus messages by the validator */ - int val_log_level; - /** squelch val_log_level to log - this is library goes to callback */ - int val_log_squelch; - /** should validator allow bogus messages to go through */ - int val_permissive_mode; - /** use cached NSEC records to synthesise (negative) answers */ - int aggressive_nsec; - /** ignore the CD flag in incoming queries and refuse them bogus data */ - int ignore_cd; - /** serve expired entries and prefetch them */ - int serve_expired; - /** serve expired entries until TTL after expiration */ - int serve_expired_ttl; - /** reset serve expired TTL after failed update attempt */ - int serve_expired_ttl_reset; - /** TTL for the serve expired replies */ - int serve_expired_reply_ttl; - /** serve expired entries only after trying to update the entries and this - * timeout (in milliseconds) is reached */ - int serve_expired_client_timeout; - /** serve EDE code 3 - Stale Answer (RFC8914) for expired entries */ - int ede_serve_expired; - /** serve original TTLs rather than decrementing ones */ - int serve_original_ttl; - /** nsec3 maximum iterations per key size, string */ - char* val_nsec3_key_iterations; - /** if zonemd failures are permitted, only logged */ - int zonemd_permissive_mode; - /** autotrust add holddown time, in seconds */ - unsigned int add_holddown; - /** autotrust del holddown time, in seconds */ - unsigned int del_holddown; - /** autotrust keep_missing time, in seconds. 0 is forever. */ - unsigned int keep_missing; - /** permit small holddown values, allowing 5011 rollover very fast */ - int permit_small_holddown; - - /** size of the key cache */ - size_t key_cache_size; - /** slabs in the key cache. */ - size_t key_cache_slabs; - /** size of the neg cache */ - size_t neg_cache_size; - - /** local zones config */ - struct config_str2list* local_zones; - /** local zones nodefault list */ - struct config_strlist* local_zones_nodefault; -#ifdef USE_IPSET - /** local zones ipset list */ - struct config_strlist* local_zones_ipset; -#endif - /** do not add any default local zone */ - int local_zones_disable_default; - /** local data RRs configured */ - struct config_strlist* local_data; - /** local zone override types per netblock */ - struct config_str3list* local_zone_overrides; - /** unblock lan zones (reverse lookups for AS112 zones) */ - int unblock_lan_zones; - /** insecure lan zones (don't validate AS112 zones) */ - int insecure_lan_zones; - /** list of zonename, tagbitlist */ - struct config_strbytelist* local_zone_tags; - /** list of aclname, tagbitlist */ - struct config_strbytelist* acl_tags; - /** list of aclname, tagname, localzonetype */ - struct config_str3list* acl_tag_actions; - /** list of aclname, tagname, redirectdata */ - struct config_str3list* acl_tag_datas; - /** list of aclname, view*/ - struct config_str2list* acl_view; - /** list of interface action entries, linked list */ - struct config_str2list* interface_actions; - /** list of interface, tagbitlist */ - struct config_strbytelist* interface_tags; - /** list of interface, tagname, localzonetype */ - struct config_str3list* interface_tag_actions; - /** list of interface, tagname, redirectdata */ - struct config_str3list* interface_tag_datas; - /** list of interface, view*/ - struct config_str2list* interface_view; - /** list of IP-netblock, tagbitlist */ - struct config_strbytelist* respip_tags; - /** list of response-driven access control entries, linked list */ - struct config_str2list* respip_actions; - /** RRs configured for response-driven access controls */ - struct config_str2list* respip_data; - /** tag list, array with tagname[i] is malloced string */ - char** tagname; - /** number of items in the taglist */ - int num_tags; - - /** remote control section. enable toggle. */ - int remote_control_enable; - /** the interfaces the remote control should listen on */ - struct config_strlist_head control_ifs; - /** if the use-cert option is set */ - int control_use_cert; - /** port number for the control port */ - int control_port; - /** private key file for server */ - char* server_key_file; - /** certificate file for server */ - char* server_cert_file; - /** private key file for unbound-control */ - char* control_key_file; - /** certificate file for unbound-control */ - char* control_cert_file; - - /** Python script file */ - struct config_strlist* python_script; - - /** Dynamic library file */ - struct config_strlist* dynlib_file; - - /** Use systemd socket activation. */ - int use_systemd; - - /** daemonize, i.e. fork into the background. */ - int do_daemonize; - - /* minimal response when positive answer */ - int minimal_responses; - - /* RRSet roundrobin */ - int rrset_roundrobin; - - /* wait time for unknown server in msec */ - int unknown_server_time_limit; - - /* maximum UDP response size */ - size_t max_udp_size; - - /* DNS64 prefix */ - char* dns64_prefix; - - /* Synthetize all AAAA record despite the presence of an authoritative one */ - int dns64_synthall; - /** ignore AAAAs for these domain names and use A record anyway */ - struct config_strlist* dns64_ignore_aaaa; - - /* NAT64 prefix; if unset defaults to dns64_prefix */ - char* nat64_prefix; - - /** true to enable dnstap support */ - int dnstap; - /** using bidirectional frame streams if true */ - int dnstap_bidirectional; - /** dnstap socket path */ - char* dnstap_socket_path; - /** dnstap IP */ - char* dnstap_ip; - /** dnstap TLS enable */ - int dnstap_tls; - /** dnstap tls server authentication name */ - char* dnstap_tls_server_name; - /** dnstap server cert bundle */ - char* dnstap_tls_cert_bundle; - /** dnstap client key for client authentication */ - char* dnstap_tls_client_key_file; - /** dnstap client cert for client authentication */ - char* dnstap_tls_client_cert_file; - /** true to send "identity" via dnstap */ - int dnstap_send_identity; - /** true to send "version" via dnstap */ - int dnstap_send_version; - /** dnstap "identity", hostname is used if "". */ - char* dnstap_identity; - /** dnstap "version", package version is used if "". */ - char* dnstap_version; - - /** true to log dnstap RESOLVER_QUERY message events */ - int dnstap_log_resolver_query_messages; - /** true to log dnstap RESOLVER_RESPONSE message events */ - int dnstap_log_resolver_response_messages; - /** true to log dnstap CLIENT_QUERY message events */ - int dnstap_log_client_query_messages; - /** true to log dnstap CLIENT_RESPONSE message events */ - int dnstap_log_client_response_messages; - /** true to log dnstap FORWARDER_QUERY message events */ - int dnstap_log_forwarder_query_messages; - /** true to log dnstap FORWARDER_RESPONSE message events */ - int dnstap_log_forwarder_response_messages; - - /** true to disable DNSSEC lameness check in iterator */ - int disable_dnssec_lame_check; - - /** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */ - int ip_ratelimit; - /** ratelimit for ip addresses with a valid DNS Cookie. 0 is off, - * otherwise qps (unless overridden) */ - int ip_ratelimit_cookie; - /** number of slabs for ip_ratelimit cache */ - size_t ip_ratelimit_slabs; - /** memory size in bytes for ip_ratelimit cache */ - size_t ip_ratelimit_size; - /** ip_ratelimit factor, 0 blocks all, 10 allows 1/10 of traffic */ - int ip_ratelimit_factor; - /** ratelimit backoff, when on, if the limit is reached it is - * considered an attack and it backs off until 'demand' decreases over - * the RATE_WINDOW. */ - int ip_ratelimit_backoff; - - /** ratelimit for domains. 0 is off, otherwise qps (unless overridden) */ - int ratelimit; - /** number of slabs for ratelimit cache */ - size_t ratelimit_slabs; - /** memory size in bytes for ratelimit cache */ - size_t ratelimit_size; - /** ratelimits for domain (exact match) */ - struct config_str2list* ratelimit_for_domain; - /** ratelimits below domain */ - struct config_str2list* ratelimit_below_domain; - /** ratelimit factor, 0 blocks all, 10 allows 1/10 of traffic */ - int ratelimit_factor; - /** ratelimit backoff, when on, if the limit is reached it is - * considered an attack and it backs off until 'demand' decreases over - * the RATE_WINDOW. */ - int ratelimit_backoff; - - /** number of retries on outgoing queries */ - int outbound_msg_retry; - /** max sent queries per qstate; resets on query restarts (e.g., - * CNAMES) and referrals */ - int max_sent_count; - /** max number of query restarts; determines max length of CNAME chain */ - int max_query_restarts; - /** minimise outgoing QNAME and hide original QTYPE if possible */ - int qname_minimisation; - /** minimise QNAME in strict mode, minimise according to RFC. - * Do not apply fallback */ - int qname_minimisation_strict; - /** SHM data - true if shm is enabled */ - int shm_enable; - /** SHM data - key for the shm */ - int shm_key; - - /** list of EDNS client string entries, linked list */ - struct config_str2list* edns_client_strings; - /** EDNS opcode to use for EDNS client strings */ - uint16_t edns_client_string_opcode; - - /** DNSCrypt */ - /** true to enable dnscrypt */ - int dnscrypt; - /** port on which to provide dnscrypt service */ - int dnscrypt_port; - /** provider name 2.dnscrypt-cert.example.com */ - char* dnscrypt_provider; - /** dnscrypt secret keys 1.key */ - struct config_strlist* dnscrypt_secret_key; - /** dnscrypt provider certs 1.cert */ - struct config_strlist* dnscrypt_provider_cert; - /** dnscrypt provider certs 1.cert which have been rotated and should not be - * advertised through DNS's providername TXT record but are required to be - * able to handle existing traffic using the old cert. */ - struct config_strlist* dnscrypt_provider_cert_rotated; - /** memory size in bytes for dnscrypt shared secrets cache */ - size_t dnscrypt_shared_secret_cache_size; - /** number of slabs for dnscrypt shared secrets cache */ - size_t dnscrypt_shared_secret_cache_slabs; - /** memory size in bytes for dnscrypt nonces cache */ - size_t dnscrypt_nonce_cache_size; - /** number of slabs for dnscrypt nonces cache */ - size_t dnscrypt_nonce_cache_slabs; - - /** EDNS padding according to RFC7830 and RFC8467 */ - /** true to enable padding of responses (default: on) */ - int pad_responses; - /** block size with which to pad encrypted responses (default: 468) */ - size_t pad_responses_block_size; - /** true to enable padding of queries (default: on) */ - int pad_queries; - /** block size with which to pad encrypted queries (default: 128) */ - size_t pad_queries_block_size; - - /** IPsec module */ -#ifdef USE_IPSECMOD - /** false to bypass the IPsec module */ - int ipsecmod_enabled; - /** whitelisted domains for ipsecmod */ - struct config_strlist* ipsecmod_whitelist; - /** path to external hook */ - char* ipsecmod_hook; - /** true to proceed even with a bogus IPSECKEY */ - int ipsecmod_ignore_bogus; - /** max TTL for the A/AAAA records that call the hook */ - int ipsecmod_max_ttl; - /** false to proceed even when ipsecmod_hook fails */ - int ipsecmod_strict; -#endif - - /* cachedb module */ -#ifdef USE_CACHEDB - /** backend DB name */ - char* cachedb_backend; - /** secret seed for hash key calculation */ - char* cachedb_secret; -#ifdef USE_REDIS - /** redis server's IP address or host name */ - char* redis_server_host; - /** redis server's TCP port */ - int redis_server_port; - /** redis server's unix path. Or "", NULL if unused */ - char* redis_server_path; - /** redis server's AUTH password. Or "", NULL if unused */ - char* redis_server_password; - /** timeout (in ms) for communication with the redis server */ - int redis_timeout; - /** set timeout on redis records based on DNS response ttl */ - int redis_expire_records; -#endif -#endif - /** Downstream DNS Cookies */ - /** do answer with server cookie when request contained cookie option */ - int do_answer_cookie; - /** cookie secret */ - uint8_t cookie_secret[40]; - /** cookie secret length */ - size_t cookie_secret_len; - - /* ipset module */ -#ifdef USE_IPSET - char* ipset_name_v4; - char* ipset_name_v6; -#endif - /** respond with Extended DNS Errors (RFC8914) */ - int ede; -}; - -/** from cfg username, after daemonize setup performed */ -extern uid_t cfg_uid; -/** from cfg username, after daemonize setup performed */ -extern gid_t cfg_gid; -/** debug and enable small timeouts */ -extern int autr_permit_small_holddown; -/** size (in bytes) of stream wait buffers max */ -extern size_t stream_wait_max; -/** size (in bytes) of all total HTTP2 query buffers max */ -extern size_t http2_query_buffer_max; -/** size (in bytes) of all total HTTP2 response buffers max */ -extern size_t http2_response_buffer_max; - -/** - * Stub config options - */ -struct config_stub { - /** next in list */ - struct config_stub* next; - /** domain name (in text) of the stub apex domain */ - char* name; - /** list of stub nameserver hosts (domain name) */ - struct config_strlist* hosts; - /** list of stub nameserver addresses (IP address) */ - struct config_strlist* addrs; - /** if stub-prime is set */ - int isprime; - /** if forward-first is set (failover to without if fails) */ - int isfirst; - /** use tcp for queries to this stub */ - int tcp_upstream; - /** use SSL for queries to this stub */ - int ssl_upstream; - /*** no cache */ - int no_cache; -}; - -/** - * Auth config options - */ -struct config_auth { - /** next in list */ - struct config_auth* next; - /** domain name (in text) of the auth apex domain */ - char* name; - /** list of masters */ - struct config_strlist* masters; - /** list of urls */ - struct config_strlist* urls; - /** list of allow-notify */ - struct config_strlist* allow_notify; - /** zonefile (or NULL) */ - char* zonefile; - /** provide downstream answers */ - int for_downstream; - /** provide upstream answers */ - int for_upstream; - /** fallback to recursion to authorities if zone expired and other - * reasons perhaps (like, query bogus) */ - int fallback_enabled; - /** this zone is used to create local-zone policies */ - int isrpz; - /** rpz tags (or NULL) */ - uint8_t* rpz_taglist; - /** length of the taglist (in bytes) */ - size_t rpz_taglistlen; - /** Override RPZ action for this zone, regardless of zone content */ - char* rpz_action_override; - /** Log when this RPZ policy is applied */ - int rpz_log; - /** Display this name in the log when RPZ policy is applied */ - char* rpz_log_name; - /** Always reply with this CNAME target if the cname override action is - * used */ - char* rpz_cname; - /** signal nxdomain block with unset RA */ - int rpz_signal_nxdomain_ra; - /** Check ZONEMD records for this zone */ - int zonemd_check; - /** Reject absence of ZONEMD records, zone must have one */ - int zonemd_reject_absence; -}; - -/** - * View config options - */ -struct config_view { - /** next in list */ - struct config_view* next; - /** view name */ - char* name; - /** local zones */ - struct config_str2list* local_zones; - /** local data RRs */ - struct config_strlist* local_data; - /** local zones nodefault list */ - struct config_strlist* local_zones_nodefault; -#ifdef USE_IPSET - /** local zones ipset list */ - struct config_strlist* local_zones_ipset; -#endif - /** Fallback to global local_zones when there is no match in the view - * view specific tree. 1 for yes, 0 for no */ - int isfirst; - /** predefined actions for particular IP address responses */ - struct config_str2list* respip_actions; - /** data complementing the 'redirect' response IP actions */ - struct config_str2list* respip_data; -}; - -/** - * List of strings for config options - */ -struct config_strlist { - /** next item in list */ - struct config_strlist* next; - /** config option string */ - char* str; -}; - -/** - * List of two strings for config options - */ -struct config_str2list { - /** next item in list */ - struct config_str2list* next; - /** first string */ - char* str; - /** second string */ - char* str2; -}; - -/** - * List of three strings for config options - */ -struct config_str3list { - /** next item in list */ - struct config_str3list* next; - /** first string */ - char* str; - /** second string */ - char* str2; - /** third string */ - char* str3; -}; - - -/** - * List of string, bytestring for config options - */ -struct config_strbytelist { - /** next item in list */ - struct config_strbytelist* next; - /** first string */ - char* str; - /** second bytestring */ - uint8_t* str2; - size_t str2len; -}; - -/** - * Create config file structure. Filled with default values. - * @return: the new structure or NULL on memory error. - */ -struct config_file* config_create(void); - -/** - * Create config file structure for library use. Filled with default values. - * @return: the new structure or NULL on memory error. - */ -struct config_file* config_create_forlib(void); - -/** - * Read the config file from the specified filename. - * @param config: where options are stored into, must be freshly created. - * @param filename: name of configfile. If NULL nothing is done. - * @param chroot: if not NULL, the chroot dir currently in use (for include). - * @return: false on error. In that case errno is set, ENOENT means - * file not found. - */ -int config_read(struct config_file* config, const char* filename, - const char* chroot); - -/** - * Destroy the config file structure. - * @param config: to delete. - */ -void config_delete(struct config_file* config); - -/** - * Apply config to global constants; this routine is called in single thread. - * @param config: to apply. Side effect: global constants change. - */ -void config_apply(struct config_file* config); - -/** - * Find username, sets cfg_uid and cfg_gid. - * @param config: the config structure. - */ -void config_lookup_uid(struct config_file* config); - -/** - * Set the given keyword to the given value. - * @param config: where to store config - * @param option: option name, including the ':' character. - * @param value: value, this string is copied if needed, or parsed. - * The caller owns the value string. - * @return 0 on error (malloc or syntax error). - */ -int config_set_option(struct config_file* config, const char* option, - const char* value); - -/** - * Call print routine for the given option. - * @param cfg: config. - * @param opt: option name without trailing :. - * This is different from config_set_option. - * @param func: print func, called as (str, arg) for every data element. - * @param arg: user argument for print func. - * @return false if the option name is not supported (syntax error). - */ -int config_get_option(struct config_file* cfg, const char* opt, - void (*func)(char*,void*), void* arg); - -/** - * Get an option and return strlist - * @param cfg: config file - * @param opt: option name. - * @param list: list is returned here. malloced, caller must free it. - * @return 0=OK, 1=syntax error, 2=malloc failed. - */ -int config_get_option_list(struct config_file* cfg, const char* opt, - struct config_strlist** list); - -/** - * Get an option and collate results into string - * @param cfg: config file - * @param opt: option name. - * @param str: string. malloced, caller must free it. - * @return 0=OK, 1=syntax error, 2=malloc failed. - */ -int config_get_option_collate(struct config_file* cfg, const char* opt, - char** str); - -/** - * function to print to a file, use as func with config_get_option. - * @param line: text to print. \n appended. - * @param arg: pass a FILE*, like stdout. - */ -void config_print_func(char* line, void* arg); - -/** - * function to collate the text strings into a strlist_head. - * @param line: text to append. - * @param arg: pass a strlist_head structure. zeroed on start. - */ -void config_collate_func(char* line, void* arg); - -/** - * take a strlist_head list and return a malloc string. separated with newline. - * @param list: strlist first to collate. zeroes return "". - * @return NULL on malloc failure. Or if malloc failure happened in strlist. - */ -char* config_collate_cat(struct config_strlist* list); - -/** - * Append text at end of list. - * @param list: list head. zeroed at start. - * @param item: new item. malloced by caller. if NULL the insertion fails. - * @return true on success. - * on fail the item is free()ed. - */ -int cfg_strlist_append(struct config_strlist_head* list, char* item); - -/** - * Searches the end of a string list and appends the given text. - * @param head: pointer to strlist head variable. - * @param item: new item. malloced by caller. if NULL the insertion fails. - * @return true on success. - */ -int cfg_strlist_append_ex(struct config_strlist** head, char* item); - -/** - * Find string in strlist. - * @param head: pointer to strlist head variable. - * @param item: the item to search for. - * @return: the element in the list when found, NULL otherwise. - */ -struct config_strlist* cfg_strlist_find(struct config_strlist* head, - const char* item); - -/** - * Insert string into strlist. - * @param head: pointer to strlist head variable. - * @param item: new item. malloced by caller. If NULL the insertion fails. - * @return: true on success. - * on fail, the item is free()d. - */ -int cfg_strlist_insert(struct config_strlist** head, char* item); - -/** insert with region for allocation. */ -int cfg_region_strlist_insert(struct regional* region, - struct config_strlist** head, char* item); - -/** - * Insert string into str2list. - * @param head: pointer to str2list head variable. - * @param item: new item. malloced by caller. If NULL the insertion fails. - * @param i2: 2nd string, malloced by caller. If NULL the insertion fails. - * @return: true on success. - * on fail, the item and i2 are free()d. - */ -int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2); - -/** - * Insert string into str3list. - * @param head: pointer to str3list head variable. - * @param item: new item. malloced by caller. If NULL the insertion fails. - * @param i2: 2nd string, malloced by caller. If NULL the insertion fails. - * @param i3: 3rd string, malloced by caller. If NULL the insertion fails. - * @return: true on success. - */ -int cfg_str3list_insert(struct config_str3list** head, char* item, char* i2, - char* i3); - -/** - * Insert string into strbytelist. - * @param head: pointer to strbytelist head variable. - * @param item: new item. malloced by caller. If NULL the insertion fails. - * @param i2: 2nd string, malloced by caller. If NULL the insertion fails. - * @param i2len: length of the i2 bytestring. - * @return: true on success. - */ -int cfg_strbytelist_insert(struct config_strbytelist** head, char* item, - uint8_t* i2, size_t i2len); - -/** - * Find stub in config list, also returns prevptr (for deletion). - * @param pp: call routine with pointer to a pointer to the start of the list, - * if the stub is found, on exit, the value contains a pointer to the - * next pointer that points to the found element (or to the list start - * pointer if it is the first element). - * @param nm: name of stub to find. - * @return: pointer to config_stub if found, or NULL if not found. - */ -struct config_stub* cfg_stub_find(struct config_stub*** pp, const char* nm); - -/** - * Delete items in config string list. - * @param list: list. - */ -void config_delstrlist(struct config_strlist* list); - -/** - * Delete items in config double string list. - * @param list: list. - */ -void config_deldblstrlist(struct config_str2list* list); - -/** - * Delete items in config triple string list. - * @param list: list. - */ -void config_deltrplstrlist(struct config_str3list* list); - -/** delete string array */ -void config_del_strarray(char** array, int num); - -/** delete stringbytelist */ -void config_del_strbytelist(struct config_strbytelist* list); - -/** - * Delete a stub item - * @param p: stub item - */ -void config_delstub(struct config_stub* p); - -/** - * Delete items in config stub list. - * @param list: list. - */ -void config_delstubs(struct config_stub* list); - -/** - * Delete an auth item - * @param p: auth item - */ -void config_delauth(struct config_auth* p); - -/** - * Delete items in config auth list. - * @param list: list. - */ -void config_delauths(struct config_auth* list); - -/** - * Delete a view item - * @param p: view item - */ -void config_delview(struct config_view* p); - -/** - * Delete items in config view list. - * @param list: list. - */ -void config_delviews(struct config_view* list); - -/** check if config for remote control turns on IP-address interface - * with certificates or a named pipe without certificates. */ -int options_remote_is_address(struct config_file* cfg); - -/** - * Convert 14digit to time value - * @param str: string of 14 digits - * @return time value or 0 for error. - */ -time_t cfg_convert_timeval(const char* str); - -/** - * Count number of values in the string. - * format ::= (sp num)+ sp - * num ::= [-](0-9)+ - * sp ::= (space|tab)* - * - * @param str: string - * @return: 0 on parse error, or empty string, else - * number of integer values in the string. - */ -int cfg_count_numbers(const char* str); - -/** - * Convert a 'nice' memory or file size into a bytecount - * From '100k' to 102400. and so on. Understands kKmMgG. - * k=1024, m=1024*1024, g=1024*1024*1024. - * @param str: string - * @param res: result is stored here, size in bytes. - * @return: true if parsed correctly, or 0 on a parse error (and an error - * is logged). - */ -int cfg_parse_memsize(const char* str, size_t* res); - -/** - * Parse nsid from string into binary nsid. nsid is either a hexadecimal - * string or an ascii string prepended with ascii_ in which case the - * characters after ascii_ are simply copied. - * @param str: the string to parse. - * @param nsid_len: returns length of nsid in bytes. - * @return malloced bytes or NULL on parse error or malloc failure. - */ -uint8_t* cfg_parse_nsid(const char* str, uint16_t* nsid_len); - -/** - * Add a tag name to the config. It is added at the end with a new ID value. - * @param cfg: the config structure. - * @param tag: string (which is copied) with the name. - * @return: false on alloc failure. - */ -int config_add_tag(struct config_file* cfg, const char* tag); - -/** - * Find tag ID in the tag list. - * @param cfg: the config structure. - * @param tag: string with tag name to search for. - * @return: 0..(num_tags-1) with tag ID, or -1 if tagname is not found. - */ -int find_tag_id(struct config_file* cfg, const char* tag); - -/** - * parse taglist from string into bytestring with bitlist. - * @param cfg: the config structure (with tagnames) - * @param str: the string to parse. Parse puts 0 bytes in string. - * @param listlen: returns length of in bytes. - * @return malloced bytes with a bitlist of the tags. or NULL on parse error - * or malloc failure. - */ -uint8_t* config_parse_taglist(struct config_file* cfg, char* str, - size_t* listlen); - -/** - * convert tag bitlist to a malloced string with tag names. For debug output. - * @param cfg: the config structure (with tagnames) - * @param taglist: the tag bitlist. - * @param len: length of the tag bitlist. - * @return malloced string or NULL. - */ -char* config_taglist2str(struct config_file* cfg, uint8_t* taglist, - size_t len); - -/** - * see if two taglists intersect (have tags in common). - * @param list1: first tag bitlist. - * @param list1len: length in bytes of first list. - * @param list2: second tag bitlist. - * @param list2len: length in bytes of second list. - * @return true if there are tags in common, 0 if not. - */ -int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2, - size_t list2len); - -/** - * Parse local-zone directive into two strings and register it in the config. - * @param cfg: to put it in. - * @param val: argument strings to local-zone, "example.com nodefault". - * @return: false on failure - */ -int cfg_parse_local_zone(struct config_file* cfg, const char* val); - -/** - * Mark "number" or "low-high" as available or not in ports array. - * @param str: string in input - * @param allow: give true if this range is permitted. - * @param avail: the array from cfg. - * @param num: size of the array (65536). - * @return: true if parsed correctly, or 0 on a parse error (and an error - * is logged). - */ -int cfg_mark_ports(const char* str, int allow, int* avail, int num); - -/** - * Get a condensed list of ports returned. allocated. - * @param cfg: config file. - * @param avail: the available ports array is returned here. - * @return: number of ports in array or 0 on error. - */ -int cfg_condense_ports(struct config_file* cfg, int** avail); - -/** - * Apply system specific port range policy. - * @param cfg: config file. - * @param num: size of the array (65536). - */ -void cfg_apply_local_port_policy(struct config_file* cfg, int num); - -/** - * Scan ports available - * @param avail: the array from cfg. - * @param num: size of the array (65536). - * @return the number of ports available for use. - */ -int cfg_scan_ports(int* avail, int num); - -/** - * Convert a filename to full pathname in original filesys - * @param fname: the path name to convert. - * Must not be null or empty. - * @param cfg: config struct for chroot and chdir (if set). - * @param use_chdir: if false, only chroot is applied. - * @return pointer to malloced buffer which is: [chroot][chdir]fname - * or NULL on malloc failure. - */ -char* fname_after_chroot(const char* fname, struct config_file* cfg, - int use_chdir); - -/** - * Convert a ptr shorthand into a full reverse-notation PTR record. - * @param str: input string, "IP name" - * @return: malloced string "reversed-ip-name PTR name" - */ -char* cfg_ptr_reverse(char* str); - -/** - * Used during options parsing - */ -struct config_parser_state { - /** name of file being parser */ - char* filename; - /** line number in the file, starts at 1 */ - int line; - /** number of errors encountered */ - int errors; - /** the result of parsing is stored here. */ - struct config_file* cfg; - /** the current chroot dir (or NULL if none) */ - const char* chroot; - /** if we are started in a toplevel, or not, after a force_toplevel */ - int started_toplevel; -}; - -/** global config parser object used during config parsing */ -extern struct config_parser_state* cfg_parser; -/** init lex state */ -void init_cfg_parse(void); -/** lex in file */ -extern FILE* ub_c_in; -/** lex out file */ -extern FILE* ub_c_out; -/** the yacc lex generated parse function */ -int ub_c_parse(void); -/** the lexer function */ -int ub_c_lex(void); -/** wrap function */ -int ub_c_wrap(void); -/** parsing helpers: print error with file and line numbers */ -void ub_c_error(const char* msg); -/** parsing helpers: print error with file and line numbers */ -void ub_c_error_msg(const char* fmt, ...) ATTR_FORMAT(printf, 1, 2); - -#ifdef UB_ON_WINDOWS -/** - * Obtain registry string (if it exists). - * @param key: key string - * @param name: name of value to fetch. - * @return malloced string with the result or NULL if it did not - * exist on an error (logged with log_err) was encountered. - */ -char* w_lookup_reg_str(const char* key, const char* name); - -/** Modify directory in options for module file name */ -void w_config_adjust_directory(struct config_file* cfg); -#endif /* UB_ON_WINDOWS */ - -/** debug option for unit tests. */ -extern int fake_dsa, fake_sha1; - -/** see if interface is https, its port number == the https port number */ -int if_is_https(const char* ifname, const char* port, int https_port); - -/** - * Return true if the config contains settings that enable https. - * @param cfg: config information. - * @return true if https ports are used for server. - */ -int cfg_has_https(struct config_file* cfg); - -/** see if interface is PROXYv2, its port number == the proxy port number */ -int if_is_pp2(const char* ifname, const char* port, - struct config_strlist* proxy_protocol_port); - -/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */ -int if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port); -#ifdef USE_LINUX_IP_LOCAL_PORT_RANGE -#define LINUX_IP_LOCAL_PORT_RANGE_PATH "/proc/sys/net/ipv4/ip_local_port_range" -#endif - -#endif /* UTIL_CONFIG_FILE_H */ diff --git a/crates/libunbound-sys/unbound/util/configlexer.c b/crates/libunbound-sys/unbound/util/configlexer.c deleted file mode 100644 index 546800c2..00000000 --- a/crates/libunbound-sys/unbound/util/configlexer.c +++ /dev/null @@ -1,7564 +0,0 @@ -#include "config.h" -#include "util/configyyrename.h" - -#line 2 "" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 4 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#ifndef SIZE_MAX -#define SIZE_MAX (~(size_t)0) -#endif - -#endif /* ! C99 */ - -#endif /* ! FLEXINT_H */ - -/* begin standard C++ headers. */ - -/* TODO: this is always defined, so inline it */ -#define yyconst const - -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an - * integer in range [0..255] for use as an array index. - */ -#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -extern int yyleng; - -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - #define YY_LINENO_REWIND_TO(ptr) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = NULL; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart ( FILE *input_file ); -void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); -void yy_delete_buffer ( YY_BUFFER_STATE b ); -void yy_flush_buffer ( YY_BUFFER_STATE b ); -void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); -void yypop_buffer_state ( void ); - -static void yyensure_buffer_stack ( void ); -static void yy_load_buffer_state ( void ); -static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); -#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); -YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); - -void *yyalloc ( yy_size_t ); -void *yyrealloc ( void *, yy_size_t ); -void yyfree ( void * ); - -#define yy_new_buffer yy_create_buffer -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ -typedef flex_uint8_t YY_CHAR; - -FILE *yyin = NULL, *yyout = NULL; - -typedef int yy_state_type; - -extern int yylineno; -int yylineno = 1; - -extern char *yytext; -#ifdef yytext_ptr -#undef yytext_ptr -#endif -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state ( void ); -static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); -static int yy_get_next_buffer ( void ); -static void yynoreturn yy_fatal_error ( const char* msg ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - (yytext_ptr) -= (yy_more_len); \ - yyleng = (int) (yy_cp - (yytext_ptr)); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 381 -#define YY_END_OF_BUFFER 382 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static const flex_int16_t yy_accept[3778] = - { 0, - 1, 1, 355, 355, 359, 359, 363, 363, 367, 367, - 1, 1, 371, 371, 375, 375, 382, 379, 1, 353, - 353, 380, 2, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 380, 355, 356, 356, 357, - 380, 359, 360, 360, 361, 380, 366, 363, 364, 364, - 365, 380, 367, 368, 368, 369, 380, 378, 354, 2, - 358, 378, 380, 374, 371, 372, 372, 373, 380, 375, - 376, 376, 377, 380, 379, 0, 1, 2, 2, 2, - 2, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 355, 0, 359, 0, 366, 0, 363, 367, 0, 378, - 0, 2, 2, 378, 374, 0, 371, 375, 0, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 378, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 351, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 136, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 146, 379, 379, 379, 379, 379, - - 379, 379, 378, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 118, 379, - 379, 350, 379, 379, 379, 379, 379, 379, 379, 379, - - 8, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 137, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 151, 379, 379, - 378, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 341, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 378, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 71, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 265, 379, 14, 15, 379, 379, 20, 19, - - 379, 379, 244, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 144, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 242, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 3, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 378, 379, 379, 379, 379, 379, 379, 379, 379, 333, - 379, 379, 332, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 362, 379, 379, 379, - 379, 379, 379, 379, 379, 70, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 74, 379, 302, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 342, 343, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 75, 379, 379, - - 145, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 140, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 231, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 22, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 172, 379, 379, 379, 379, 379, - 378, 362, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 116, 379, 379, 379, 379, - 379, 379, 379, 310, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 16, 379, 379, 379, 379, 379, - 379, 379, 379, 199, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 171, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 115, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 37, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 38, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 72, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 143, - 379, 379, 379, 378, 379, 379, 379, 379, 379, 379, - 135, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 73, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 269, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 200, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 60, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 288, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 65, 379, 66, - 379, 379, 379, 379, 379, 379, 119, 379, 120, 379, - - 379, 379, 379, 379, 117, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 7, 379, - 379, 379, 379, 378, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 254, 379, 379, 379, 379, 175, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 270, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 51, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 61, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 222, 379, 221, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 17, 18, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 76, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 230, 379, 379, 379, 379, 379, 379, 379, 122, - 379, 121, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 213, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 152, 379, - 379, 379, 378, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 110, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 97, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 243, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 102, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 69, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 216, - 217, 379, 379, 379, 304, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 6, 379, 379, 379, 379, 379, 379, 379, 323, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 308, - 379, 379, 379, 379, 379, 379, 379, 334, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 48, 379, 379, 379, 379, 379, 50, - 379, 379, 379, 98, 379, 379, 379, 379, 379, 58, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 378, 379, 209, 379, 379, 379, 147, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 235, - 379, 379, 210, 379, 379, 379, 250, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 59, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 149, - 128, 379, 129, 379, 379, 379, 379, 127, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 168, 379, - 379, 56, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 286, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 211, 379, 379, 379, 379, 379, 214, 379, - 220, 379, 379, 379, 379, 379, 379, 379, 379, 249, - 379, 379, 379, 379, 379, 379, 253, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 114, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 141, - 379, 379, 379, 379, 379, 379, 379, 379, 67, 379, - 379, 379, 379, 31, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 21, 379, 379, 379, - - 379, 379, 379, 379, 32, 41, 379, 180, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 207, 379, 379, 378, 379, 379, 379, 379, - 346, 379, 379, 84, 86, 379, 379, 379, 379, 379, - 379, 379, 347, 379, 379, 379, 379, 379, 379, 312, - 379, 379, 379, 379, 266, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 130, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 167, 379, 52, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 260, 379, 379, 379, 379, 379, - 379, 379, 379, 327, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 174, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 321, - 379, 379, 379, 379, 241, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 339, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 192, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 123, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 187, 379, 201, 379, 379, 379, - 379, 379, 379, 379, 378, 379, 155, 379, 379, 379, - 379, 379, 109, 379, 379, 379, 379, 233, 379, 379, - 379, 379, 379, 379, 251, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 278, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 148, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 191, 379, 379, 379, 379, 379, 379, 379, - 87, 379, 88, 379, 379, 379, 379, 379, 263, 379, - 379, 379, 379, 379, 68, 330, 379, 379, 379, 379, - 379, 96, 202, 379, 223, 379, 255, 379, 379, 215, - 305, 379, 379, 379, 379, 300, 379, 379, 379, 80, - 379, 204, 379, 379, 379, 379, 379, 379, 9, 379, - 379, 379, 379, 379, 113, 379, 379, 379, 379, 379, - 379, 292, 379, 379, 379, 379, 379, 232, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 378, 379, 379, 379, 379, 190, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 176, 379, 311, 379, 379, 379, 379, 379, 277, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 245, 379, 379, 379, 379, 379, 379, 303, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 173, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 331, 379, - 203, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 79, 81, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 112, 379, 379, 379, 379, 379, 379, 290, - 379, 379, 379, 379, 379, 379, 307, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 237, 379, 39, 33, 35, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 40, 379, - 34, 36, 379, 42, 379, 379, 379, 379, 379, 379, - - 379, 108, 379, 186, 379, 379, 379, 379, 379, 379, - 379, 378, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 239, 236, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 78, 379, 379, 379, 150, 379, - 131, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 169, 53, 379, 379, 379, 370, 13, 379, - 379, 379, 379, 379, 379, 379, 156, 379, 379, 379, - 379, 379, 379, 379, 379, 325, 379, 328, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 12, 379, 379, 23, 379, 379, 379, 379, 379, - 379, 379, 296, 379, 379, 379, 379, 379, 379, 309, - 379, 379, 379, 379, 82, 379, 247, 379, 379, 379, - 379, 379, 238, 379, 379, 379, 379, 77, 379, 379, - 379, 379, 379, 379, 24, 379, 379, 49, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 185, 184, 379, 379, 370, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 240, 234, 379, 252, 379, 379, - 313, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 197, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 89, 379, - 379, 379, 379, 379, 379, 379, 379, 291, 379, 379, - 379, 379, 219, 379, 379, 379, 379, 379, 379, 246, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 298, 379, 379, 379, 335, 379, 337, 336, 182, 379, - 379, 379, 83, 379, 379, 379, 379, 193, 379, 379, - 379, 379, 379, 124, 126, 125, 379, 379, 379, 26, - 379, 379, 177, 379, 179, 379, 224, 379, 379, 379, - 379, 183, 379, 379, 379, 379, 256, 379, 379, 379, - - 379, 379, 379, 379, 158, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 268, 379, 379, - 379, 379, 379, 379, 379, 348, 379, 28, 379, 306, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 94, 225, - 379, 379, 262, 379, 379, 379, 289, 379, 329, 379, - 218, 379, 379, 301, 379, 379, 379, 299, 62, 379, - 379, 379, 379, 379, 379, 379, 4, 379, 379, 379, - 379, 379, 139, 379, 157, 379, 379, 379, 198, 30, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 259, - 43, 44, 379, 379, 379, 379, 379, 379, 379, 314, - 379, 379, 379, 379, 379, 379, 379, 276, 379, 379, - 379, 379, 379, 379, 379, 379, 228, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 93, 92, 379, 379, 63, 379, 379, 287, - 295, 379, 264, 379, 379, 379, 379, 379, 11, 379, - 379, 379, 379, 352, 379, 379, 379, 379, 379, 138, - 379, 379, 379, 379, 379, 379, 226, 99, 379, 379, - 46, 379, 379, 379, 379, 379, 379, 379, 379, 189, - - 379, 379, 379, 379, 379, 379, 379, 160, 379, 379, - 379, 379, 267, 379, 379, 379, 379, 379, 275, 379, - 379, 379, 379, 153, 379, 379, 379, 132, 134, 133, - 379, 379, 379, 101, 105, 100, 379, 170, 379, 379, - 379, 379, 90, 379, 261, 297, 379, 379, 379, 379, - 379, 379, 10, 379, 379, 379, 379, 379, 293, 340, - 379, 379, 379, 379, 379, 379, 379, 379, 345, 45, - 379, 379, 379, 379, 379, 188, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 106, 104, 379, 379, 57, 379, 379, 91, 379, - 326, 379, 379, 379, 379, 25, 379, 379, 379, 379, - 379, 212, 379, 379, 338, 379, 379, 379, 379, 227, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 208, - 379, 379, 178, 85, 379, 379, 379, 379, 379, 315, - 379, 379, 379, 379, 379, 379, 379, 272, 379, 379, - 271, 154, 379, 379, 103, 379, 54, 379, 379, 161, - 162, 165, 166, 163, 164, 95, 324, 379, 379, 294, - 142, 379, 379, 379, 379, 27, 379, 181, 379, 379, - 379, 379, 206, 379, 258, 379, 379, 379, 379, 379, - - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 195, 194, 229, - 47, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 322, 379, 379, 379, 379, - 111, 379, 257, 379, 285, 319, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 349, 379, 107, - 55, 64, 5, 379, 379, 248, 379, 379, 320, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 273, 29, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - - 379, 379, 274, 379, 379, 379, 159, 379, 379, 379, - 379, 379, 379, 379, 379, 196, 379, 205, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 316, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 344, 379, 379, 281, 379, - 379, 379, 379, 379, 317, 379, 379, 379, 379, 379, - 379, 318, 379, 379, 379, 279, 379, 282, 283, 379, - 379, 379, 379, 379, 280, 284, 0 - } ; - -static const YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 1, 5, 6, 1, 1, 1, 7, 1, - 1, 1, 1, 1, 8, 1, 1, 1, 9, 1, - 10, 11, 1, 12, 1, 1, 1, 13, 1, 1, - 1, 1, 1, 1, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 1, 40, 1, 1, 1, 1, 41, 42, 43, 44, - - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static const YY_CHAR yy_meta[67] = - { 0, - 1, 2, 3, 4, 5, 1, 6, 1, 1, 1, - 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1 - } ; - -static const flex_int16_t yy_base[3796] = - { 0, - 0, 0, 64, 67, 70, 72, 78, 84, 89, 92, - 131, 137, 112, 118, 123, 142, 616, 527, 96,10717, - 10717,10717, 160, 185, 116, 183, 229, 132, 175, 173, - 232, 50, 66, 120, 263, 275, 159, 323, 134, 375, - 416, 286, 308, 283, 126, 258, 516,10717,10717,10717, - 95, 496,10717,10717,10717, 187, 471, 490,10717,10717, - 10717, 238, 449,10717,10717,10717, 104, 401,10717, 351, - 10717, 194, 369, 379, 381,10717,10717,10717, 375, 309, - 10717,10717,10717, 146, 307, 392, 177, 0, 405, 0, - 0, 201, 270, 233, 230, 310, 259, 290, 371, 178, - - 335, 396, 413, 415, 330, 358, 417, 368, 442, 402, - 453, 423, 448, 451, 450, 454, 412, 481, 476, 469, - 480, 503, 494, 475, 463, 381, 504, 502, 511, 512, - 514, 515, 530, 531, 532, 551, 543, 345, 544, 561, - 540, 542, 554, 591, 559, 581, 577, 596, 595, 373, - 579, 599, 569, 608, 603, 622, 616, 621, 629, 624, - 281, 180, 273, 339, 268, 668, 273, 228, 222, 210, - 678, 682, 0, 650, 152, 690, 188, 128, 672, 663, - 680, 660, 670, 665, 683, 675, 692, 674, 679, 699, - 676, 697, 702, 727, 705, 709, 716, 250, 743, 787, - - 732, 722, 745, 720, 747, 748, 738, 731, 761, 758, - 766, 721, 754, 767, 785, 765, 794, 798, 835, 810, - 786, 789, 256, 816, 825, 258, 802, 418, 845, 829, - 792, 833, 91, 851, 843, 856, 857, 862, 848, 863, - 865, 867, 880, 852, 879, 882, 892, 889, 884, 888, - 881, 910, 908, 900, 917, 911, 922, 923, 919, 928, - 912, 929, 945, 924, 946, 957, 959, 939, 967, 951, - 950, 970, 965, 981, 980, 977, 960, 984, 976, 974, - 987, 982, 1000, 990, 1007, 1023, 1024, 1016, 1020, 1029, - 1015, 1014, 1017, 1022, 1019, 1037, 1011, 1042, 1050, 1052, - - 1058, 167, 1043, 1064, 1066, 1055, 1072, 1075, 1070, 1080, - 1081, 1049,10717, 1088, 1082, 1108, 1102, 1111, 1106, 1112, - 1114, 1116, 1117, 1098, 1103, 1099, 1115, 1123, 1129, 1131, - 1130, 1133, 1135, 1163, 1147, 1166, 1155, 1171, 1170, 1156, - 1205, 1172, 1157, 1180, 1250, 1174, 1176, 1194, 1207, 1220, - 320, 1208, 1178, 1237, 1203, 1204, 1243, 1239, 1247, 1258, - 1273, 1262, 1264, 1272, 1286, 1288, 1290, 1284, 1259, 1289, - 1232, 1306,10717, 1292, 1305, 1245, 1316, 1330, 1337, 1324, - 1281, 1355, 1317, 1322, 1319, 1327, 1351, 1403, 1451, 1339, - 1360, 1346, 1357, 1366,10717, 1392, 1382, 1500, 1387, 1391, - - 1410, 1407, 1405, 1398, 1431, 1432, 1409, 1352, 1438, 1423, - 1350, 1448, 1465, 1459, 1457, 1460, 1478, 1458, 1490, 1483, - 1365, 1505, 1491, 1496, 1507, 1529, 1501, 1520, 1532, 1546, - 1530, 1531, 1533, 1538, 1541, 1559, 1547, 1564, 1558, 1568, - 1569, 1556, 1565, 1574, 1582, 1589, 1604, 1649, 1609, 1596, - 1593, 1602, 1601, 1620, 1617, 1615, 1614, 1616, 1629, 1630, - 1651, 1595, 1415, 1653, 1642, 1659, 1664, 1668, 1656, 1675, - 1679, 1683, 1691, 1689, 1685, 1686, 1695, 1706, 1687, 1698, - 1712, 1716, 1714, 1723, 1732, 1719, 1728, 1439,10717, 1743, - 1741,10717, 1727, 1744, 1736, 1749, 1739, 1756, 1745, 1750, - - 10717, 1773, 1763, 1774, 1778, 1768, 1779, 1771, 1783, 1792, - 1772, 1803, 1799, 1790, 1800, 1807, 1801, 1805, 1809, 1827, - 1819, 1830, 1822, 1826, 1836, 1831, 1832, 1841, 1846, 1834, - 1857, 1842, 1903,10717, 1859, 1860, 1865, 1862, 1869, 1886, - 1878, 1893, 1905, 1885, 1920, 1924, 1926, 1953, 1927, 1912, - 1930, 1936, 1941, 1963, 1874, 1965, 1956, 1962, 1960, 1972, - 1957, 1955, 1989, 1969, 1987, 1980, 1991,10717, 1999, 2005, - 2007, 1875, 1998, 2000, 1993, 2003, 1986, 2004, 2022, 2024, - 2016, 2021, 2030, 2033, 2045, 2052, 2046, 2057, 2064, 2049, - 2050, 2048, 2051, 2060, 2067, 2086, 2047, 2069, 2085, 2082, - - 2083, 158, 2076, 2099, 2100, 2091, 2106, 2089, 2087, 2092, - 2112, 2116, 2101, 2103, 2114, 2118, 2113, 2127, 2133, 2129, - 2131, 2145, 2134, 2148, 2141, 2156, 2144, 2160, 2161, 2143, - 2158, 2170, 2172, 2164, 2178, 2195, 2182, 2193, 2184, 2188, - 2205, 2208, 2209, 2197,10717, 2219, 2217, 2215, 2234, 2236, - 2225, 2242, 2227, 2230, 2244, 2245, 2254, 2229, 2262, 2255, - 2261, 2268, 2256, 2252, 2274, 2275, 2282, 2272, 2286, 2293, - 2299, 2287, 2302, 2301, 2297, 2298, 2304, 2311, 2308, 2313, - 2317, 2339, 2333, 2321, 2332, 2325, 2355, 2334, 2338, 2352, - 2358, 2343, 2360, 2370, 2356, 2366, 2373, 2374, 2387, 2361, - - 2365, 2401, 2391, 2394, 2384, 2408, 2393, 2411, 2398, 2397, - 2423, 2426, 2428, 2407, 2431, 2425, 2421, 2434, 2436, 2442, - 2440, 2461, 2450, 2467, 2452, 2456, 2454, 2463, 2468, 2477, - 2471, 2483, 2487, 2488, 2493, 2486, 2498, 2502, 2494, 2518, - 2520, 2513, 2522, 2515, 2523, 2531, 2532, 2533, 2530, 2549, - 2550, 2554, 2538, 2564, 2566, 2560, 2565, 2558, 2559, 2575, - 2568, 2579, 2585, 2594, 2599, 2587, 2595, 2593, 2606, 2596, - 2592, 2615, 2637, 2616, 2620, 2618,10717, 2622, 2623, 2629, - 2612, 2630, 2639, 2628, 2640, 2649, 2652, 2655, 2645, 2644, - 2650, 2696,10717, 2668,10717,10717, 1473, 2667,10717,10717, - - 2677, 2687,10717, 2680, 2694, 2690, 2676, 2720, 2711, 2721, - 2719, 2713, 2723, 2714, 2679, 2764, 2732, 2728, 2742, 2735, - 2750, 2743, 2769, 2770, 2759, 2779, 2772, 2788, 2798, 2822, - 2797, 2806, 2793, 2814, 2817, 2816, 2820, 2824, 2709, 2825, - 2826, 2836, 2833, 2812, 2839, 2834, 2856, 2847, 2853, 2869, - 2850, 2859, 2851, 2761, 2874, 2872, 2881,10717, 2882, 2880, - 2875, 2884, 2885, 2895, 2883, 2896, 2889, 2898, 2909, 2913, - 2918, 2906, 2919, 2908, 2916, 2925, 2930, 2920, 2912, 2915, - 2941, 2940, 2942, 2958, 2964, 2944, 2947,10717, 2951, 2954, - 2946, 2967, 2971, 2976, 2977, 2961, 2959, 2974, 2987, 3013, - - 2978, 2994, 2997, 2996, 3007, 2993, 3008, 3022,10717, 3027, - 3018, 3009, 3023, 3010, 3036, 3039, 3042, 3024, 3044, 3038, - 3049, 3057, 3052, 3048, 3053, 3068, 3066, 3065, 3063, 3069, - 3079, 3090, 3073, 3096, 3102, 3084, 3093, 3106, 3099, 3108, - 3104, 3100, 3117, 3112, 3114, 3123, 3126, 3131, 3142, 3133, - 3128, 3143, 3157, 3150, 3137, 3153, 3161, 3141, 3170, 3172, - 3181, 3175, 3164, 3174, 3184, 3176, 3185, 3168, 3189, 3201, - 3215, 3191, 3203, 3221, 3198, 3209, 3211, 3227, 3216,10717, - 3200, 3223,10717, 3228, 3225, 3236, 3282, 3234, 3268, 3261, - 3252, 3270, 3248, 3274, 3262, 3272, 3275, 3292, 3281, 3301, - - 3297, 3313, 3300, 3316, 3314, 3318, 3308, 3332, 3325, 3320, - 3327, 3350, 3333, 3352, 3263, 3356, 3362, 477, 3369, 3343, - 3348, 3353, 3398, 3364, 3363, 3360, 3366, 3380, 3383, 3392, - 3395, 3370, 3402, 3401, 3411, 3405, 3407, 3432, 3423, 3396, - 3426, 3422, 3428, 3452, 3450, 3436,10717, 3463, 3457, 3447, - 3465, 3448, 3473, 3467, 3459,10717, 3462, 3476, 3464, 3481, - 3486, 3477, 3497, 3489, 3487, 3490, 3494, 3511, 3516, 3512, - 3513, 3524,10717, 3499,10717, 3517, 3507, 3521, 3536, 3537, - 3534, 3535, 3532, 3540, 3551, 3560,10717,10717, 3561, 3564, - 3562, 3573, 3575, 3577, 3570, 3580, 3572,10717, 3578, 3586, - - 10717, 3607, 3588, 3587, 3596, 3589, 3602, 3601, 3612, 3605, - 3629, 3606, 3632, 3616, 3635, 3627,10717, 3643, 3639, 3628, - 3645, 3646, 3647, 3648, 3655, 3656, 3652,10717, 3659, 3669, - 3674, 3668, 3686, 3693, 3688, 3676, 3695, 3699, 3684, 3687, - 3690, 3701, 3692, 3713, 3714, 3723, 3725, 3729, 3728, 3731, - 3740,10717, 3733, 3721, 3722, 3748, 3741, 3744, 3745, 3750, - 3757, 3752, 3755, 3761, 3773, 3767, 3775, 3765, 3781, 3768, - 3758, 3795, 3784, 3791, 3798, 3785, 3792, 3797, 3803, 552, - 3810, 3807, 3808, 3788,10717, 3819, 3817, 3824, 3834, 3836, - 3822, 115, 3831, 3835, 3840, 3848, 3820, 3849, 3857, 3851, - - 3865, 3875, 3858, 3868, 3879, 3877, 3869, 3872, 3884, 3878, - 3888, 3887, 3896, 3897, 3899,10717, 3894, 3905, 3904, 3910, - 3921, 3908, 3924,10717, 3932, 3941, 3939, 3933, 3946, 3947, - 3954, 3931, 3958, 3955,10717, 3967, 3956, 3966, 3952, 3981, - 3973, 3979, 3970,10717, 3992, 3991, 3993, 3984, 4002, 3997, - 4000, 3995, 4006, 4011, 4023, 4017, 4033, 4027, 4022, 4024, - 4025, 4036, 4031, 4044, 4020, 4054, 4056, 4052, 4050, 4059, - 4063, 4066, 4062, 4069, 4096, 4077,10717, 4099, 4080, 4086, - 4090, 4088, 4093, 4101, 4104, 4134, 4091, 4105, 4117, 4120, - 4161, 4125, 4131, 4144, 4148, 4136, 4145, 4150, 4146, 4155, - - 4158, 4171, 4163, 4197, 4179, 4176, 4188, 4209, 4205, 4186, - 4190, 4207, 4204, 4196, 4221, 4219, 4233, 4215, 4226, 4227, - 4259, 4238, 4235, 4254, 4260, 4245,10717, 4247, 4265, 4244, - 4266, 4276, 4294, 4281, 4239, 4291, 4283, 4289, 4282, 4286, - 4300, 4304, 4318, 4303, 4312, 4308, 4321, 4323, 4324, 4327, - 4311, 4330, 4331, 4340, 4344, 4343, 4347, 4360,10717, 4363, - 4364, 4346, 4367, 4368, 4357, 4372, 4374, 4373, 4385, 4386, - 4387, 4383, 4389, 4371, 4394, 4391, 4390, 4414, 4413, 4418, - 4405,10717, 4424, 4410, 4415, 4421, 4416, 4434, 4436, 4451, - 4455, 4454, 4461, 4460, 4446, 4463, 4467, 4457,10717, 4472, - - 4473, 4471, 4475, 4477, 4484, 4486, 4468, 4508, 4489,10717, - 4507, 4492, 4504, 4500, 4497, 4495, 4526, 4528, 4519, 4522, - 10717, 4531, 4534, 4520, 4523, 4539, 4542, 4541, 4537, 4552, - 4546, 4558, 4557, 4564, 4530, 4565, 4569,10717, 4568, 4602, - 4586, 4581, 4585, 4580, 4591, 4601, 4617, 4596, 4608, 4597, - 10717, 4631, 4623, 4628, 4641, 4615, 4621, 4633, 4635, 4648, - 4652, 4638, 4643, 4654, 4644,10717, 4655, 4658, 4670, 4671, - 4673, 4674, 4668, 4678, 4681, 4686, 4690, 4680, 4691, 4695, - 4697, 4707, 4704, 4718, 4708, 4713, 4720, 4719, 4724, 4715, - 4735, 4729, 4731, 4753, 4765, 4747, 4762, 4764, 4760, 4751, - - 4748, 4768, 4770, 4775, 4777, 4778, 4781,10717, 4783, 4780, - 4789, 4794, 4787, 4804, 4800, 4806, 4816, 4802, 4811, 4827, - 4809, 4828, 4853, 4856, 4814, 4836, 4833, 4838, 4849, 4861, - 4843, 4848, 4851, 4840, 4867, 4855, 4870, 4871, 4865, 4876, - 4882, 4875, 4892, 4885, 4896, 4887, 4888, 4897, 4902, 4908, - 4899, 4910, 4926, 4933, 4911, 4923, 4928, 4939, 4941, 4946, - 4952, 4931, 4947, 4950, 4948, 4974,10717, 4954, 4960, 4955, - 4964, 4969, 4990, 4989, 5000, 4983, 4991, 5005, 4997, 5009, - 5010, 4988, 5001, 5017, 5003, 5011, 5022,10717, 5015,10717, - 5039, 5024, 5038, 5046, 5044, 5028,10717, 5052,10717, 5051, - - 5056, 5041, 5042, 5060,10717, 5059, 5040, 5070, 5055, 5072, - 5079, 5078, 5073, 5077, 5097, 5081, 5082, 5100, 5089, 5108, - 5103, 5085, 5111, 5112, 5119, 5114, 5129, 5121, 5115, 5139, - 5124, 5146, 5127, 5138, 5141, 5151, 5145, 5162,10717, 5150, - 5166, 5168, 5170, 5171, 5165, 5172, 5184, 5174, 5180, 5191, - 5189, 5201, 5192, 5202, 5209, 5211, 5216, 5214, 5223, 5219, - 5228, 5215, 5231, 5232,10717, 5226, 5244, 5238, 5239,10717, - 5249, 5236, 5255, 5267, 5259, 5251, 5262, 5271, 5278, 5270, - 5263, 5265, 5304, 5296, 5294, 5290,10717, 5302, 5298, 5289, - 5305, 5313, 5300, 5323, 5333, 5334, 5318, 5341, 5338, 5343, - - 5331, 5329, 5335, 5332, 5350, 5360, 5362, 5368, 5359, 5372, - 5355, 5371, 5373, 5379, 5365, 5370, 5381, 5366, 5374, 5388, - 5393, 5395, 5386, 5389, 5415, 5416, 5405, 5420,10717, 5413, - 5421, 5417, 5431, 5408, 5422, 5436, 5423, 5450, 5458, 5452, - 10717, 5439, 5442, 5463, 5455, 5469, 5457, 5460, 5449, 5475, - 5482, 5477, 5496, 5498, 5489,10717, 5497,10717, 5481, 5508, - 5513, 5514, 5509, 5504, 5523, 5515, 5516, 5527, 5540, 5542, - 5525, 5530, 5553, 5541, 5543, 5552, 5544, 5572, 5538, 5555, - 5571, 5575, 5569, 5573, 5570, 5574, 5580, 5579, 5609, 5600, - 5601,10717,10717, 5587, 5597, 5616, 5620, 5602, 5621, 5632, - - 5634, 5629, 5626, 5607, 5642, 5628, 5671,10717, 5640, 5655, - 5650, 5669, 5661, 5656, 5660, 5679, 5685, 5681, 5677, 5689, - 5687,10717, 5680, 5683, 5695, 5690, 5698, 5712, 5697,10717, - 5718,10717, 5704, 5710, 5713, 5720, 5714, 5724, 5722, 5725, - 5730, 5740, 5744, 5763, 5749, 5769, 5762, 5753, 5768, 5752, - 5755, 5756, 5774, 5764, 5783, 5776, 5770, 5787,10717, 5788, - 5789, 5790, 5801, 5792, 5802, 5803, 5811, 5795,10717, 5813, - 5814, 5828, 5815, 5822, 5826, 5825, 5834, 5829, 5843, 5852, - 5845, 5853, 5850, 5851,10717, 5847, 5849, 5870, 5855, 5865, - 5875, 5868, 5882, 5871, 5888,10717, 5894, 5892, 5905, 5903, - - 5895, 5902, 5908, 5886, 5898, 5896, 5909, 5912, 5919, 5928, - 5930, 5925, 5938, 5936, 5929, 5948, 5954, 5935, 5961, 5921, - 5947,10717, 5955, 5964, 5965, 5962, 5946, 5977, 5980, 5989, - 5997, 5999, 5981, 6000, 6002, 5988, 5991, 5992, 6014, 6016, - 6007, 6019,10717, 6030, 6015, 6036, 6021, 6027, 6010, 6042, - 6038, 6031, 6047, 6050, 6040, 6043, 6048, 6056, 6065, 6063, - 6078, 6084, 6067, 6081, 6080, 6086, 6082, 6090, 6094, 6107, - 10717, 6089, 6092, 6105, 6113, 6111, 6116, 6091, 6126, 6121, - 6123, 6136, 6119, 6150, 6132, 6133, 6153, 6156, 6137,10717, - 10717, 6161, 6140, 6160,10717, 6164, 6149, 6171, 6166, 6159, - - 6176, 6174, 6168, 6179, 6192, 6195, 6181, 6208, 6205, 6184, - 6197,10717, 6219, 6215, 6223, 6218, 6221, 6230, 6225,10717, - 6214, 6234, 6239, 6244, 6242, 6241, 6243, 6240, 6250, 6246, - 6261, 6254, 6248, 6278, 6235, 6287, 6269, 6277, 6280,10717, - 6275, 6271, 6298, 6294, 6285, 6291, 6302,10717, 6296, 6304, - 6312, 6318, 6319, 6326, 6323, 6329, 6327, 6334, 6320, 6335, - 6339, 6347, 6337, 6351, 6353, 6368, 6354, 6360, 6362, 6356, - 6377, 6381, 6384,10717, 6383, 6390, 6366, 6398, 6391,10717, - 6397, 6412, 6395,10717, 6410, 6394, 6409, 6404, 6428,10717, - 6415, 6422, 6417, 6431, 6413, 6439, 6423, 6440, 6446, 6433, - - 6437, 6443, 6449,10717, 6450, 6444, 6464,10717, 6451, 6465, - 6473, 6480, 6481, 6466, 6487, 6477, 6489, 6479, 6488,10717, - 6493, 6499,10717, 6500, 6490, 6504,10717, 6506, 6507, 6517, - 6509, 6514, 6530, 6532, 6525, 6511, 6520, 6533, 6521, 6524, - 6549, 6551, 6559, 6545, 6552, 6547, 6544,10717, 6572, 6550, - 6566, 6578, 6562, 6580, 6585, 6579, 6576, 6593, 6583,10717, - 10717, 6601,10717, 6610, 6588, 6600, 6603,10717, 6602, 6608, - 6631, 6615, 6633, 6636, 6625, 6623, 6645, 6640,10717, 6647, - 6650,10717, 6630, 6649, 6659, 6642, 6657, 6663, 6661, 6669, - 6678, 6668, 6680, 6682, 6683, 6688, 6675, 6684, 6702, 6704, - - 6695, 6730,10717, 6703, 6711, 6712, 6713, 6708, 6721, 6739, - 6738, 6727,10717, 6750, 6735, 6740, 6751, 6745,10717, 6762, - 10717, 6757, 6764, 6768, 6779, 6767, 6770, 6676, 6772,10717, - 6785, 6774, 6793, 6777, 6791, 6807,10717, 6800, 6806, 6798, - 6804, 6801, 6815, 6819, 6813, 6817, 6850, 6827,10717, 6820, - 6838, 6843, 6837, 6840, 6846, 6844, 6849, 6863, 6856, 6858, - 6854, 6881, 6874, 6866, 6879, 6890, 6883, 6893, 6876,10717, - 6896, 6902, 6907, 6901, 6931, 6903, 6923, 6921,10717, 6924, - 6927, 6908, 6938,10717, 6934, 6936, 6946, 6875, 6935, 6949, - 6950, 6959, 6954, 6958, 6942, 6973,10717, 6976, 6977, 6970, - - 6982, 6986, 6983, 6980,10717,10717, 7002,10717, 6995, 6997, - 6996, 7009, 7005, 7017, 7012, 7022, 7033, 7016, 7018, 7036, - 7041, 7029,10717, 7032, 6868, 7028, 7070, 7057, 7067, 7063, - 10717, 7064, 7054,10717,10717, 7071, 7081, 7076, 7075, 7078, - 7077, 7065,10717, 7091, 7090, 7086, 7088, 7106, 7105,10717, - 7115, 7100, 7117, 7104,10717, 7101, 7125, 7112, 7114, 7131, - 7122, 7127, 7139, 7145, 7133, 7137, 7157, 7153, 7160, 7151, - 7147, 7158, 7163, 7152, 7178, 7180, 7179, 7181,10717, 7186, - 7172, 7182, 7185, 7188, 7190, 7200, 7195, 7213, 7202, 7231, - 7235,10717, 7217,10717, 7220, 7222, 7228, 7237, 7245, 7242, - - 7243, 7250, 7241, 7247, 7259, 7263, 7255, 7251, 7277, 7257, - 7270, 7272, 7275, 7290,10717, 7289, 7292, 7280, 7300, 7296, - 7309, 7310, 7306,10717, 7319, 7314, 7320, 7317, 7325, 7326, - 7312, 7330, 7327, 7342, 7328, 7344, 7348, 7350, 7346, 7353, - 7358, 7347, 7363, 7351, 7369,10717, 7374, 7366, 7375, 7368, - 7380, 7376, 7377, 7396, 7404, 7382, 7392, 7385, 7395,10717, - 7401, 7410, 7413, 7240,10717, 7414, 7403, 7412, 7421, 7438, - 7417, 7427, 7428, 7437, 7456,10717, 7449, 7431, 7443, 7439, - 7441, 7454, 7460, 7462, 7466, 7465, 7480, 7492,10717, 7490, - 7479, 7498, 7499, 7500, 7486, 7501, 7502, 7507, 7515, 7509, - - 10717, 7519, 7528, 7539, 7525, 7526, 7550, 7527, 7534, 7561, - 7552, 7553, 7538, 7546, 7565, 7554, 7555, 7560, 7580, 7584, - 7556, 7577, 7583, 7590,10717, 7578,10717, 7579, 7591, 7601, - 7608, 7613, 7603, 7618, 7604, 7628,10717, 7616, 7617, 7615, - 7636, 7625,10717, 7626, 7631, 7639, 7644,10717, 7659, 7652, - 7649, 7655, 7637, 7671,10717, 7668, 7670, 7675, 7690, 7692, - 7679, 7691, 7687, 7702, 7681, 7695, 7685, 7710, 7697, 7699, - 7700,10717, 7712, 7718, 7723, 7720, 7728, 7726, 7732, 7722, - 7730, 7744, 7738,10717, 7749, 7736, 7746, 7747, 7750, 7768, - 7755, 7753, 7784, 7780, 7769, 7787, 7771, 7773, 7782, 7785, - - 7783, 7803,10717, 7793, 7802, 7816, 7811, 7813, 7814, 7823, - 10717, 7815,10717, 7812, 7819, 7834, 7841, 7836,10717, 7851, - 7832, 7852, 7830, 7857,10717,10717, 7861, 7839, 7860, 7867, - 7864,10717,10717, 7869,10717, 7859,10717, 7862, 7874,10717, - 10717, 7870, 7879, 7880, 7887,10717, 7888, 7904, 7895,10717, - 7910,10717, 7885, 7891, 7912, 7900, 7897, 7918,10717, 7902, - 7925, 7914, 7922, 7930,10717, 7917, 7938, 7936, 7956, 7940, - 7939,10717, 7959, 7961, 7943, 7952, 7950,10717, 7974, 7973, - 7977, 7960, 7967, 7979, 7985, 7991, 7970, 7994, 7995, 8005, - 7996, 8004, 8009, 8013, 8000, 8025, 8026, 8028, 8017, 8031, - - 8012, 8040, 8037, 8046, 8048, 8042, 8039, 8050, 8041, 8057, - 8055, 8063, 8060, 8070, 8080, 8072, 8085, 8081, 8084, 8082, - 8075, 8087, 8076, 8097, 8100, 8104, 8101, 8089, 8105, 8116, - 8106, 8112, 8114, 8132, 8123, 8137, 8139, 8131, 8140,10717, - 8127, 8147, 8153, 8157, 8154, 8165, 8166, 8151, 8177, 8178, - 10717, 8182,10717, 8184, 8172, 8175, 8181, 8174,10717, 8187, - 8197, 8196, 8199, 8211, 8201, 8223, 8202, 8212, 8213, 8232, - 10717, 8237, 8235, 8229, 8239, 8227, 8244,10717, 8242, 8253, - 8247, 8249, 8254, 8248, 8258, 8259, 8266, 8263, 8264, 8285, - 8280, 8295, 8296, 8278, 8290, 8291,10717, 8301, 8302, 8314, - - 8303, 8309, 8304, 8307, 8306, 8310, 8313, 8312, 8318, 8323, - 8333, 8340, 8329, 8347, 8353, 8357, 8356, 8361,10717, 8345, - 10717, 8354, 8350, 8374, 8346, 8370, 8367, 8384, 8372, 8376, - 10717,10717, 8378, 8382, 8401, 8406, 8393, 8394, 8407, 8399, - 8402, 8411,10717, 8403, 8409, 8426, 8419, 8440, 8428,10717, - 8433, 8427, 8430, 8435, 8436, 8452,10717, 8446, 8455, 8457, - 8465, 8469, 8453, 8471, 8473, 8468, 8470, 8475, 8474, 8481, - 10717, 8482,10717,10717,10717, 8488, 8497, 8485, 8490, 8498, - 8505, 8509, 8501, 8514, 8517, 8519, 8500, 8516,10717, 8529, - 10717,10717, 8530,10717, 8534, 8528, 8543, 8532, 8533, 8545, - - 8555,10717, 8549,10717, 8546, 8560, 8553, 8571, 8574, 8572, - 8566, 8583, 8579, 8584, 8570, 8576, 8601, 8595, 8604, 8587, - 8603, 8607, 8609,10717,10717, 8606, 8617, 8615, 8625, 8621, - 8632, 8624, 8628, 8635, 8636, 8631, 8634, 8642, 8633, 8629, - 8648, 8652, 8658, 8647,10717, 8664, 8667, 8675,10717, 8661, - 10717, 8677, 8681, 8684, 8665, 8674, 8694, 8697, 8692, 8698, - 8691, 8685,10717,10717, 8705, 8701, 8709,10717,10717, 8708, - 8711, 8717, 8720, 8726, 8722, 8721,10717, 8732, 8734, 8744, - 8736, 8746, 8742, 8752, 8756,10717, 8747,10717, 8760, 8761, - 8776, 8766, 8782, 8786, 8771, 8767, 8800, 8796, 8789, 8774, - - 8801,10717, 8795, 8792,10717, 8813, 8807, 8811, 8802, 8816, - 8814, 8821,10717, 8824, 8817, 8839, 8822, 8846, 8850,10717, - 8853, 8851, 8849, 8847,10717, 8858,10717, 8840, 8859, 8857, - 8870, 8863,10717, 8841, 8872, 8873, 8878,10717, 8871, 8889, - 8894, 8898, 8882, 8890,10717, 8904, 8896,10717, 8888, 8907, - 8909, 8911, 8897, 8913, 8905, 8915, 8929, 8931, 8927, 8940, - 10717,10717, 8934, 8941, 73, 8952, 8926, 8928, 8930, 8945, - 8964, 8937, 8959, 8965,10717,10717, 8961,10717, 8972, 8971, - 10717, 8956, 8979, 8968, 8967, 8992, 8986, 8983, 8973, 9002, - 8991, 9012, 9006, 8998, 9008,10717, 9026, 9027, 9009, 9034, - - 9036, 9039, 9044, 9047, 9050, 9022, 9041, 9032, 9030, 9049, - 9055, 9057, 9061, 9065, 9072, 9066, 9067, 9071,10717, 9090, - 9095, 9097, 9088, 9101, 9096, 9099, 9092,10717, 9105, 9109, - 9106, 9107,10717, 9111, 9126, 9131, 9120, 9132, 9133,10717, - 9127, 9121, 9125, 9146, 9147, 9130, 9144, 9136, 9159, 9166, - 10717, 9157, 9171, 9160,10717, 9173,10717,10717,10717, 9176, - 9165, 9175,10717, 9185, 9182, 9174, 9177,10717, 9190, 9194, - 9201, 9216, 9193,10717,10717,10717, 9200, 9208, 9209,10717, - 9204, 9219,10717, 9217,10717, 9212,10717, 9236, 9237, 9246, - 9221,10717, 9244, 9240, 9245, 9254,10717, 9234, 9238, 9250, - - 9257, 9263, 9243, 9270,10717, 9284, 9273, 9282, 9288, 9274, - 9279, 9277, 9289, 9281, 9300, 9295, 9296,10717, 9303, 9308, - 9312, 9323, 9309, 9314, 9316,10717, 9318,10717, 9332,10717, - 9333, 9335, 9336, 9350, 9343, 9326, 9345, 9353, 9362, 9351, - 9363, 9365, 9359, 9369, 9358, 9374, 9382, 9378,10717,10717, - 9404, 9386,10717, 9396, 9403, 9406,10717, 9391,10717, 9407, - 10717, 9392, 9399,10717, 9411, 9401, 9420,10717,10717, 9421, - 9426, 9413, 9437, 9418, 9436, 9431,10717, 9453, 9442, 9432, - 9439, 9455,10717, 9465,10717, 9447, 9466, 9470,10717,10717, - 9449, 9459, 9462, 9472, 9464, 9468, 9490, 9476, 9491, 9481, - - 9510, 9477, 9495, 9493, 9511, 9504, 9518, 9522, 9515,10717, - 10717,10717, 9512, 9506, 9534, 9530, 9529, 9540, 9523,10717, - 9539, 9547, 9549, 9536, 9563, 9552, 9560,10717, 9550, 9546, - 9553, 9559, 9565, 9556, 9568, 9576,10717, 9588, 9593, 9594, - 9595, 9587, 9599, 9598, 9606, 9607, 9608, 9609, 9597, 9592, - 9613, 9611,10717,10717, 9623, 9614,10717, 9629, 9632,10717, - 10717, 9620,10717, 9624, 9626, 9633, 9627, 9641,10717, 9655, - 9635, 9644, 9650,10717, 9638, 9665, 9667, 9670, 9668,10717, - 9660, 9685, 9666, 9662, 9679, 9691,10717,10717, 9677, 9683, - 10717, 9700, 9697, 9689, 9712, 9705, 9701, 9714, 9710,10717, - - 9716, 9721, 9711, 9713, 9729, 9723, 9739,10717, 9738, 9730, - 9732, 9743,10717, 9737, 9751, 9757, 9750, 9764,10717, 9776, - 9760, 9724, 9778,10717, 9765, 9786, 9782,10717,10717,10717, - 9788, 9793, 9796,10717,10717,10717, 9784,10717, 9797, 9801, - 9798, 9804,10717, 9803,10717,10717, 9814, 9836, 9838, 9819, - 9840, 9825,10717, 9816, 9823, 9842, 9831, 9833,10717,10717, - 9851, 9852, 9834, 9835, 9859, 9857, 9848, 9850,10717,10717, - 9846, 9861, 9879, 9863, 9874,10717, 9867, 9882, 9892, 9891, - 9895, 9902, 9903, 9890, 9899, 9912, 9913, 9727, 9908, 9910, - 9907, 9915, 9931, 9919, 9941, 9916, 9939, 9944, 9949, 9935, - - 9948,10717,10717, 9954, 9942,10717, 9957, 9952,10717, 9946, - 10717, 9959, 9967, 9970, 9974,10717, 9978, 9982, 9985, 9987, - 9963,10717, 9983, 9993,10717, 9995, 9990, 9984, 9980,10717, - 9988, 9998, 9994,10002, 9991,10011,10016,10007,10004,10717, - 10017,10036,10717,10717,10019,10038,10021,10044,10031,10717, - 10039,10055,10040,10048,10033,10043,10046,10717,10050,10069, - 10717,10717,10080,10070,10717,10086,10717,10064,10072,10717, - 10717,10717,10717,10717,10717,10717,10717,10088,10091,10717, - 10717,10082,10098,10100,10101,10717,10102,10717,10081,10097, - 10099,10096,10717,10118,10717,10111,10124,10131,10137,10125, - - 10141,10133,10128,10126,10138,10123,10155,10163,10164,10151, - 10158,10165,10175,10167,10110,10168,10182,10717,10717,10717, - 10717,10184,10169,10157,10191,10193,10204,10201,10208,10202, - 10190,10209,10214,10217,10199,10215,10228,10220,10226,10235, - 10233,10223,10245,10252,10254,10717,10256,10244,10239,10263, - 10717,10249,10717,10250,10717,10717,10269,10272,10266,10261, - 10283,10287,10270,10262,10279,10289,10292,10717,10303,10717, - 10717,10717,10717,10288,10285,10717,10290,10314,10717,10293, - 10317,10307,10310,10311,10308,10328,10334,10329,10717,10717, - 10332,10330,10343,10342,10341,10363,10364,10366,10367,10369, - - 10357,10368,10717,10377,10373,10380,10717,10379,10389,10375, - 10392,10393,10386,10395,10402,10717,10396,10717,10417,10409, - 10420,10407,10413,10424,10427,10438,10433,10717,10404,10448, - 10431,10455,10460,10457,10459,10444,10467,10464,10470,10468, - 10471,10473,10482,10476,10483,10717,10479,10485,10717,10487, - 10506,10494,10496,10516,10717,10518,10503,10505,10519,10525, - 10527,10717,10526,10535,10529,10717,10532,10717,10717,10543, - 10531,10538,10539,10541,10717,10717,10717,10597,10604,10611, - 10618,10625,10632,10639, 100,10646,10653,10660,10667,10674, - 10681,10688,10695,10702,10709 - - } ; - -static const flex_int16_t yy_def[3796] = - { 0, - 3777, 1, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, - 3782, 3782, 3783, 3783, 3784, 3784, 3777, 3785, 3777, 3777, - 3777, 3777, 3786, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3787, 3777, 3777, 3777, - 3787, 3788, 3777, 3777, 3777, 3788, 3789, 3777, 3777, 3777, - 3777, 3789, 3790, 3777, 3777, 3777, 3790, 3791, 3777, 3792, - 3777, 3791, 3791, 3793, 3777, 3777, 3777, 3777, 3793, 3794, - 3777, 3777, 3777, 3794, 3785, 3785, 3777, 3795, 3786, 3795, - 3786, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3787, 3787, 3788, 3788, 3789, 3789, 3777, 3790, 3790, 3791, - 3791, 3792, 3792, 3791, 3793, 3793, 3777, 3794, 3794, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3791, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3777, 3777, 3785, 3785, 3777, 3777, - - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3791, 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, - - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3777, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3791, 3785, 3777, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3777, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3791, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3777, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3791, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3777, 3777, 3785, 3785, 3785, 3785, - 3785, 3777, 3777, 3785, 3777, 3785, 3777, 3785, 3785, 3777, - 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3777, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3777, 3777, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3777, 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3791, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3777, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3777, 3785, 3785, 3785, 3777, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3777, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3777, 3785, 3785, 3791, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3777, 3777, 3785, 3777, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3777, 3785, 3785, 3785, 3777, 3785, 3777, 3777, 3777, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3777, 3777, 3777, 3785, 3785, 3785, 3777, - 3785, 3785, 3777, 3785, 3777, 3785, 3777, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, - 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3785, 3777, 3785, - 3777, 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3785, 3777, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3777, 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3777, 3785, 3785, 3777, 3785, 3785, 3777, - 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, 3785, 3785, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3777, 3777, - 3785, 3785, 3785, 3777, 3777, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3777, 3785, 3777, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, 3777, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3777, 3777, 3785, 3785, 3777, 3785, 3785, 3777, 3785, - 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3777, 3777, 3785, 3785, 3785, 3785, 3785, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3777, 3777, 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3785, 3785, 3777, - 3777, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3777, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, 3777, - 3777, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, - 3777, 3785, 3777, 3785, 3777, 3777, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, - 3777, 3777, 3777, 3785, 3785, 3777, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3777, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - - 3785, 3785, 3777, 3785, 3785, 3785, 3777, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, 3785, - 3785, 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3777, 3785, - 3785, 3785, 3785, 3785, 3777, 3785, 3785, 3785, 3785, 3785, - 3785, 3777, 3785, 3785, 3785, 3777, 3785, 3777, 3777, 3785, - 3785, 3785, 3785, 3785, 3777, 3777, 0, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777 - - } ; - -static const flex_int16_t yy_nxt[10784] = - { 0, - 18, 19, 20, 21, 22, 23, 22, 18, 18, 18, - 18, 18, 22, 24, 25, 26, 27, 28, 29, 18, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 18, 18, 18, 45, 46, - 24, 25, 26, 27, 28, 29, 18, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 18, 18, 18, 45, 48, 49, 50, 48, - 49, 50, 53, 54, 53, 54, 55, 120, 55, 58, - 59, 60, 61, 121, 22, 58, 59, 60, 61, 86, - 22, 64, 65, 66, 64, 65, 66, 87, 161, 161, - - 85, 88, 351, 51, 120, 86, 51, 168, 168, 56, - 121, 56, 171, 75, 76, 77, 78, 62, 22, 75, - 76, 77, 78, 62, 22, 81, 82, 83, 67, 98, - 86, 67, 19, 20, 21, 69, 70, 71, 19, 20, - 21, 69, 70, 71, 81, 82, 83, 122, 109, 178, - 178, 79, 72, 160, 171, 86, 98, 79, 72, 86, - 138, 90, 84, 90, 90, 86, 90, 179, 110, 797, - 73, 86, 90, 86, 122, 109, 73, 426, 87, 72, - 160, 84, 88, 161, 161, 72, 113, 138, 111, 177, - 163, 176, 131, 163, 114, 110, 99, 86, 86, 91, - - 92, 93, 112, 100, 94, 115, 86, 101, 189, 95, - 102, 96, 86, 113, 86, 111, 180, 86, 97, 131, - 174, 114, 86, 99, 86, 168, 168, 92, 93, 112, - 100, 94, 115, 171, 101, 189, 95, 102, 96, 165, - 86, 165, 165, 180, 165, 97, 103, 174, 116, 171, - 104, 117, 182, 105, 183, 106, 107, 301, 118, 85, - 119, 85, 85, 339, 85, 343, 108, 169, 86, 86, - 85, 86, 86, 103, 167, 116, 123, 104, 117, 182, - 105, 183, 106, 107, 124, 118, 181, 119, 127, 86, - 125, 185, 128, 108, 126, 86, 157, 86, 86, 149, - - 158, 150, 86, 123, 159, 186, 129, 166, 130, 86, - 151, 124, 164, 181, 86, 127, 152, 125, 185, 128, - 162, 126, 86, 157, 153, 86, 149, 158, 150, 86, - 490, 159, 186, 129, 154, 130, 132, 151, 155, 156, - 133, 184, 163, 152, 134, 163, 86, 86, 179, 86, - 135, 153, 90, 136, 90, 90, 190, 90, 246, 86, - 137, 154, 86, 132, 198, 155, 156, 133, 184, 86, - 170, 134, 170, 170, 86, 170, 175, 135, 175, 175, - 136, 175, 177, 190, 86, 246, 187, 137, 139, 199, - 173, 198, 140, 85, 202, 85, 85, 86, 85, 188, - - 231, 266, 141, 142, 85, 143, 90, 86, 90, 90, - 86, 90, 86, 187, 86, 139, 199, 90, 176, 140, - 86, 202, 191, 192, 200, 345, 188, 231, 266, 141, - 142, 193, 143, 144, 205, 86, 145, 194, 214, 195, - 171, 86, 201, 146, 91, 196, 197, 147, 148, 191, - 192, 86, 86, 209, 86, 86, 86, 86, 193, 203, - 144, 205, 86, 145, 194, 214, 195, 211, 204, 201, - 146, 213, 196, 197, 147, 148, 206, 207, 210, 230, - 209, 86, 212, 219, 208, 1245, 203, 86, 169, 86, - 86, 167, 86, 86, 211, 204, 215, 222, 213, 216, - - 221, 229, 86, 206, 207, 210, 230, 220, 86, 212, - 166, 208, 217, 218, 86, 86, 86, 223, 224, 86, - 86, 234, 225, 215, 222, 227, 216, 221, 229, 232, - 228, 238, 235, 86, 220, 164, 233, 236, 226, 217, - 218, 86, 86, 86, 223, 224, 237, 240, 234, 225, - 86, 86, 227, 86, 86, 162, 232, 228, 238, 235, - 239, 1404, 241, 233, 236, 226, 86, 251, 242, 86, - 86, 86, 243, 237, 240, 245, 247, 248, 244, 86, - 252, 86, 86, 86, 257, 253, 249, 239, 258, 241, - 86, 86, 250, 86, 251, 242, 259, 269, 86, 243, - - 86, 260, 245, 247, 248, 244, 254, 252, 86, 261, - 267, 257, 253, 249, 264, 3777, 86, 255, 86, 250, - 86, 256, 270, 259, 269, 265, 262, 273, 260, 263, - 86, 271, 268, 254, 86, 86, 261, 267, 86, 274, - 275, 264, 86, 272, 255, 3777, 277, 86, 256, 270, - 278, 276, 265, 262, 273, 86, 263, 3777, 271, 268, - 86, 86, 3777, 86, 3777, 279, 274, 275, 86, 165, - 272, 165, 165, 277, 165, 178, 178, 278, 276, 170, - 280, 170, 170, 90, 170, 90, 90, 281, 90, 171, - 283, 175, 279, 175, 175, 3777, 175, 284, 288, 86, - - 285, 282, 86, 286, 86, 290, 291, 280, 293, 86, - 287, 3777, 289, 86, 86, 86, 292, 283, 86, 86, - 294, 173, 86, 295, 284, 288, 299, 285, 282, 300, - 286, 86, 290, 291, 296, 293, 86, 287, 86, 289, - 297, 86, 298, 292, 86, 310, 311, 294, 86, 323, - 295, 314, 312, 299, 302, 86, 300, 313, 303, 86, - 86, 86, 317, 318, 315, 316, 86, 297, 319, 298, - 86, 86, 310, 311, 321, 304, 323, 86, 314, 3777, - 324, 3777, 86, 322, 86, 303, 86, 86, 3777, 317, - 318, 315, 316, 86, 325, 328, 320, 86, 3777, 349, - - 86, 321, 304, 305, 86, 86, 86, 324, 306, 326, - 322, 329, 327, 307, 3777, 330, 3777, 338, 337, 308, - 309, 325, 328, 320, 86, 86, 86, 336, 86, 340, - 305, 86, 341, 86, 344, 306, 326, 86, 329, 327, - 307, 86, 330, 342, 338, 337, 308, 309, 331, 86, - 350, 332, 346, 333, 336, 86, 340, 3777, 352, 353, - 3777, 344, 348, 354, 86, 334, 347, 335, 86, 357, - 342, 355, 86, 358, 86, 331, 356, 350, 332, 3777, - 333, 359, 86, 3777, 86, 361, 353, 86, 364, 348, - 86, 86, 334, 347, 335, 86, 86, 360, 355, 365, - - 358, 86, 86, 356, 86, 362, 86, 366, 359, 367, - 368, 369, 361, 371, 363, 364, 370, 372, 86, 86, - 86, 86, 373, 86, 360, 374, 365, 86, 86, 378, - 375, 86, 362, 376, 366, 382, 367, 368, 369, 86, - 371, 363, 381, 370, 383, 377, 384, 86, 3777, 86, - 86, 86, 374, 379, 380, 386, 86, 375, 86, 385, - 376, 86, 86, 86, 388, 387, 389, 86, 86, 381, - 390, 383, 377, 384, 391, 392, 393, 395, 86, 3777, - 379, 380, 386, 394, 86, 86, 385, 398, 396, 86, - 86, 399, 387, 3777, 3777, 401, 86, 390, 86, 86, - - 403, 402, 392, 393, 86, 404, 86, 405, 400, 86, - 394, 397, 3777, 86, 406, 171, 86, 407, 399, 86, - 86, 86, 401, 86, 409, 408, 86, 403, 402, 86, - 410, 411, 404, 412, 405, 400, 414, 413, 397, 86, - 416, 406, 415, 418, 407, 419, 86, 417, 421, 422, - 86, 409, 408, 86, 86, 86, 86, 420, 86, 86, - 412, 86, 86, 86, 413, 423, 424, 416, 86, 415, - 418, 425, 419, 427, 417, 421, 86, 428, 3777, 429, - 437, 86, 86, 430, 420, 431, 434, 3777, 86, 86, - 433, 86, 423, 424, 86, 438, 3777, 86, 425, 432, - - 427, 435, 436, 86, 428, 86, 429, 437, 439, 86, - 430, 86, 431, 434, 86, 440, 441, 433, 442, 86, - 86, 86, 443, 447, 448, 445, 432, 86, 435, 436, - 450, 446, 452, 451, 3777, 439, 454, 86, 86, 444, - 453, 86, 86, 441, 455, 86, 457, 86, 449, 443, - 86, 86, 445, 86, 86, 86, 86, 450, 446, 452, - 451, 456, 86, 454, 458, 459, 444, 453, 86, 86, - 86, 455, 86, 457, 86, 449, 460, 461, 465, 464, - 467, 462, 3777, 3777, 3777, 466, 86, 475, 456, 483, - 492, 458, 459, 474, 86, 86, 86, 476, 463, 3777, - - 3777, 484, 86, 460, 461, 86, 464, 467, 462, 86, - 86, 86, 466, 86, 475, 86, 483, 86, 485, 86, - 474, 486, 487, 491, 476, 463, 468, 488, 484, 469, - 495, 496, 489, 86, 470, 471, 472, 473, 3777, 512, - 3777, 3777, 86, 86, 86, 485, 86, 86, 486, 487, - 491, 3777, 519, 468, 3777, 3777, 469, 495, 496, 86, - 499, 470, 471, 472, 473, 477, 493, 478, 500, 494, - 501, 86, 497, 498, 3777, 503, 86, 504, 86, 479, - 480, 481, 86, 482, 86, 3777, 86, 499, 526, 86, - 502, 510, 477, 493, 478, 500, 494, 86, 86, 497, - - 498, 86, 503, 86, 504, 507, 479, 480, 481, 505, - 482, 86, 86, 506, 508, 509, 511, 502, 510, 513, - 86, 514, 518, 86, 517, 86, 533, 86, 86, 86, - 515, 86, 507, 520, 3777, 532, 505, 516, 531, 534, - 506, 508, 509, 511, 86, 86, 513, 521, 514, 518, - 525, 517, 523, 522, 524, 86, 86, 515, 86, 576, - 520, 86, 532, 86, 516, 531, 86, 3777, 535, 86, - 527, 548, 591, 551, 521, 549, 86, 525, 86, 523, - 522, 524, 579, 528, 552, 86, 529, 3777, 530, 86, - 86, 86, 553, 550, 86, 535, 86, 527, 548, 86, - - 551, 3777, 549, 3777, 86, 86, 3777, 554, 556, 579, - 528, 552, 566, 529, 565, 530, 536, 567, 537, 553, - 550, 86, 568, 555, 538, 569, 86, 645, 539, 572, - 86, 86, 570, 540, 554, 556, 541, 86, 571, 566, - 575, 565, 86, 536, 171, 537, 86, 3777, 86, 86, - 555, 538, 569, 574, 86, 539, 572, 3777, 573, 570, - 540, 578, 86, 541, 542, 571, 543, 575, 577, 3777, - 86, 86, 581, 671, 580, 588, 583, 86, 86, 544, - 574, 582, 545, 1008, 546, 573, 547, 86, 578, 585, - 86, 542, 586, 543, 584, 577, 86, 86, 86, 86, - - 671, 580, 588, 583, 86, 587, 544, 589, 582, 545, - 590, 546, 86, 547, 557, 558, 585, 86, 592, 586, - 594, 584, 86, 593, 559, 560, 561, 562, 563, 86, - 86, 564, 587, 595, 589, 86, 596, 590, 597, 86, - 86, 557, 558, 3777, 86, 592, 86, 594, 598, 599, - 593, 559, 560, 561, 562, 563, 600, 601, 564, 86, - 595, 604, 602, 603, 608, 597, 605, 606, 86, 86, - 86, 86, 86, 607, 612, 598, 599, 86, 609, 610, - 86, 3777, 615, 3777, 613, 86, 86, 616, 604, 602, - 603, 608, 617, 605, 606, 86, 611, 86, 86, 614, - - 607, 612, 618, 86, 86, 609, 610, 86, 86, 615, - 633, 613, 619, 86, 616, 620, 631, 632, 634, 617, - 644, 86, 635, 611, 621, 622, 614, 636, 86, 618, - 639, 640, 86, 638, 86, 86, 623, 633, 624, 619, - 86, 86, 620, 86, 632, 634, 641, 644, 86, 635, - 637, 621, 622, 86, 86, 86, 86, 639, 640, 86, - 638, 3777, 642, 623, 643, 624, 625, 647, 86, 86, - 646, 649, 648, 641, 626, 627, 3777, 637, 628, 629, - 3777, 86, 630, 651, 650, 3777, 3777, 3777, 86, 642, - 86, 643, 86, 625, 647, 86, 653, 646, 86, 648, - - 654, 626, 627, 86, 655, 628, 629, 86, 652, 630, - 651, 650, 656, 657, 86, 663, 659, 658, 86, 660, - 662, 661, 86, 653, 86, 86, 86, 654, 86, 664, - 86, 655, 665, 3777, 86, 652, 667, 86, 666, 656, - 657, 670, 663, 659, 658, 86, 660, 662, 661, 668, - 672, 86, 669, 86, 673, 86, 664, 3777, 86, 665, - 674, 3777, 86, 667, 675, 666, 86, 86, 670, 676, - 677, 86, 678, 679, 681, 86, 668, 680, 86, 669, - 86, 673, 86, 86, 86, 686, 688, 674, 86, 86, - 690, 675, 689, 684, 687, 86, 676, 677, 692, 678, - - 679, 681, 86, 682, 680, 683, 685, 86, 699, 691, - 86, 86, 86, 86, 695, 3777, 696, 86, 86, 689, - 684, 687, 86, 693, 701, 692, 694, 697, 698, 86, - 682, 86, 683, 685, 702, 3777, 691, 700, 86, 86, - 86, 695, 86, 696, 86, 704, 86, 705, 86, 710, - 693, 701, 708, 694, 697, 698, 706, 703, 86, 707, - 709, 86, 713, 712, 700, 86, 86, 715, 711, 86, - 86, 86, 704, 86, 705, 86, 710, 3777, 727, 708, - 86, 86, 764, 706, 703, 86, 707, 709, 714, 713, - 712, 724, 726, 725, 715, 711, 86, 3777, 86, 86, - - 728, 86, 3777, 729, 86, 727, 730, 3777, 86, 731, - 3777, 748, 734, 86, 86, 714, 716, 86, 724, 726, - 725, 717, 732, 718, 86, 86, 733, 728, 3777, 719, - 729, 720, 86, 730, 721, 722, 731, 735, 748, 734, - 743, 723, 86, 716, 86, 744, 3777, 739, 717, 732, - 718, 86, 737, 733, 742, 738, 719, 736, 720, 86, - 740, 721, 722, 86, 735, 86, 86, 743, 723, 86, - 741, 745, 744, 746, 739, 86, 747, 3777, 749, 737, - 86, 742, 738, 750, 736, 753, 751, 752, 754, 755, - 757, 3777, 86, 769, 86, 86, 86, 741, 745, 86, - - 746, 86, 86, 747, 86, 749, 756, 759, 86, 760, - 750, 86, 753, 751, 752, 754, 755, 757, 758, 86, - 761, 762, 765, 763, 767, 86, 86, 766, 86, 768, - 86, 770, 86, 756, 759, 774, 760, 86, 86, 86, - 772, 773, 86, 86, 86, 758, 171, 761, 762, 765, - 763, 767, 771, 776, 766, 86, 768, 777, 770, 778, - 86, 86, 774, 86, 780, 783, 775, 772, 773, 86, - 779, 781, 86, 782, 784, 791, 792, 786, 785, 771, - 776, 793, 787, 798, 86, 86, 86, 86, 86, 86, - 86, 86, 783, 775, 795, 796, 86, 779, 801, 86, - - 782, 784, 791, 86, 786, 785, 86, 788, 86, 787, - 794, 799, 800, 802, 789, 86, 806, 790, 803, 804, - 805, 86, 86, 810, 86, 86, 86, 807, 86, 811, - 86, 86, 809, 808, 788, 812, 816, 794, 86, 86, - 86, 789, 86, 806, 790, 86, 804, 805, 813, 815, - 810, 86, 86, 86, 807, 86, 811, 86, 814, 809, - 808, 818, 812, 817, 819, 820, 86, 821, 86, 822, - 86, 823, 86, 86, 826, 813, 815, 3777, 825, 829, - 86, 830, 86, 86, 86, 814, 827, 86, 818, 3777, - 817, 819, 820, 824, 821, 86, 822, 86, 823, 86, - - 86, 826, 828, 86, 831, 825, 837, 3777, 830, 86, - 832, 86, 836, 827, 838, 833, 839, 86, 834, 835, - 824, 86, 840, 86, 843, 841, 844, 86, 3777, 828, - 846, 831, 86, 837, 86, 842, 86, 832, 845, 836, - 850, 838, 833, 839, 86, 834, 835, 86, 86, 840, - 847, 843, 841, 849, 86, 852, 86, 846, 86, 851, - 853, 857, 842, 854, 86, 845, 86, 850, 86, 86, - 855, 856, 848, 86, 858, 86, 859, 847, 863, 867, - 849, 86, 852, 86, 86, 861, 851, 853, 857, 862, - 854, 86, 860, 86, 86, 86, 865, 855, 856, 848, - - 86, 86, 864, 859, 868, 863, 866, 86, 869, 870, - 871, 86, 861, 86, 86, 872, 862, 873, 874, 860, - 880, 86, 3777, 865, 876, 86, 86, 875, 878, 864, - 877, 868, 86, 866, 881, 869, 86, 86, 86, 879, - 86, 86, 872, 86, 873, 874, 882, 86, 883, 885, - 86, 876, 86, 886, 875, 878, 86, 877, 884, 889, - 86, 881, 887, 890, 86, 894, 879, 888, 904, 891, - 3777, 86, 86, 86, 895, 883, 885, 86, 86, 899, - 886, 896, 86, 892, 893, 884, 889, 897, 898, 905, - 890, 86, 900, 901, 86, 86, 891, 86, 908, 86, - - 86, 895, 902, 909, 86, 86, 899, 910, 896, 86, - 892, 893, 86, 86, 897, 898, 905, 903, 906, 900, - 901, 911, 912, 86, 913, 914, 86, 916, 907, 902, - 86, 915, 86, 86, 910, 3777, 86, 86, 921, 920, - 86, 922, 923, 3777, 903, 906, 86, 86, 911, 912, - 86, 913, 914, 917, 916, 907, 918, 3777, 915, 919, - 86, 924, 86, 925, 86, 86, 920, 86, 922, 923, - 86, 927, 926, 86, 931, 86, 928, 930, 934, 86, - 917, 86, 933, 918, 932, 929, 919, 938, 924, 86, - 925, 86, 3777, 86, 935, 86, 3777, 3777, 927, 926, - - 86, 936, 86, 928, 930, 934, 86, 86, 937, 933, - 86, 932, 929, 939, 938, 940, 86, 944, 941, 946, - 947, 935, 86, 942, 943, 86, 86, 86, 936, 945, - 3777, 948, 86, 86, 3777, 937, 949, 86, 952, 950, - 939, 86, 940, 3777, 944, 941, 946, 947, 954, 953, - 942, 943, 86, 951, 86, 957, 945, 86, 948, 86, - 955, 86, 86, 949, 956, 952, 950, 959, 958, 86, - 86, 86, 86, 960, 961, 954, 953, 86, 3777, 966, - 951, 962, 957, 963, 965, 967, 970, 955, 86, 86, - 964, 956, 969, 86, 959, 958, 968, 86, 86, 86, - - 960, 961, 971, 86, 86, 86, 966, 86, 962, 972, - 963, 965, 967, 974, 86, 973, 975, 964, 86, 969, - 976, 977, 978, 968, 171, 979, 86, 980, 983, 971, - 987, 86, 86, 86, 86, 86, 972, 984, 86, 985, - 974, 3777, 973, 975, 989, 86, 990, 976, 977, 978, - 981, 86, 979, 986, 86, 86, 994, 86, 982, 86, - 988, 86, 86, 991, 984, 992, 985, 86, 86, 86, - 993, 989, 995, 990, 996, 997, 86, 981, 86, 86, - 986, 998, 999, 86, 86, 982, 1023, 988, 86, 86, - 991, 86, 992, 3777, 86, 1007, 1009, 993, 1010, 995, - - 3777, 996, 997, 3777, 1015, 1011, 86, 86, 998, 999, - 1000, 1014, 1013, 1001, 1012, 86, 86, 1002, 86, 86, - 1003, 1056, 1007, 1009, 1017, 1010, 86, 1004, 1005, 86, - 1006, 1015, 1011, 86, 1018, 86, 1016, 1000, 1014, 1013, - 1001, 1012, 1019, 1020, 1002, 1033, 1022, 1003, 86, 1021, - 86, 1017, 86, 86, 1004, 1005, 3777, 1006, 86, 86, - 86, 1018, 86, 1016, 1032, 1035, 1036, 86, 1071, 1019, - 1020, 86, 1033, 1022, 86, 1034, 1021, 1024, 1025, 1037, - 1026, 86, 86, 1027, 3777, 1038, 3777, 1040, 1028, 86, - 1041, 1032, 1035, 1036, 1029, 1030, 1042, 1031, 86, 1043, - - 86, 1039, 1034, 86, 1024, 1025, 1037, 1026, 86, 86, - 1027, 86, 1038, 1045, 1040, 1028, 1048, 1041, 86, 1049, - 1050, 1029, 1030, 1042, 1031, 1044, 1043, 86, 1039, 1046, - 1052, 1051, 86, 1053, 1047, 1054, 86, 86, 3777, 1057, - 1045, 1055, 3777, 1048, 1061, 86, 1049, 1050, 3777, 1060, - 1058, 86, 1044, 86, 1063, 86, 86, 1052, 1051, 86, - 1053, 86, 1054, 86, 86, 86, 1057, 1059, 1055, 1064, - 1062, 1061, 86, 86, 1065, 86, 1060, 1058, 86, 1066, - 1068, 1063, 1067, 1069, 1073, 1070, 86, 1077, 1074, 86, - 86, 1072, 86, 1075, 1059, 86, 1064, 1062, 86, 1076, - - 1082, 1065, 1081, 1083, 1084, 1078, 1066, 1068, 86, 1067, - 1069, 86, 1070, 86, 86, 1079, 1085, 1080, 1072, 86, - 86, 86, 86, 86, 86, 1087, 1076, 1082, 86, 1086, - 1088, 1084, 1078, 1092, 86, 86, 1089, 86, 1091, 1090, - 1096, 1093, 1079, 1085, 1080, 86, 1097, 86, 86, 1094, - 1095, 86, 86, 1098, 86, 86, 1086, 86, 86, 86, - 1092, 1099, 1100, 1089, 86, 1091, 1090, 1096, 1093, 86, - 1101, 1102, 1105, 1097, 1103, 1106, 1094, 1095, 1104, 86, - 86, 86, 1107, 86, 1108, 86, 86, 1112, 1099, 1100, - 86, 1110, 1109, 86, 1111, 1114, 1113, 86, 86, 1105, - - 86, 1103, 1106, 86, 1118, 1104, 86, 1119, 3777, 1107, - 86, 1108, 1115, 86, 1112, 86, 86, 86, 1110, 1109, - 1116, 1111, 1114, 1113, 1120, 1117, 86, 1121, 1122, 1123, - 1128, 1118, 86, 86, 1119, 86, 86, 1125, 1124, 1115, - 1130, 1127, 1129, 1131, 3777, 1126, 86, 86, 86, 86, - 3777, 1120, 86, 1132, 1121, 1122, 1123, 86, 1135, 1137, - 1142, 86, 86, 86, 1125, 1124, 86, 1130, 1127, 1129, - 1131, 1133, 1126, 1139, 1134, 86, 1136, 86, 86, 1141, - 1132, 86, 1140, 86, 1138, 1135, 1137, 86, 86, 1143, - 1144, 86, 86, 1145, 1146, 1147, 86, 1148, 1133, 1150, - - 1139, 1134, 86, 1136, 86, 86, 1141, 86, 86, 1140, - 1149, 1138, 86, 1151, 1152, 1153, 1143, 1144, 86, 3777, - 1145, 1146, 1147, 86, 1148, 1154, 1150, 1155, 1157, 86, - 1163, 1156, 86, 1164, 1159, 86, 1158, 1149, 86, 86, - 1151, 86, 1153, 86, 1161, 86, 1162, 86, 1160, 1166, - 1169, 86, 1154, 86, 1155, 1157, 86, 1165, 1156, 1167, - 1168, 1159, 86, 1158, 1170, 86, 1171, 86, 1172, 3777, - 86, 1161, 86, 1162, 1176, 1160, 86, 1173, 1175, 1178, - 86, 86, 86, 1177, 1165, 1174, 1167, 1168, 1179, 86, - 1180, 1183, 86, 1171, 1181, 1172, 86, 1185, 1186, 1182, - - 86, 1176, 3777, 86, 1173, 1175, 1187, 86, 1184, 86, - 1177, 86, 1174, 86, 86, 86, 1188, 1180, 1193, 1194, - 86, 1181, 1191, 86, 86, 1186, 1182, 1192, 86, 1189, - 86, 1190, 1196, 1187, 1195, 1184, 1201, 86, 1198, 86, - 86, 1197, 86, 1188, 1199, 1193, 1194, 1200, 86, 1202, - 86, 1212, 3777, 1203, 171, 86, 1189, 1204, 1190, 1196, - 86, 1195, 86, 1201, 86, 1198, 86, 86, 1197, 1205, - 1242, 1199, 3777, 86, 1200, 86, 1202, 1214, 1212, 1215, - 1203, 1213, 1216, 3777, 1204, 1217, 3777, 86, 1223, 1219, - 1218, 86, 1221, 1224, 3777, 3777, 1205, 1206, 1220, 1207, - - 86, 86, 86, 1208, 1214, 1209, 1215, 86, 1213, 86, - 1210, 86, 1217, 86, 86, 1211, 1219, 1218, 1222, 1221, - 86, 86, 1225, 1226, 1206, 1220, 1207, 1229, 3777, 1227, - 1208, 86, 1209, 1230, 1234, 1233, 86, 1210, 1232, 86, - 86, 1228, 1211, 1231, 1235, 1222, 1237, 86, 1238, 1225, - 1226, 1240, 86, 86, 1229, 86, 1227, 86, 1236, 86, - 1230, 1234, 1233, 1243, 86, 1232, 86, 1239, 1228, 1241, - 1231, 86, 86, 1237, 1244, 1238, 1246, 1247, 1240, 1248, - 1258, 3777, 86, 1249, 3777, 1236, 1259, 86, 1257, 86, - 1260, 86, 86, 1261, 1239, 86, 1241, 3777, 1265, 86, - - 1262, 86, 86, 86, 1247, 86, 1248, 1258, 86, 86, - 1249, 1250, 1263, 1259, 1270, 1257, 1251, 1260, 1252, 86, - 1261, 1264, 86, 3777, 1253, 1265, 1273, 1262, 1266, 1254, - 1255, 86, 1267, 1269, 86, 86, 1256, 86, 1250, 1263, - 86, 86, 1268, 1251, 86, 1252, 86, 1272, 1264, 1271, - 86, 1253, 1275, 1273, 1274, 1266, 1254, 1255, 1276, 1267, - 1269, 86, 86, 1256, 1277, 86, 1278, 86, 1279, 1268, - 1280, 86, 1281, 1284, 1272, 86, 1271, 3777, 1282, 1275, - 1285, 1274, 1283, 1288, 1286, 1276, 86, 86, 1291, 86, - 1287, 86, 1290, 1278, 3777, 1279, 86, 1289, 86, 1281, - - 1284, 86, 86, 86, 86, 1282, 86, 1292, 1293, 1283, - 1288, 1286, 86, 1296, 1294, 86, 86, 1287, 1298, 1290, - 86, 1295, 1297, 3777, 1289, 86, 86, 1304, 86, 86, - 1301, 1303, 1299, 86, 1292, 1293, 86, 1300, 86, 1306, - 1296, 1294, 1302, 1305, 1309, 1298, 86, 3777, 1295, 1297, - 86, 86, 86, 1308, 1304, 86, 86, 1301, 1307, 1299, - 86, 1311, 1312, 86, 1300, 1310, 1306, 1313, 1314, 1302, - 1305, 86, 3777, 86, 86, 86, 86, 1315, 1316, 86, - 1308, 1317, 1320, 1318, 1321, 1307, 1319, 3777, 1311, 1312, - 86, 1322, 1310, 1326, 1313, 1314, 3777, 1324, 1327, 86, - - 86, 86, 1331, 86, 1315, 1316, 1325, 1323, 1317, 86, - 1318, 86, 86, 1319, 86, 1330, 86, 86, 1322, 86, - 1328, 1333, 1332, 1329, 1324, 86, 86, 86, 86, 1331, - 1334, 1335, 1337, 1325, 1323, 86, 1338, 1336, 1339, 1340, - 86, 86, 1330, 1341, 86, 86, 86, 1328, 1333, 1332, - 1329, 86, 1342, 1343, 1345, 86, 1344, 1334, 1335, 1337, - 3777, 1346, 1347, 1348, 1336, 1339, 86, 86, 86, 1350, - 1341, 86, 1351, 1352, 86, 1349, 1353, 1354, 86, 1342, - 1343, 1345, 86, 1344, 86, 86, 86, 86, 1346, 1347, - 1348, 86, 1356, 1358, 86, 86, 1350, 1355, 86, 1351, - - 1352, 1357, 1349, 1353, 1354, 1359, 1361, 86, 86, 1360, - 1362, 3777, 1363, 86, 1364, 86, 1367, 1368, 1365, 1356, - 1369, 1370, 1366, 86, 1355, 86, 86, 86, 1357, 86, - 1371, 86, 86, 1361, 86, 1374, 1360, 1362, 86, 1363, - 86, 1364, 1372, 1367, 1368, 1365, 1373, 1376, 1375, 1366, - 1377, 1378, 86, 86, 1379, 1380, 1382, 3777, 1381, 3777, - 86, 86, 86, 3777, 86, 1395, 1383, 86, 86, 1372, - 86, 1384, 86, 1373, 1385, 1375, 1388, 1377, 1378, 86, - 86, 1379, 1386, 86, 86, 1381, 1387, 86, 1389, 86, - 1390, 86, 1391, 1383, 86, 1392, 86, 86, 1384, 1394, - - 86, 1385, 1396, 1388, 86, 1393, 86, 86, 1398, 1386, - 1399, 1397, 86, 1387, 86, 1389, 1400, 1390, 1401, 1391, - 86, 1402, 1392, 86, 86, 1408, 1394, 86, 1406, 1410, - 86, 86, 1393, 1403, 86, 1398, 86, 86, 1397, 1407, - 1405, 1419, 86, 1400, 1411, 1401, 86, 86, 1402, 86, - 1409, 1412, 1408, 1413, 1414, 1406, 86, 1415, 86, 86, - 1403, 171, 1416, 86, 1417, 1418, 1407, 1405, 1419, 1421, - 86, 1411, 1423, 86, 86, 86, 1420, 1409, 1412, 86, - 1413, 1414, 1424, 1422, 1415, 1426, 1425, 86, 86, 1416, - 86, 1417, 1418, 1427, 1428, 1429, 86, 86, 1430, 3777, - - 3777, 1431, 1434, 1420, 86, 1432, 1438, 86, 86, 3777, - 1422, 86, 1426, 1425, 86, 1435, 86, 86, 86, 1433, - 1427, 1428, 1429, 86, 1436, 1430, 86, 86, 1431, 1434, - 1437, 1439, 1432, 86, 1440, 86, 86, 1441, 86, 1442, - 1443, 1444, 1435, 86, 86, 1451, 1433, 86, 1448, 86, - 1445, 1436, 1446, 3777, 1449, 1447, 1450, 1437, 1439, 1461, - 86, 1440, 1455, 86, 1441, 1452, 1442, 1443, 1444, 1454, - 86, 86, 86, 1453, 3777, 1448, 1457, 1445, 86, 1446, - 86, 1449, 1447, 1450, 1458, 86, 86, 1459, 1456, 1455, - 1460, 86, 1452, 86, 86, 86, 1454, 86, 1462, 1463, - - 1453, 1465, 1464, 1457, 1466, 86, 86, 3777, 1467, 86, - 1468, 1458, 86, 1471, 1459, 1456, 1469, 1460, 86, 1470, - 86, 1472, 1473, 86, 3777, 1462, 1463, 1487, 1465, 1464, - 86, 86, 86, 1474, 86, 1467, 86, 1468, 1476, 86, - 1471, 86, 1475, 1469, 1478, 86, 1470, 1477, 1472, 1473, - 86, 1480, 1479, 1481, 1484, 1483, 86, 1482, 1485, 86, - 1474, 86, 86, 86, 86, 1476, 86, 1486, 3777, 1475, - 86, 1478, 86, 1490, 1477, 86, 3777, 1491, 1480, 1479, - 1481, 1484, 1483, 86, 1482, 1485, 1488, 1493, 1489, 86, - 1492, 86, 3777, 86, 1486, 86, 1496, 1494, 86, 1495, - - 1490, 86, 86, 1497, 1491, 86, 1499, 1500, 86, 1498, - 1502, 3777, 1501, 1488, 1493, 1489, 86, 1492, 1505, 86, - 1503, 1504, 1509, 1496, 1494, 86, 1495, 86, 1506, 86, - 86, 1510, 86, 1512, 1500, 86, 1498, 1502, 86, 1501, - 86, 1507, 1511, 86, 86, 1505, 1508, 1503, 1504, 1509, - 1520, 1522, 1521, 1524, 3777, 1506, 86, 1526, 1510, 86, - 1512, 1523, 3777, 1527, 86, 3777, 1525, 3777, 3777, 1511, - 86, 1529, 1528, 86, 1513, 86, 1531, 1520, 1514, 1521, - 1524, 1515, 1516, 86, 86, 86, 1517, 86, 1523, 86, - 1527, 3777, 1518, 1525, 86, 1536, 1519, 86, 1529, 1528, - - 86, 1513, 86, 1531, 1530, 1514, 1535, 1539, 1515, 1516, - 86, 1534, 1532, 1517, 1533, 86, 1537, 3777, 86, 1518, - 1538, 3777, 1540, 1519, 1541, 86, 1543, 86, 1544, 86, - 1542, 1530, 1547, 1535, 1539, 86, 86, 1545, 1534, 1532, - 1546, 1533, 1548, 86, 86, 3777, 86, 1538, 86, 1540, - 3777, 1541, 1549, 1543, 86, 1555, 3777, 1542, 86, 1547, - 86, 1556, 3777, 1561, 1545, 86, 86, 1557, 1560, 1548, - 1558, 1559, 86, 1569, 86, 3777, 1563, 86, 86, 1549, - 1550, 3777, 1555, 86, 86, 1551, 86, 1552, 1556, 1553, - 1561, 1554, 1562, 86, 1557, 1560, 1564, 1565, 86, 86, - - 1569, 1566, 1568, 1563, 86, 86, 1567, 1550, 1570, 1571, - 1572, 1576, 1551, 1573, 1552, 86, 1553, 1574, 1554, 1562, - 86, 86, 86, 1564, 1565, 86, 1575, 1578, 86, 1568, - 86, 1577, 1579, 86, 1580, 1570, 1571, 1572, 1581, 86, - 1573, 1585, 86, 86, 1574, 1583, 1584, 86, 1587, 1582, - 86, 86, 1588, 1575, 1578, 1590, 3777, 86, 1577, 1579, - 86, 1580, 86, 86, 1591, 1581, 86, 1586, 1585, 86, - 86, 1589, 1583, 1584, 1592, 1587, 1582, 1595, 1593, 86, - 1597, 1594, 86, 86, 1599, 86, 86, 1600, 1596, 1598, - 1601, 1591, 3777, 3777, 1586, 1605, 86, 1610, 1589, 86, - - 1607, 1592, 86, 86, 1595, 1593, 86, 86, 1594, 1608, - 86, 86, 86, 86, 1600, 1596, 1598, 1601, 1602, 1603, - 1604, 1606, 86, 1609, 86, 86, 86, 1607, 86, 86, - 86, 1611, 1613, 86, 1612, 1614, 1608, 1616, 1618, 1615, - 1617, 3777, 1619, 3777, 86, 1602, 1603, 1604, 1606, 86, - 1609, 1620, 86, 86, 86, 86, 1621, 86, 1611, 1613, - 86, 1612, 1614, 86, 1616, 1618, 1615, 1617, 1622, 1619, - 1623, 1624, 3777, 86, 1625, 86, 1627, 1626, 1620, 1631, - 1632, 1628, 1630, 1621, 1635, 86, 1629, 3777, 1633, 3777, - 86, 1638, 1634, 86, 86, 1622, 86, 1623, 1624, 86, - - 86, 1625, 86, 1627, 1626, 1636, 86, 86, 1628, 1630, - 86, 86, 86, 1629, 86, 1633, 86, 1637, 1638, 1634, - 1639, 1640, 1642, 86, 1641, 86, 1643, 1644, 86, 1645, - 1646, 86, 1636, 1647, 86, 1648, 86, 1649, 1651, 171, - 3777, 3777, 1665, 86, 1637, 1650, 86, 86, 1640, 1642, - 1659, 1641, 1654, 1643, 1644, 1655, 1645, 1646, 86, 86, - 1652, 86, 86, 1656, 1649, 86, 1653, 86, 1657, 86, - 86, 1658, 1650, 86, 1663, 3777, 86, 1659, 86, 1654, - 86, 86, 1655, 1661, 1660, 86, 1667, 1652, 1662, 3777, - 1656, 86, 3777, 1653, 1664, 1657, 86, 86, 1658, 1668, - - 1666, 1663, 1672, 86, 86, 1673, 1674, 86, 86, 1669, - 1661, 1660, 3777, 1667, 1670, 1662, 1671, 1680, 1675, 86, - 86, 1664, 1681, 1682, 86, 86, 1668, 1666, 1676, 1672, - 86, 1677, 1673, 1674, 1678, 86, 86, 1679, 1683, 1684, - 86, 86, 3777, 1671, 1680, 1675, 1688, 86, 1686, 1681, - 1682, 1685, 1691, 1687, 86, 1676, 86, 3777, 1677, 1689, - 86, 1678, 86, 1690, 1679, 1692, 1684, 86, 1694, 1693, - 86, 1696, 86, 1688, 86, 1695, 1697, 86, 1685, 1691, - 86, 1698, 86, 86, 1701, 1705, 1689, 86, 1699, 1702, - 1690, 86, 1692, 86, 86, 1694, 1693, 86, 1696, 1704, - - 1700, 3777, 1695, 1697, 1703, 1706, 1709, 86, 1698, 86, - 86, 1701, 86, 86, 1707, 1699, 1702, 86, 1710, 86, - 86, 1708, 1711, 1714, 1713, 86, 1704, 1700, 1712, 86, - 86, 1703, 1706, 1709, 86, 1715, 86, 1720, 1716, 1717, - 1719, 1707, 1721, 86, 1724, 1710, 86, 86, 1708, 1711, - 1714, 1713, 86, 1718, 86, 1712, 1722, 86, 86, 86, - 1725, 1723, 1715, 86, 1720, 1716, 1717, 1719, 86, 1721, - 86, 1724, 1726, 1727, 86, 1728, 1729, 1734, 1730, 1731, - 1718, 1732, 1735, 1722, 1736, 1733, 86, 86, 1723, 3777, - 86, 1737, 86, 3777, 1738, 1741, 1742, 3777, 3777, 86, - - 1727, 86, 1728, 86, 86, 1730, 1731, 86, 1732, 86, - 1743, 1745, 1733, 1739, 86, 1740, 86, 86, 1737, 86, - 86, 1738, 86, 1742, 1744, 1748, 86, 1747, 86, 1749, - 1746, 1751, 3777, 86, 1750, 1753, 3777, 1743, 1745, 86, - 1739, 86, 1740, 86, 1752, 86, 1759, 1768, 86, 1760, - 86, 1744, 1748, 86, 1747, 86, 1749, 1746, 1751, 1754, - 1755, 1750, 1753, 1757, 1761, 1756, 86, 86, 1758, 1762, - 1763, 1752, 86, 1759, 1765, 86, 1760, 86, 1764, 86, - 1766, 1767, 86, 1774, 1769, 1770, 1754, 86, 86, 3777, - 86, 1761, 86, 1776, 86, 86, 1762, 1763, 1772, 1777, - - 86, 1765, 1771, 1773, 86, 1764, 86, 1766, 1767, 86, - 86, 1769, 1770, 1775, 86, 86, 1778, 1779, 1780, 1781, - 1776, 86, 3777, 3777, 86, 1772, 86, 86, 1782, 1771, - 1773, 86, 1785, 1783, 1784, 86, 86, 1786, 86, 1787, - 1775, 86, 1789, 1778, 1779, 1780, 1781, 86, 1788, 86, - 86, 1792, 1791, 1793, 1790, 1782, 1796, 3777, 3777, 1785, - 1783, 1784, 86, 1794, 1786, 86, 1787, 86, 1795, 1789, - 86, 1798, 86, 1799, 1797, 1788, 3777, 1804, 86, 1791, - 86, 1790, 1805, 1796, 1803, 86, 86, 86, 1800, 86, - 1794, 86, 1801, 86, 86, 1795, 1806, 1807, 1798, 86, - - 1799, 1797, 1808, 86, 1804, 1802, 1809, 1810, 86, 1805, - 1811, 1803, 1813, 86, 1814, 1800, 1812, 3777, 1821, 1801, - 1817, 3777, 86, 1806, 1807, 1815, 1816, 86, 86, 86, - 86, 1818, 1802, 1809, 1822, 1820, 86, 1811, 1819, 86, - 86, 1814, 86, 1812, 86, 1823, 1824, 1817, 86, 86, - 86, 1828, 1815, 1816, 86, 1826, 86, 1825, 1818, 1827, - 1829, 86, 1820, 86, 1830, 1819, 1831, 86, 1832, 1833, - 1834, 3777, 1823, 1837, 1836, 3777, 1839, 86, 86, 86, - 86, 86, 1826, 86, 1825, 86, 1827, 1829, 1835, 1847, - 86, 86, 1841, 1831, 86, 86, 1833, 1834, 86, 86, - - 1837, 1836, 1838, 1839, 1840, 1842, 1843, 1846, 1844, 86, - 1849, 86, 86, 1848, 1845, 1835, 86, 86, 86, 1841, - 86, 86, 1852, 3777, 86, 1854, 3777, 1859, 86, 1838, - 1851, 1840, 1842, 1843, 1846, 1844, 86, 1849, 1850, 86, - 1848, 1845, 86, 1853, 1856, 1855, 1857, 86, 1858, 1852, - 86, 86, 1854, 86, 86, 1860, 1861, 1851, 86, 1862, - 86, 1863, 1869, 86, 1865, 1850, 86, 1866, 86, 1864, - 1853, 1856, 1855, 1857, 3777, 1858, 1867, 86, 86, 1868, - 86, 1870, 1860, 1861, 86, 86, 1862, 1872, 1863, 86, - 86, 1865, 3777, 1871, 1866, 1874, 1864, 3777, 1875, 1873, - - 1878, 86, 1881, 1867, 86, 86, 1868, 86, 1870, 86, - 171, 86, 1880, 86, 1872, 1876, 1877, 1879, 1882, 86, - 1871, 1885, 1874, 86, 1883, 1875, 1873, 1878, 86, 1881, - 86, 86, 1886, 1887, 1884, 1891, 1890, 1889, 1893, 1880, - 86, 86, 1876, 1877, 1879, 1882, 1888, 1892, 86, 1894, - 86, 1883, 1895, 86, 86, 86, 1896, 1898, 86, 1886, - 1887, 1884, 86, 1890, 1889, 86, 1899, 86, 1901, 1897, - 86, 86, 1900, 1888, 1892, 86, 1894, 86, 86, 1895, - 1902, 1904, 3777, 86, 1898, 1903, 1906, 1909, 86, 1905, - 86, 1907, 3777, 1899, 86, 1901, 1897, 1910, 86, 1900, - - 1908, 86, 86, 1914, 86, 1916, 86, 1902, 1904, 86, - 86, 1915, 1903, 1906, 1909, 1919, 1905, 86, 1907, 1911, - 1921, 1917, 1912, 1918, 1910, 1922, 1920, 1908, 86, 86, - 1924, 1927, 1916, 86, 1913, 86, 1923, 86, 1915, 86, - 1925, 86, 1919, 86, 86, 1929, 1911, 1921, 1917, 1912, - 1918, 1926, 86, 1920, 1928, 3777, 1931, 86, 1927, 1932, - 1930, 1913, 86, 1923, 1934, 1935, 1933, 1936, 86, 1937, - 86, 86, 86, 86, 86, 1938, 1939, 86, 1926, 1940, - 86, 1928, 86, 1931, 3777, 1943, 1932, 1930, 1942, 86, - 1941, 1934, 1935, 1933, 86, 1945, 1944, 1948, 86, 86, - - 3777, 86, 1946, 1939, 86, 86, 1949, 86, 1947, 86, - 86, 86, 86, 86, 1950, 1942, 1953, 1941, 86, 1951, - 86, 1952, 1945, 1944, 1948, 86, 1954, 86, 86, 1946, - 1956, 1955, 86, 1949, 86, 1947, 1957, 1959, 1962, 1958, - 1963, 1950, 1961, 1953, 86, 1960, 1951, 86, 1952, 1966, - 1964, 1971, 86, 1954, 86, 86, 86, 1956, 1955, 86, - 86, 86, 86, 1957, 1959, 1967, 1958, 1963, 1965, 1961, - 86, 1969, 1960, 1970, 1972, 86, 1966, 1964, 86, 1974, - 1973, 86, 1975, 1968, 1976, 1978, 1977, 3777, 86, 86, - 3777, 86, 1967, 3777, 86, 1965, 86, 86, 1969, 86, - - 1970, 1972, 86, 1980, 1981, 1979, 1974, 1973, 86, 1975, - 1968, 1976, 1978, 1977, 86, 1982, 86, 1985, 1988, 1983, - 86, 86, 1984, 1989, 1986, 1990, 1991, 1995, 86, 1987, - 1980, 1981, 1979, 1992, 1993, 86, 86, 86, 1994, 3777, - 2000, 1996, 1982, 86, 1985, 1988, 1983, 86, 86, 1984, - 1989, 1986, 86, 86, 86, 86, 1987, 1998, 1997, 1999, - 1992, 1993, 86, 2001, 86, 1994, 86, 2000, 1996, 86, - 2002, 2004, 2003, 2005, 2009, 2006, 2010, 86, 2011, 86, - 86, 86, 86, 86, 1998, 1997, 1999, 2012, 2013, 3777, - 2001, 86, 86, 2007, 86, 2015, 2008, 2002, 2004, 2003, - - 2005, 2009, 2006, 2010, 2016, 2014, 2017, 2018, 86, 86, - 86, 86, 86, 86, 86, 2013, 2019, 2021, 86, 86, - 2007, 2020, 2015, 2008, 2023, 2022, 86, 2024, 3777, 2025, - 2027, 2016, 2014, 2017, 2018, 2026, 86, 2036, 3777, 86, - 86, 86, 2028, 2035, 2021, 2029, 86, 2031, 86, 2030, - 2033, 2023, 2022, 2034, 2024, 86, 2025, 2027, 2038, 86, - 86, 2032, 2026, 2046, 2036, 86, 2041, 86, 86, 2028, - 2035, 86, 2029, 86, 2031, 2037, 2030, 2033, 2039, 86, - 2034, 86, 2042, 2040, 2043, 2038, 2044, 2045, 2032, 86, - 2047, 2048, 2049, 2041, 86, 86, 2052, 2057, 2050, 86, - - 86, 3777, 2037, 2051, 2061, 2053, 3777, 3777, 86, 2042, - 86, 2043, 2054, 2044, 2045, 2055, 86, 2047, 86, 86, - 86, 2056, 86, 2058, 86, 2050, 86, 2059, 86, 86, - 2051, 2067, 2053, 2060, 86, 2063, 86, 86, 2062, 2054, - 2066, 2064, 2055, 86, 2065, 2068, 2070, 2069, 2056, 86, - 2058, 86, 86, 86, 2059, 2071, 2076, 86, 2067, 86, - 2060, 86, 2063, 86, 86, 2062, 2072, 2066, 2064, 86, - 2073, 2065, 2068, 2070, 2069, 2074, 2077, 2078, 2079, 86, - 2080, 3777, 2071, 86, 2081, 2082, 2084, 2083, 86, 2085, - 2086, 86, 86, 2072, 86, 86, 2075, 2073, 2088, 3777, - - 2090, 86, 86, 86, 2078, 2079, 2092, 86, 86, 86, - 2087, 2081, 2082, 86, 2083, 86, 2085, 2089, 2093, 2095, - 2096, 2091, 86, 2075, 2094, 2088, 86, 86, 86, 86, - 2098, 86, 2097, 2092, 86, 2100, 2099, 2087, 2104, 2102, - 86, 86, 86, 2101, 2089, 2093, 2095, 2096, 2091, 2103, - 86, 2094, 86, 86, 171, 2108, 2105, 2098, 2106, 2097, - 2107, 86, 2100, 2099, 86, 86, 2102, 86, 86, 2109, - 2101, 2110, 2111, 86, 2112, 2113, 2103, 2116, 2114, 2117, - 2120, 2115, 86, 2105, 86, 2106, 86, 2107, 86, 86, - 86, 86, 86, 2119, 86, 2118, 2109, 2121, 2110, 2111, - - 2123, 2112, 2113, 2122, 86, 2114, 2117, 86, 2115, 86, - 86, 2124, 2126, 2125, 86, 2127, 2129, 3777, 2131, 2128, - 2119, 86, 2118, 2130, 2121, 86, 2133, 86, 2149, 2135, - 2122, 86, 2132, 86, 86, 86, 2136, 86, 2124, 2134, - 2125, 86, 86, 2129, 86, 2131, 2128, 86, 86, 2137, - 2130, 86, 2139, 2133, 2138, 2140, 2135, 2141, 86, 2132, - 86, 2143, 2147, 2136, 86, 2144, 2134, 86, 86, 86, - 2142, 2146, 2145, 2148, 86, 86, 2137, 86, 2155, 2139, - 2150, 2138, 2140, 2151, 2141, 86, 86, 86, 2143, 2147, - 2154, 2156, 2144, 86, 86, 2152, 2153, 2142, 2146, 2145, - - 86, 86, 2159, 86, 86, 2155, 2157, 2150, 2158, 2160, - 2151, 2161, 2163, 2162, 2170, 2164, 86, 2154, 2156, 86, - 86, 2165, 2152, 2153, 2166, 2167, 2168, 86, 86, 2159, - 86, 86, 2169, 2157, 2171, 2158, 86, 2172, 86, 86, - 2162, 86, 2164, 2174, 2176, 2173, 86, 2177, 2165, 86, - 2179, 2166, 2167, 86, 86, 86, 2175, 2178, 86, 2169, - 86, 2171, 2182, 2180, 2181, 2185, 86, 2183, 3777, 86, - 86, 2176, 2173, 2186, 2177, 86, 2184, 86, 2187, 86, - 2188, 86, 86, 2175, 2178, 2189, 86, 86, 3777, 86, - 2180, 2181, 2185, 2197, 2183, 86, 2202, 3777, 2209, 2194, - - 2186, 2203, 86, 2184, 86, 2187, 86, 2188, 2190, 2191, - 2192, 2195, 2196, 2200, 2198, 2193, 3777, 86, 2204, 86, - 86, 86, 2199, 86, 2201, 86, 2194, 2206, 86, 86, - 86, 86, 2205, 86, 2207, 2190, 2191, 2192, 2195, 2196, - 2200, 2198, 2193, 2208, 86, 2204, 86, 2210, 2213, 2199, - 86, 2201, 86, 2211, 2206, 86, 2212, 2214, 86, 2205, - 86, 2207, 86, 2215, 2216, 86, 2218, 2217, 2219, 2220, - 2208, 86, 86, 2221, 2210, 86, 86, 2222, 2226, 86, - 2211, 2223, 2225, 2212, 2214, 2224, 2230, 2228, 86, 86, - 2215, 2216, 86, 2218, 2217, 86, 2220, 2227, 86, 86, - - 86, 2231, 2229, 86, 2222, 86, 2232, 86, 2223, 2225, - 86, 2233, 2224, 86, 2228, 86, 2234, 2237, 86, 2235, - 86, 2236, 2238, 86, 2227, 2239, 2240, 3777, 2231, 2229, - 2242, 86, 2241, 2232, 86, 3777, 86, 2245, 2233, 2246, - 2244, 2248, 2261, 2234, 86, 2247, 2235, 86, 2236, 2238, - 2243, 2249, 2239, 86, 86, 3777, 3777, 86, 86, 2241, - 86, 2250, 86, 2251, 86, 2255, 2246, 2244, 2252, 86, - 2256, 2254, 2247, 86, 86, 2253, 2257, 2243, 86, 86, - 86, 86, 86, 86, 2258, 86, 2259, 86, 2250, 86, - 2251, 2260, 2255, 86, 2262, 2252, 2265, 2256, 2254, 3777, - - 86, 2263, 2253, 2257, 2264, 2268, 2270, 2267, 86, 3777, - 86, 2258, 2266, 2259, 86, 2269, 86, 86, 2260, 86, - 2275, 2271, 2272, 2265, 86, 2276, 86, 2274, 2263, 2273, - 86, 2264, 2268, 86, 2267, 86, 2277, 86, 2279, 2266, - 2278, 86, 2269, 86, 2280, 2281, 2284, 2275, 2271, 2272, - 2282, 86, 2276, 2285, 2274, 2283, 2273, 86, 86, 86, - 3777, 2286, 86, 2277, 2288, 86, 86, 2278, 86, 2289, - 2287, 2280, 2281, 86, 86, 2292, 86, 2282, 86, 2295, - 2285, 2296, 2283, 2290, 2293, 2291, 86, 2294, 2286, 2297, - 86, 2288, 86, 86, 2298, 86, 2289, 2287, 2303, 86, - - 2299, 86, 2309, 2305, 2300, 86, 2295, 86, 2296, 2306, - 2290, 2293, 2291, 2301, 2294, 2304, 86, 2310, 2302, 2307, - 86, 2298, 86, 86, 2308, 2303, 2312, 2299, 2313, 86, - 86, 2300, 2311, 86, 86, 2314, 86, 86, 2316, 2315, - 2301, 2317, 2304, 86, 2318, 2302, 2320, 2322, 86, 86, - 2319, 86, 86, 2312, 86, 2313, 86, 2321, 2323, 2311, - 2326, 86, 86, 2331, 2324, 2316, 2315, 86, 2317, 2325, - 86, 2318, 86, 2327, 2328, 2329, 86, 2319, 86, 86, - 2332, 2330, 171, 86, 2321, 86, 2333, 2326, 86, 86, - 86, 2324, 2334, 2335, 2337, 2338, 2325, 2340, 2336, 3777, - - 2327, 2328, 2329, 86, 86, 86, 2339, 2332, 2330, 2341, - 2342, 2343, 86, 2333, 2345, 2344, 86, 2346, 86, 86, - 86, 2350, 2338, 2355, 2340, 2336, 86, 86, 86, 86, - 2347, 2348, 86, 2339, 2349, 2351, 2341, 2342, 86, 86, - 2354, 2345, 2344, 86, 2346, 86, 86, 2352, 86, 2353, - 86, 2358, 2356, 86, 2357, 2359, 86, 2347, 2348, 86, - 86, 2349, 2351, 86, 86, 2360, 2362, 2354, 2361, 86, - 2366, 86, 86, 2364, 2352, 2363, 2353, 2365, 2358, 2356, - 2369, 2357, 2359, 86, 86, 2367, 86, 2370, 86, 86, - 86, 86, 2360, 2373, 2372, 2361, 2368, 2366, 86, 2371, - - 2364, 86, 2363, 2375, 2365, 86, 2374, 2369, 2378, 2376, - 2377, 86, 2367, 2379, 2370, 86, 2381, 86, 86, 86, - 2373, 2372, 86, 2368, 86, 2380, 2371, 86, 2382, 2384, - 2375, 2383, 86, 2374, 2385, 2378, 2376, 2377, 2386, 86, - 86, 86, 86, 2381, 2387, 3777, 2388, 86, 3777, 86, - 2389, 2390, 2380, 2391, 86, 2382, 2384, 2392, 2383, 2394, - 2393, 2385, 86, 2395, 86, 2396, 2398, 2397, 2399, 86, - 86, 2387, 86, 2388, 3777, 86, 2400, 2389, 2390, 86, - 2391, 86, 2403, 2442, 86, 3777, 86, 2393, 86, 86, - 2395, 2404, 2396, 2402, 2397, 2399, 86, 2401, 86, 2405, - - 86, 2406, 86, 2400, 2407, 2412, 2408, 86, 86, 2403, - 2409, 2414, 2410, 2411, 86, 86, 2415, 86, 2404, 86, - 2402, 86, 86, 86, 2401, 2424, 2405, 86, 2406, 2413, - 2416, 2407, 2412, 2408, 86, 2421, 2423, 2409, 2425, 2410, - 2411, 86, 86, 86, 2417, 2418, 2422, 86, 2419, 2431, - 86, 86, 86, 2426, 2427, 2428, 2413, 2416, 3777, 2429, - 86, 2420, 2421, 2423, 2434, 2425, 86, 2430, 2433, 86, - 2432, 2417, 2418, 2422, 86, 2419, 2431, 86, 86, 86, - 2426, 2427, 2428, 2435, 86, 2437, 2429, 2436, 2420, 86, - 86, 2434, 2438, 2439, 2430, 2433, 86, 2432, 2440, 2444, - - 2445, 86, 2441, 86, 2443, 2446, 86, 86, 2448, 86, - 2435, 86, 2437, 86, 2436, 2447, 86, 2450, 86, 2438, - 2439, 2449, 2455, 2451, 86, 2440, 2444, 2445, 2452, 2441, - 86, 2443, 86, 2454, 2453, 2448, 2456, 86, 2457, 86, - 86, 2458, 2447, 86, 2450, 86, 86, 2461, 2449, 2465, - 2451, 2462, 86, 2466, 86, 2452, 86, 2459, 86, 86, - 2454, 2453, 2460, 2456, 2463, 2457, 86, 2464, 2458, 2467, - 2470, 2468, 2472, 2471, 2461, 2534, 86, 86, 2462, 86, - 2466, 2469, 86, 86, 2473, 86, 2476, 2501, 86, 86, - 2477, 2463, 2478, 86, 2464, 86, 2467, 86, 2468, 2472, - - 2471, 2474, 86, 2479, 2480, 86, 2482, 86, 2469, 2475, - 2481, 2473, 2483, 86, 86, 86, 3777, 2477, 86, 2478, - 86, 2486, 86, 2484, 3777, 2495, 2485, 2490, 2474, 86, - 2479, 2480, 86, 2482, 2487, 86, 2475, 2481, 2488, 2483, - 86, 86, 86, 2489, 2491, 2492, 86, 86, 2486, 2493, - 2484, 2494, 2495, 2485, 2490, 2496, 2498, 3777, 3777, 2497, - 86, 2487, 86, 86, 3777, 2502, 86, 2500, 2499, 2508, - 86, 2491, 2492, 86, 86, 86, 2493, 86, 2494, 2503, - 2504, 86, 2496, 2498, 2507, 86, 2497, 2505, 86, 86, - 2509, 2506, 2502, 86, 2500, 2499, 2508, 86, 86, 2513, - - 2510, 2511, 2512, 2514, 2515, 3777, 2503, 2504, 3777, 86, - 2516, 2507, 86, 2519, 2505, 86, 86, 2509, 2506, 86, - 2517, 86, 86, 2521, 2525, 86, 2513, 2510, 2511, 2512, - 2514, 2515, 2520, 2518, 86, 86, 86, 2516, 2524, 2522, - 2519, 86, 2523, 2526, 86, 2527, 2528, 2517, 86, 2529, - 2521, 86, 2530, 3777, 2532, 86, 86, 86, 2531, 2520, - 2518, 86, 2535, 2533, 2538, 2524, 2522, 171, 86, 2523, - 2526, 86, 86, 2528, 2539, 86, 2529, 2536, 2540, 2530, - 86, 2532, 2537, 2543, 2541, 2531, 2542, 2548, 3777, 2535, - 2533, 2549, 3777, 86, 2544, 2551, 86, 2547, 2552, 2554, - - 2555, 2550, 86, 86, 86, 2540, 86, 2553, 2545, 86, - 86, 2541, 2557, 2542, 86, 86, 86, 86, 2549, 2546, - 86, 2544, 2551, 2556, 2547, 86, 2554, 86, 2550, 86, - 86, 2558, 2559, 2560, 2553, 2545, 2561, 3777, 2562, 86, - 86, 2565, 2563, 86, 86, 86, 2546, 2564, 2566, 2572, - 2556, 86, 2567, 86, 86, 2568, 86, 3777, 2558, 2559, - 2560, 86, 2570, 2561, 86, 2562, 86, 2571, 2565, 2563, - 86, 2569, 86, 2573, 2564, 2566, 86, 2575, 86, 2567, - 2574, 2576, 2568, 2580, 86, 2577, 86, 2579, 2578, 2570, - 86, 86, 86, 2584, 2571, 2581, 86, 86, 2569, 86, - - 2573, 3777, 86, 2586, 2575, 2582, 2585, 2574, 2576, 2583, - 2580, 86, 2577, 2587, 2579, 2578, 2588, 86, 86, 86, - 86, 86, 2581, 2589, 86, 86, 2590, 86, 2592, 86, - 2586, 2591, 2582, 2585, 86, 2594, 2583, 2593, 2595, 86, - 2587, 86, 2596, 2588, 2597, 2598, 2600, 2666, 2599, 3777, - 2589, 2601, 86, 2590, 2603, 2592, 86, 3777, 2591, 86, - 2604, 86, 2594, 2611, 2593, 2605, 2606, 86, 2610, 2613, - 86, 2597, 2598, 2600, 86, 2599, 86, 2602, 2601, 86, - 86, 86, 86, 2607, 86, 2608, 86, 2604, 2609, 86, - 86, 2612, 2605, 2606, 86, 2610, 86, 2614, 86, 2615, - - 2616, 2619, 86, 2617, 2602, 2620, 2618, 2621, 3777, 86, - 2607, 86, 2608, 2622, 86, 2609, 86, 2623, 2612, 86, - 2624, 2625, 2626, 2627, 2614, 3777, 2615, 2616, 86, 86, - 2617, 86, 2620, 2618, 2621, 86, 2628, 2632, 2633, 86, - 2622, 2631, 2635, 2634, 2623, 86, 2629, 2624, 86, 86, - 2627, 86, 2630, 86, 2637, 2638, 86, 2636, 86, 86, - 2640, 2639, 2641, 2628, 86, 86, 86, 86, 2631, 86, - 2634, 2644, 2642, 2629, 2643, 2646, 2645, 2647, 2650, 2630, - 2652, 86, 2638, 86, 2636, 86, 86, 86, 2639, 86, - 86, 2649, 86, 2654, 2659, 2655, 3777, 86, 2644, 2642, - - 2648, 2643, 86, 2645, 2647, 86, 2651, 86, 86, 2662, - 2653, 2656, 2661, 86, 86, 86, 86, 2657, 2649, 86, - 2654, 86, 2655, 2660, 86, 2665, 3777, 2648, 2663, 2672, - 2668, 86, 2658, 2651, 86, 86, 2662, 2653, 2656, 2661, - 86, 2664, 86, 86, 2657, 2674, 2667, 2669, 2670, 86, - 2660, 86, 86, 86, 2671, 2663, 86, 2668, 2673, 2658, - 86, 2678, 2680, 2679, 2675, 2681, 86, 86, 2664, 2676, - 86, 2682, 2674, 2667, 2669, 2670, 86, 86, 86, 2686, - 86, 2671, 86, 2677, 2683, 2673, 2687, 2684, 86, 2680, - 2679, 2675, 2681, 86, 2688, 86, 2676, 2692, 2682, 86, - - 2685, 86, 3777, 2693, 86, 86, 2686, 2689, 3777, 3777, - 2677, 2683, 3777, 2687, 2684, 2694, 2695, 2696, 86, 86, - 3777, 2688, 2690, 2697, 2691, 86, 2698, 2685, 2700, 86, - 2693, 86, 2701, 2707, 2689, 2699, 2703, 86, 86, 86, - 86, 86, 2694, 2695, 2696, 2704, 86, 2702, 86, 2690, - 2697, 2691, 2706, 2698, 86, 2700, 2705, 2708, 86, 2701, - 2709, 2710, 2699, 2703, 86, 86, 86, 86, 2711, 2712, - 2713, 2715, 2704, 86, 2702, 2714, 2718, 86, 86, 2706, - 2716, 2719, 2722, 2705, 2723, 86, 2717, 2709, 2710, 86, - 2724, 86, 86, 86, 86, 86, 2712, 2713, 2715, 86, - - 86, 2720, 2714, 2718, 86, 2721, 2725, 2716, 2719, 2722, - 2726, 2727, 2728, 2717, 2729, 2730, 86, 86, 86, 86, - 3777, 2735, 86, 86, 2733, 3777, 2731, 2740, 2720, 86, - 86, 2734, 2721, 2725, 2732, 3777, 3777, 2726, 2727, 2728, - 86, 2729, 86, 171, 2738, 2739, 2742, 86, 2735, 2751, - 2743, 2733, 86, 2731, 86, 86, 86, 86, 2734, 2744, - 2736, 2732, 2737, 2741, 86, 86, 2745, 86, 2746, 2748, - 86, 2738, 2739, 2742, 2747, 86, 86, 2743, 86, 2750, - 2753, 2749, 3777, 86, 2752, 2754, 2744, 2736, 86, 2737, - 2741, 86, 2755, 2745, 86, 2746, 2748, 2756, 86, 2757, - - 2758, 2747, 3777, 2759, 2766, 2762, 2750, 86, 2749, 86, - 86, 2752, 2754, 2760, 86, 2761, 2764, 2768, 86, 2755, - 86, 2763, 3777, 2765, 86, 2767, 86, 2758, 2769, 86, - 86, 86, 2762, 2770, 86, 2771, 86, 2772, 86, 86, - 2760, 86, 2761, 2764, 2768, 2773, 2777, 2774, 2763, 86, - 2765, 86, 2767, 2775, 2776, 2769, 2778, 86, 3777, 86, - 2770, 86, 86, 2779, 2772, 86, 2780, 86, 2781, 86, - 2787, 86, 2773, 2777, 2774, 86, 2784, 86, 2782, 2783, - 2775, 2776, 2790, 86, 2785, 86, 86, 2786, 86, 86, - 2779, 2788, 86, 2780, 86, 2781, 3777, 2787, 2789, 3777, - - 2791, 2792, 2795, 2784, 2793, 2782, 2783, 86, 86, 2790, - 86, 2785, 86, 2794, 2786, 2797, 2796, 2798, 2801, 86, - 2802, 86, 86, 86, 86, 2789, 86, 2791, 2792, 2795, - 2799, 2793, 86, 2800, 2803, 3777, 2805, 2804, 2806, 3777, - 2794, 86, 86, 2796, 2798, 2807, 2817, 2808, 3777, 2810, - 86, 86, 86, 86, 86, 86, 2809, 2799, 86, 2812, - 2800, 2803, 86, 2805, 2804, 2806, 2811, 2813, 2814, 86, - 2815, 86, 2807, 86, 2808, 86, 2810, 2816, 86, 2819, - 86, 2821, 3777, 2809, 2818, 2820, 2812, 2825, 2823, 2822, - 86, 86, 2833, 2811, 2813, 2814, 86, 2815, 86, 86, - - 86, 86, 2824, 86, 2816, 2829, 86, 2831, 86, 86, - 2827, 2818, 2820, 86, 2825, 2823, 2822, 2826, 86, 86, - 2828, 2830, 2832, 2834, 86, 2835, 86, 86, 2836, 2824, - 86, 2837, 2829, 2839, 86, 2838, 86, 2827, 2841, 86, - 2840, 86, 2843, 86, 2826, 2844, 2842, 2828, 2830, 86, - 2834, 86, 2835, 86, 2846, 2836, 86, 86, 2837, 2845, - 2839, 86, 2838, 2847, 86, 2841, 2849, 2840, 3777, 86, - 2848, 2850, 2844, 2842, 2852, 86, 2851, 86, 86, 86, - 2855, 2846, 86, 2853, 2854, 2857, 2845, 2856, 2860, 86, - 2859, 86, 3777, 2849, 2858, 86, 2864, 2848, 86, 86, - - 86, 2852, 2862, 2851, 2861, 2863, 86, 2855, 3777, 86, - 2853, 2854, 86, 86, 2856, 2860, 86, 2859, 86, 2866, - 2865, 2858, 2867, 2864, 86, 2871, 2870, 2872, 2868, 2862, - 86, 2861, 2863, 86, 86, 86, 2869, 2873, 2874, 86, - 2875, 2876, 2878, 86, 86, 2877, 2866, 2865, 86, 2867, - 2880, 86, 86, 2870, 2872, 2868, 86, 2879, 3777, 2881, - 3777, 2882, 3777, 2869, 86, 86, 2883, 86, 2876, 2878, - 86, 2884, 2877, 2886, 2885, 2889, 86, 2880, 86, 86, - 86, 86, 2891, 2888, 2879, 86, 2881, 86, 2882, 86, - 2887, 2890, 2892, 2883, 86, 2893, 86, 2894, 2884, 86, - - 2886, 2885, 86, 2896, 2899, 2895, 2897, 2898, 2900, 86, - 2888, 86, 2902, 2904, 86, 86, 3777, 2887, 2890, 86, - 86, 86, 2893, 86, 86, 2903, 86, 2905, 86, 2901, - 2896, 2899, 2895, 2897, 2898, 2900, 86, 2906, 2909, 86, - 86, 2907, 2908, 86, 86, 86, 2911, 2912, 2910, 3777, - 2913, 86, 2903, 86, 2905, 86, 2901, 2917, 2915, 3777, - 2914, 3777, 171, 2924, 2906, 2909, 86, 2916, 2907, 2908, - 86, 86, 2920, 2911, 2912, 2910, 86, 2913, 86, 86, - 2921, 2918, 2922, 2923, 2917, 2915, 86, 2914, 2919, 2925, - 86, 2926, 86, 86, 2916, 2927, 86, 2928, 2930, 2920, - - 3777, 2932, 2929, 3777, 86, 86, 3777, 2921, 2918, 2922, - 2923, 86, 2931, 86, 86, 2919, 86, 86, 2926, 2933, - 86, 86, 2927, 86, 2928, 2930, 86, 2934, 2932, 2929, - 2935, 2936, 2937, 2938, 2940, 86, 86, 2939, 86, 2931, - 86, 86, 2941, 2942, 3777, 2943, 2933, 2945, 2948, 3777, - 86, 86, 86, 2944, 2934, 2946, 2949, 2935, 2936, 2937, - 2938, 2940, 86, 2950, 2939, 2951, 86, 2955, 86, 2941, - 2942, 86, 2943, 2947, 86, 2948, 86, 2952, 86, 2953, - 2944, 86, 2946, 86, 2954, 2956, 86, 86, 86, 2957, - 2950, 2959, 86, 86, 2955, 2960, 2958, 86, 86, 2962, - - 2947, 2961, 86, 86, 2952, 86, 2953, 2963, 2964, 2967, - 2965, 2954, 2956, 2968, 2969, 3777, 2957, 86, 2959, 86, - 2966, 2970, 2960, 2958, 86, 2977, 2962, 2976, 2961, 86, - 86, 2973, 2975, 2971, 86, 86, 2967, 2965, 2974, 2972, - 86, 86, 86, 86, 2978, 86, 86, 2966, 86, 86, - 2979, 86, 86, 86, 2976, 2980, 2981, 86, 2973, 2975, - 2971, 2983, 86, 2982, 2984, 2974, 2972, 2985, 86, 2986, - 2987, 2978, 86, 2988, 3777, 2990, 2989, 2979, 2993, 86, - 3777, 2991, 2980, 2981, 86, 86, 86, 2994, 2983, 86, - 2982, 2984, 86, 86, 2985, 86, 86, 2987, 2992, 2995, - - 86, 2996, 2990, 2989, 2997, 2993, 86, 2998, 2991, 86, - 2999, 86, 3000, 86, 2994, 86, 3001, 86, 3002, 3005, - 3003, 86, 3006, 86, 3004, 2992, 2995, 3008, 2996, 3007, - 3009, 2997, 86, 86, 2998, 3012, 3010, 2999, 86, 3000, - 86, 86, 86, 3001, 3011, 86, 86, 3003, 86, 3006, - 86, 3004, 3013, 3014, 3008, 3018, 3007, 3009, 86, 3016, - 3015, 3017, 3012, 3010, 3020, 86, 86, 86, 3019, 86, - 3021, 3011, 86, 3023, 86, 86, 3022, 3777, 3024, 86, - 3014, 3025, 3018, 3027, 3026, 86, 3016, 3015, 3017, 3029, - 3028, 86, 86, 3033, 86, 3019, 86, 3021, 3030, 3031, - - 3023, 3035, 3038, 3022, 86, 3024, 3032, 86, 86, 86, - 86, 3026, 86, 86, 86, 3034, 3029, 3028, 3036, 3037, - 86, 86, 3042, 3039, 86, 3030, 3031, 86, 3035, 86, - 3040, 3045, 3046, 3032, 3041, 3043, 86, 86, 3044, 86, - 86, 3048, 3034, 3047, 86, 3036, 3037, 3049, 86, 3042, - 3039, 3050, 3053, 86, 3051, 86, 86, 3040, 86, 3046, - 3052, 3041, 3043, 3058, 3054, 3044, 3055, 86, 86, 86, - 3047, 86, 86, 86, 3049, 3056, 3057, 3059, 3050, 3053, - 3060, 3051, 86, 3061, 86, 86, 3062, 3052, 86, 3063, - 3058, 3054, 86, 3055, 86, 3065, 3777, 3064, 3066, 86, - - 3068, 3067, 3056, 3057, 3059, 86, 3069, 3060, 3070, 86, - 86, 86, 3071, 86, 3073, 86, 3063, 3072, 86, 3075, - 3074, 3076, 171, 86, 3064, 3066, 86, 3068, 3067, 3078, - 3079, 3077, 3080, 3069, 86, 3085, 3092, 3081, 3082, 3071, - 86, 3073, 86, 86, 3072, 86, 86, 3074, 86, 3083, - 3084, 3086, 3088, 3087, 86, 3093, 86, 3079, 3077, 3096, - 86, 3089, 3090, 86, 86, 3082, 3091, 86, 86, 3094, - 86, 86, 86, 86, 86, 86, 3083, 3084, 3086, 3088, - 3087, 86, 3095, 3097, 3098, 3100, 86, 86, 3089, 3090, - 3099, 86, 3777, 3091, 3101, 3104, 3094, 86, 3102, 3105, - - 86, 3103, 3111, 86, 86, 3108, 86, 3110, 3113, 3095, - 3097, 3098, 3100, 86, 86, 3106, 86, 3099, 3107, 3109, - 86, 3101, 3104, 86, 86, 3102, 3105, 3114, 3103, 3111, - 86, 86, 3108, 86, 3110, 3112, 86, 86, 3119, 3115, - 86, 3120, 3106, 3116, 86, 3107, 3109, 86, 86, 3117, - 86, 3118, 3121, 3122, 3114, 3123, 86, 3124, 3777, 86, - 86, 86, 3112, 3125, 3128, 86, 3115, 3126, 3120, 3127, - 3116, 86, 3777, 86, 3130, 86, 3117, 3132, 3118, 3121, - 3122, 86, 3123, 86, 3124, 86, 86, 3129, 3133, 3135, - 3125, 86, 3131, 3136, 3126, 86, 3127, 3138, 3777, 86, - - 86, 3130, 3137, 3134, 3132, 86, 86, 3139, 3140, 3141, - 86, 3142, 3777, 86, 3129, 86, 3144, 3145, 3143, 3131, - 3146, 86, 3147, 3777, 3138, 86, 3151, 3148, 86, 3137, - 3134, 86, 3149, 3777, 86, 86, 3141, 3153, 3142, 86, - 86, 86, 3150, 3144, 3145, 3143, 86, 3154, 3152, 3147, - 86, 3155, 86, 86, 3148, 86, 86, 3156, 3157, 3149, - 86, 86, 3158, 86, 3153, 3159, 3161, 3160, 3162, 3150, - 3163, 3777, 3164, 3170, 3154, 3152, 3165, 3167, 86, 86, - 86, 3166, 3168, 3174, 3156, 86, 86, 3169, 86, 86, - 86, 3173, 86, 3161, 3160, 3162, 86, 86, 86, 3164, - - 3170, 3175, 86, 3165, 3171, 3172, 3176, 3178, 3166, 86, - 86, 86, 86, 3177, 3169, 3179, 3180, 86, 3173, 3183, - 3182, 86, 3184, 3185, 3186, 3187, 3181, 86, 86, 86, - 3188, 3171, 3172, 86, 3178, 86, 86, 86, 3191, 3192, - 3177, 3194, 3179, 86, 86, 3189, 86, 3182, 86, 3184, - 86, 3186, 86, 3181, 86, 3190, 3193, 3188, 3195, 3196, - 3199, 3198, 3200, 3201, 3197, 86, 86, 86, 86, 86, - 86, 3202, 3189, 86, 3203, 3204, 86, 3205, 3206, 86, - 86, 3211, 3190, 3193, 86, 3195, 3208, 3199, 3198, 3200, - 3201, 86, 3207, 3209, 3210, 86, 3212, 3213, 86, 3217, - - 86, 3203, 3204, 86, 86, 3206, 86, 86, 3211, 3214, - 86, 86, 86, 3208, 3218, 3216, 3215, 3219, 86, 3207, - 3209, 3210, 86, 3212, 3213, 86, 3217, 3220, 3224, 3223, - 86, 86, 3222, 3225, 3227, 3221, 3214, 86, 3226, 3228, - 3229, 86, 3216, 3215, 3219, 86, 3230, 86, 86, 3231, - 3236, 86, 3232, 3777, 3220, 3224, 3223, 3233, 3237, 3222, - 3234, 86, 3221, 3235, 3238, 86, 86, 3229, 3239, 86, - 3240, 86, 3777, 86, 3242, 86, 3231, 3236, 86, 3232, - 86, 3241, 3244, 86, 3233, 3237, 86, 3234, 86, 86, - 3235, 3238, 3243, 3245, 86, 3239, 86, 3240, 3246, 3247, - - 86, 3242, 3249, 3248, 86, 86, 86, 3250, 3241, 3244, - 86, 86, 3251, 3253, 3254, 3252, 3255, 3257, 3259, 3243, - 3245, 3777, 3256, 3261, 3260, 3246, 3247, 86, 3258, 86, - 3248, 86, 3264, 3268, 86, 86, 86, 3269, 86, 3251, - 86, 3254, 3252, 3255, 86, 86, 86, 3262, 86, 3256, - 86, 3260, 3263, 3265, 3266, 3258, 3777, 3267, 3777, 86, - 86, 3272, 3270, 3274, 86, 86, 86, 3273, 3271, 86, - 86, 86, 86, 3276, 3262, 86, 3280, 3283, 3277, 3263, - 3265, 3266, 3278, 86, 3267, 86, 86, 3777, 3272, 3270, - 3274, 3275, 3279, 3282, 3273, 3271, 86, 3285, 86, 86, - - 3281, 3284, 3289, 3280, 86, 86, 3290, 3288, 3286, 3278, - 86, 3287, 86, 86, 86, 86, 86, 3293, 3275, 3279, - 3282, 86, 3291, 3292, 86, 3295, 3298, 3281, 3284, 86, - 3296, 3777, 86, 86, 3288, 3286, 3297, 3294, 3287, 86, - 86, 3299, 3304, 86, 3293, 3300, 3310, 86, 86, 3291, - 3311, 86, 3295, 3301, 3302, 86, 86, 3296, 86, 3303, - 86, 3305, 3312, 3297, 3294, 3306, 3777, 3308, 3299, 3304, - 3309, 3307, 3300, 86, 3315, 86, 86, 86, 3313, 86, - 3301, 3302, 86, 86, 86, 86, 3303, 3316, 3305, 86, - 3318, 3317, 3306, 86, 3308, 3314, 86, 3309, 3307, 3319, - - 3320, 3315, 86, 3322, 3321, 3313, 3324, 3326, 3328, 86, - 3323, 3325, 86, 86, 3316, 3777, 86, 3318, 86, 3329, - 86, 86, 3314, 86, 3777, 3330, 3319, 86, 86, 3331, - 3322, 3321, 3327, 3324, 86, 86, 3332, 3323, 3325, 86, - 3333, 3334, 86, 3335, 3337, 3777, 3329, 86, 86, 3777, - 3336, 86, 3330, 86, 3343, 86, 3331, 86, 3338, 3327, - 3339, 3340, 86, 3332, 3342, 86, 3341, 3333, 3334, 3777, - 3335, 86, 86, 3345, 86, 86, 3344, 3336, 3349, 3346, - 3350, 3343, 86, 3347, 86, 3338, 3353, 3339, 3340, 86, - 86, 3342, 86, 3341, 3354, 3348, 3352, 86, 86, 3351, - - 3345, 86, 86, 3344, 86, 3349, 3346, 3350, 86, 3355, - 3347, 3356, 3358, 86, 3359, 3360, 3357, 86, 3361, 3363, - 3364, 86, 3348, 3352, 3362, 86, 3351, 3365, 3366, 3367, - 86, 86, 3777, 3369, 3371, 86, 3355, 3368, 86, 3358, - 86, 3359, 86, 86, 3372, 86, 86, 3364, 3374, 3777, - 86, 3362, 86, 3373, 3365, 3366, 3367, 86, 3370, 86, - 86, 3371, 3375, 3378, 3368, 86, 3376, 3380, 3377, 3379, - 86, 86, 3381, 3383, 3387, 86, 86, 3777, 86, 3382, - 3373, 86, 3777, 3385, 3388, 3370, 86, 3384, 86, 3375, - 3378, 3389, 86, 3376, 86, 3377, 3379, 3386, 86, 3393, - - 3390, 86, 3391, 86, 86, 86, 3382, 86, 3397, 86, - 3385, 86, 3394, 3395, 3384, 86, 86, 3396, 3389, 3398, - 86, 3392, 3777, 3400, 3386, 3399, 3393, 3390, 3404, 86, - 86, 3401, 86, 3402, 86, 3397, 3405, 3403, 3406, 3394, - 3395, 3407, 3408, 86, 3409, 86, 3398, 3410, 3392, 86, - 86, 86, 3399, 3411, 86, 3404, 3412, 86, 3401, 3413, - 3402, 86, 86, 3405, 3403, 3406, 3414, 3415, 86, 86, - 3416, 3409, 3419, 86, 3420, 86, 3421, 3424, 86, 86, - 3411, 3417, 3418, 3412, 3423, 86, 86, 3425, 86, 86, - 3422, 86, 86, 3414, 3415, 86, 3426, 3427, 86, 86, - - 3428, 3420, 86, 3421, 86, 3429, 3430, 86, 3417, 3418, - 3434, 3423, 3431, 3432, 3425, 86, 3433, 3422, 3435, 3436, - 3441, 3438, 3439, 3426, 3427, 3777, 86, 86, 3442, 3437, - 3440, 86, 86, 86, 86, 3443, 86, 86, 86, 3431, - 3432, 3445, 3444, 3433, 3446, 86, 86, 86, 86, 3439, - 86, 3447, 86, 86, 3452, 3442, 3437, 3440, 3448, 86, - 3449, 3451, 86, 86, 3450, 86, 86, 3453, 86, 3444, - 3457, 86, 86, 3454, 86, 3455, 3456, 86, 3447, 3459, - 86, 3452, 3460, 86, 3461, 3448, 3458, 3449, 3451, 86, - 3462, 3450, 3463, 3465, 86, 3469, 3466, 3457, 3464, 86, - - 3454, 86, 3455, 3456, 86, 86, 86, 86, 3467, 86, - 3468, 3461, 3470, 3458, 3471, 3472, 86, 3462, 86, 3473, - 3465, 3475, 86, 3466, 86, 3464, 3476, 3477, 86, 3474, - 86, 3497, 3478, 3777, 3551, 3467, 86, 3468, 3479, 86, - 86, 3471, 3472, 3480, 86, 3481, 3482, 3483, 3475, 86, - 86, 86, 86, 86, 3477, 86, 3474, 3484, 3485, 3478, - 86, 3486, 86, 86, 3487, 3479, 86, 3489, 86, 86, - 3480, 86, 3481, 3482, 3483, 3488, 86, 86, 86, 3490, - 3777, 3494, 86, 3493, 3484, 3485, 3491, 3492, 3486, 86, - 86, 3487, 3496, 3495, 3489, 3498, 86, 3499, 3777, 86, - - 3502, 3500, 3488, 86, 86, 3503, 3490, 3501, 3494, 3506, - 3493, 3505, 3504, 3491, 3492, 86, 3509, 86, 3507, 3496, - 3495, 86, 3498, 86, 3499, 86, 3511, 86, 3500, 3508, - 3510, 3516, 86, 3520, 3501, 86, 86, 86, 3505, 3504, - 86, 3519, 86, 86, 3521, 3507, 3512, 3513, 3514, 3515, - 3517, 3518, 3777, 86, 3522, 86, 3508, 3510, 86, 3524, - 3520, 3523, 86, 3525, 86, 3526, 3527, 3528, 3519, 3530, - 86, 3521, 86, 86, 86, 86, 3529, 86, 3531, 86, - 3534, 86, 3532, 3533, 3536, 86, 3524, 86, 3523, 86, - 86, 86, 3526, 3527, 3528, 3535, 86, 3538, 86, 3539, - - 86, 3537, 86, 3529, 3540, 3531, 86, 3534, 3542, 3532, - 3533, 3536, 3541, 86, 3543, 3544, 3546, 3545, 86, 3777, - 3549, 86, 3535, 3559, 3538, 3550, 3539, 3777, 3537, 86, - 86, 86, 3555, 3547, 86, 3542, 3548, 3553, 86, 3541, - 3554, 86, 86, 3546, 3545, 3552, 86, 86, 3556, 86, - 3557, 86, 86, 3558, 86, 86, 3561, 3560, 86, 3555, - 3547, 3562, 3563, 3548, 3553, 3564, 3565, 3554, 3566, 3567, - 86, 3570, 3552, 3568, 86, 3556, 3569, 3557, 86, 3571, - 86, 86, 3572, 86, 3560, 86, 3573, 86, 86, 3563, - 3574, 86, 3564, 86, 3575, 3566, 86, 3576, 86, 3577, - - 3568, 3578, 86, 3569, 3579, 3580, 86, 3581, 3583, 86, - 3586, 3582, 3584, 86, 3588, 3585, 3593, 86, 3589, 86, - 3592, 86, 86, 86, 86, 3587, 86, 86, 3578, 86, - 86, 3579, 86, 86, 86, 3583, 3590, 86, 3582, 3584, - 3591, 86, 3585, 86, 3594, 3589, 86, 3592, 3595, 3596, - 86, 3777, 3587, 3597, 3601, 86, 86, 3599, 86, 3598, - 86, 3600, 3602, 3590, 3605, 3604, 3603, 3591, 3608, 3777, - 86, 3594, 86, 3606, 3607, 86, 3596, 86, 86, 86, - 3597, 3601, 86, 86, 3599, 86, 3598, 86, 3600, 86, - 3609, 3605, 3604, 3603, 86, 3608, 3610, 3611, 3777, 3612, - - 3606, 3607, 3613, 86, 3614, 3615, 3616, 3617, 86, 86, - 3618, 86, 3619, 3620, 3621, 3624, 3622, 3609, 3623, 86, - 86, 86, 3646, 3610, 3611, 86, 3612, 86, 3625, 3613, - 86, 3614, 3615, 3616, 3617, 86, 86, 86, 86, 86, - 86, 86, 3624, 3622, 3626, 3623, 3627, 3628, 3629, 86, - 86, 3630, 3631, 3777, 3632, 3625, 3635, 86, 3633, 3634, - 3637, 3777, 86, 86, 86, 86, 3636, 86, 3641, 3651, - 86, 3626, 86, 3627, 3628, 3629, 86, 86, 3630, 3631, - 86, 3632, 3638, 3635, 3639, 3633, 3634, 3637, 3640, 3643, - 86, 3642, 3644, 3636, 86, 3641, 86, 86, 3645, 3648, - - 3647, 3650, 86, 86, 86, 3653, 86, 86, 86, 3638, - 3649, 3639, 3652, 3655, 86, 3640, 3643, 3654, 3642, 3644, - 3656, 86, 3658, 86, 3659, 3645, 3648, 3647, 3650, 86, - 86, 3660, 86, 3657, 3661, 3664, 3662, 3649, 86, 3652, - 86, 86, 3663, 86, 3654, 3668, 3665, 86, 86, 3658, - 3666, 3659, 3667, 86, 86, 3669, 86, 3670, 3660, 86, - 3657, 3661, 86, 3662, 3671, 86, 3672, 86, 3673, 3663, - 3675, 3674, 86, 3665, 86, 3676, 3677, 3666, 86, 3667, - 3678, 3679, 3669, 86, 86, 3680, 3681, 3686, 86, 86, - 3683, 86, 3682, 86, 3684, 86, 3685, 3675, 3674, 3777, - - 86, 86, 86, 3677, 3689, 86, 3688, 3678, 86, 86, - 3687, 86, 3680, 3681, 3686, 3690, 3693, 3692, 86, 3682, - 3777, 3691, 86, 3685, 86, 3695, 86, 86, 86, 86, - 3694, 86, 86, 3688, 3696, 3698, 3699, 3687, 3697, 3700, - 3777, 3703, 86, 3693, 3692, 3701, 86, 86, 3691, 86, - 86, 3702, 3695, 86, 3707, 3777, 86, 3694, 3708, 3777, - 3705, 3696, 3698, 3699, 3704, 3697, 3700, 86, 86, 86, - 3709, 86, 3701, 86, 3706, 3715, 3777, 3710, 3702, 3777, - 86, 86, 86, 3711, 3712, 3708, 3713, 3705, 3714, 3716, - 3717, 3704, 3718, 3724, 3721, 3719, 86, 3777, 3777, 3777, - - 3777, 3706, 86, 86, 3710, 86, 86, 86, 86, 3727, - 3711, 3712, 86, 3713, 86, 3714, 86, 3717, 86, 86, - 3720, 3721, 3719, 3722, 3723, 86, 3725, 3726, 86, 3728, - 3729, 86, 86, 3730, 86, 86, 3727, 3731, 3732, 3777, - 3735, 86, 3738, 86, 3733, 3777, 86, 3720, 86, 3734, - 3722, 3723, 86, 3725, 3726, 3736, 86, 3729, 3737, 86, - 3730, 3739, 3740, 86, 3731, 3732, 86, 3735, 3741, 3738, - 86, 3733, 86, 3742, 3743, 3745, 3734, 86, 3744, 3746, - 3749, 3747, 3736, 86, 3748, 3737, 3777, 86, 3739, 3740, - 3750, 3755, 3751, 3753, 86, 3741, 86, 3777, 86, 86, - - 3742, 3743, 3745, 86, 3757, 3744, 86, 86, 3747, 86, - 86, 3748, 86, 3752, 3754, 86, 3756, 3750, 86, 3751, - 3753, 86, 86, 3758, 86, 3759, 86, 3760, 3777, 3761, - 3762, 3757, 3765, 86, 3763, 86, 3764, 3766, 3768, 3777, - 3752, 3754, 86, 3756, 86, 86, 3767, 3769, 3770, 3771, - 3758, 3775, 3759, 3776, 3760, 86, 3761, 86, 86, 3765, - 3772, 3763, 3773, 3764, 86, 86, 86, 3777, 86, 3774, - 86, 86, 3777, 3767, 86, 3770, 3771, 86, 86, 3777, - 86, 3777, 86, 3777, 3777, 3777, 3777, 3772, 3777, 3773, - 3777, 3777, 3777, 3777, 3777, 3777, 3774, 47, 47, 47, - - 47, 47, 47, 47, 52, 52, 52, 52, 52, 52, - 52, 57, 57, 57, 57, 57, 57, 57, 63, 63, - 63, 63, 63, 63, 63, 68, 68, 68, 68, 68, - 68, 68, 74, 74, 74, 74, 74, 74, 74, 80, - 80, 80, 80, 80, 80, 80, 89, 89, 3777, 89, - 89, 89, 89, 161, 161, 3777, 3777, 3777, 161, 161, - 163, 163, 3777, 3777, 163, 3777, 163, 165, 3777, 3777, - 3777, 3777, 3777, 165, 168, 168, 3777, 3777, 3777, 168, - 168, 170, 3777, 3777, 3777, 3777, 3777, 170, 172, 172, - 3777, 172, 172, 172, 172, 175, 3777, 3777, 3777, 3777, - - 3777, 175, 178, 178, 3777, 3777, 3777, 178, 178, 90, - 90, 3777, 90, 90, 90, 90, 17, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777 - } ; - -static const flex_int16_t yy_chk[10784] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 3, 3, 4, - 4, 4, 5, 5, 6, 6, 5, 32, 6, 7, - 7, 7, 7, 33, 7, 8, 8, 8, 8, 32, - 8, 9, 9, 9, 10, 10, 10, 19, 51, 51, - - 3785, 19, 233, 3, 32, 33, 4, 67, 67, 5, - 33, 6, 3065, 13, 13, 13, 13, 7, 13, 14, - 14, 14, 14, 8, 14, 15, 15, 15, 9, 25, - 233, 10, 11, 11, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 16, 16, 16, 34, 28, 84, - 84, 13, 11, 45, 1192, 25, 25, 14, 12, 34, - 39, 23, 15, 23, 23, 45, 23, 178, 28, 602, - 11, 28, 23, 39, 34, 28, 12, 302, 87, 11, - 45, 16, 87, 162, 162, 12, 30, 39, 29, 177, - 56, 175, 37, 56, 30, 28, 26, 602, 37, 23, - - 24, 24, 29, 26, 24, 30, 302, 26, 100, 24, - 26, 24, 30, 30, 29, 29, 92, 100, 24, 37, - 72, 30, 26, 26, 24, 169, 169, 24, 24, 29, - 26, 24, 30, 72, 26, 100, 24, 26, 24, 62, - 92, 62, 62, 92, 62, 24, 27, 72, 31, 170, - 27, 31, 94, 27, 95, 27, 27, 198, 31, 46, - 31, 46, 46, 223, 46, 226, 27, 168, 27, 95, - 46, 31, 94, 27, 167, 31, 35, 27, 31, 94, - 27, 95, 27, 27, 35, 31, 93, 31, 36, 198, - 35, 97, 36, 27, 35, 223, 44, 226, 97, 42, - - 44, 42, 35, 35, 44, 98, 36, 165, 36, 93, - 42, 35, 163, 93, 36, 36, 42, 35, 97, 36, - 161, 35, 44, 44, 43, 42, 42, 44, 42, 98, - 351, 44, 98, 36, 43, 36, 38, 42, 43, 43, - 38, 96, 164, 42, 38, 164, 85, 43, 80, 96, - 38, 43, 70, 38, 70, 70, 101, 70, 138, 351, - 38, 43, 38, 38, 105, 43, 43, 38, 96, 105, - 73, 38, 73, 73, 101, 73, 79, 38, 79, 79, - 38, 79, 75, 101, 138, 138, 99, 38, 40, 106, - 70, 105, 40, 86, 108, 86, 86, 106, 86, 99, - - 126, 150, 40, 40, 86, 40, 89, 108, 89, 89, - 99, 89, 150, 99, 40, 40, 106, 89, 74, 40, - 126, 108, 102, 102, 107, 228, 99, 126, 150, 40, - 40, 103, 40, 41, 110, 102, 41, 103, 117, 103, - 68, 110, 107, 41, 89, 104, 104, 41, 41, 102, - 102, 117, 103, 112, 104, 41, 107, 228, 103, 109, - 41, 110, 112, 41, 103, 117, 103, 114, 109, 107, - 41, 116, 104, 104, 41, 41, 111, 111, 113, 125, - 112, 109, 115, 119, 111, 1018, 109, 113, 63, 115, - 114, 58, 111, 116, 114, 109, 118, 121, 116, 118, - - 120, 124, 125, 111, 111, 113, 125, 119, 120, 115, - 57, 111, 118, 118, 124, 119, 1018, 121, 122, 121, - 118, 128, 122, 118, 121, 123, 118, 120, 124, 127, - 123, 132, 129, 123, 119, 52, 127, 130, 122, 118, - 118, 128, 122, 127, 121, 122, 131, 134, 128, 122, - 129, 130, 123, 131, 132, 47, 127, 123, 132, 129, - 133, 1180, 135, 127, 130, 122, 18, 141, 136, 133, - 134, 135, 136, 131, 134, 137, 139, 140, 136, 141, - 142, 142, 137, 139, 145, 143, 140, 133, 146, 135, - 136, 1180, 140, 143, 141, 136, 146, 153, 145, 136, - - 140, 147, 137, 139, 140, 136, 144, 142, 153, 148, - 151, 145, 143, 140, 149, 17, 147, 144, 151, 140, - 146, 144, 154, 146, 153, 149, 148, 155, 147, 148, - 144, 154, 152, 144, 149, 148, 148, 151, 152, 156, - 157, 149, 155, 154, 144, 0, 159, 154, 144, 154, - 160, 158, 149, 148, 155, 157, 148, 0, 154, 152, - 158, 156, 0, 160, 0, 174, 156, 157, 159, 166, - 154, 166, 166, 159, 166, 179, 179, 160, 158, 171, - 180, 171, 171, 172, 171, 172, 172, 181, 172, 174, - 182, 176, 174, 176, 176, 0, 176, 183, 186, 182, - - 184, 181, 180, 185, 184, 188, 189, 180, 191, 183, - 185, 0, 187, 188, 186, 191, 190, 182, 189, 181, - 192, 172, 185, 193, 183, 186, 196, 184, 181, 197, - 185, 187, 188, 189, 194, 191, 192, 185, 190, 187, - 194, 193, 195, 190, 195, 201, 202, 192, 196, 212, - 193, 204, 203, 196, 199, 197, 197, 203, 199, 204, - 212, 202, 207, 208, 205, 206, 194, 194, 209, 195, - 208, 201, 201, 202, 210, 199, 212, 207, 204, 0, - 213, 0, 199, 211, 203, 199, 205, 206, 0, 207, - 208, 205, 206, 213, 214, 216, 209, 210, 0, 231, - - 209, 210, 199, 200, 216, 211, 214, 213, 200, 215, - 211, 217, 215, 200, 0, 218, 0, 222, 221, 200, - 200, 214, 216, 209, 215, 221, 200, 220, 222, 224, - 200, 231, 225, 217, 227, 200, 215, 218, 217, 215, - 200, 227, 218, 225, 222, 221, 200, 200, 219, 220, - 232, 219, 229, 219, 220, 224, 224, 0, 234, 235, - 0, 227, 230, 236, 225, 219, 229, 219, 230, 238, - 225, 237, 232, 239, 219, 219, 237, 232, 219, 0, - 219, 240, 235, 0, 229, 242, 235, 239, 244, 230, - 234, 244, 219, 229, 219, 236, 237, 241, 237, 245, - - 239, 238, 240, 237, 241, 243, 242, 246, 240, 247, - 248, 249, 242, 251, 243, 244, 250, 252, 245, 243, - 251, 246, 252, 249, 241, 253, 245, 250, 248, 257, - 254, 247, 243, 255, 246, 260, 247, 248, 249, 254, - 251, 243, 259, 250, 261, 256, 262, 253, 0, 252, - 256, 261, 253, 258, 258, 264, 255, 254, 259, 263, - 255, 257, 258, 264, 266, 265, 267, 260, 262, 259, - 268, 261, 256, 262, 269, 270, 271, 273, 268, 0, - 258, 258, 264, 272, 263, 265, 263, 275, 274, 271, - 270, 276, 265, 0, 0, 277, 266, 268, 267, 277, - - 279, 278, 270, 271, 273, 280, 269, 281, 276, 272, - 272, 274, 0, 280, 282, 279, 276, 283, 276, 275, - 274, 282, 277, 278, 285, 284, 281, 279, 278, 284, - 286, 287, 280, 288, 281, 276, 290, 289, 274, 283, - 292, 282, 291, 294, 283, 295, 285, 293, 297, 298, - 297, 285, 284, 292, 291, 288, 293, 296, 295, 289, - 288, 294, 286, 287, 289, 299, 300, 292, 290, 291, - 294, 301, 295, 303, 293, 297, 296, 304, 0, 305, - 312, 298, 303, 306, 296, 307, 309, 0, 312, 299, - 308, 300, 299, 300, 306, 314, 0, 301, 301, 307, - - 303, 310, 311, 304, 304, 305, 305, 312, 315, 309, - 306, 307, 307, 309, 308, 316, 317, 308, 318, 310, - 311, 315, 319, 322, 323, 320, 307, 314, 310, 311, - 324, 321, 326, 325, 0, 315, 328, 324, 326, 319, - 327, 317, 325, 317, 329, 319, 331, 316, 323, 319, - 318, 320, 320, 321, 327, 322, 323, 324, 321, 326, - 325, 330, 328, 328, 332, 333, 319, 327, 329, 331, - 330, 329, 332, 331, 333, 323, 334, 335, 338, 337, - 340, 336, 0, 0, 0, 339, 335, 343, 330, 346, - 353, 332, 333, 342, 337, 340, 343, 344, 336, 0, - - 0, 347, 334, 334, 335, 336, 337, 340, 336, 339, - 338, 342, 339, 346, 343, 347, 346, 353, 348, 344, - 342, 349, 349, 352, 344, 336, 341, 350, 347, 341, - 355, 356, 350, 348, 341, 341, 341, 341, 0, 371, - 0, 0, 355, 356, 341, 348, 349, 352, 349, 349, - 352, 0, 376, 341, 0, 0, 341, 355, 356, 350, - 358, 341, 341, 341, 341, 345, 354, 345, 359, 354, - 360, 371, 357, 357, 0, 362, 354, 363, 358, 345, - 345, 345, 357, 345, 376, 0, 359, 358, 381, 345, - 361, 369, 345, 354, 345, 359, 354, 360, 369, 357, - - 357, 362, 362, 363, 363, 366, 345, 345, 345, 364, - 345, 364, 361, 365, 367, 368, 370, 361, 369, 372, - 381, 372, 375, 368, 374, 365, 385, 366, 370, 367, - 372, 374, 366, 377, 0, 384, 364, 372, 383, 386, - 365, 367, 368, 370, 375, 372, 372, 378, 372, 375, - 380, 374, 379, 378, 379, 377, 383, 372, 385, 408, - 377, 384, 384, 380, 372, 383, 386, 0, 387, 378, - 382, 390, 421, 392, 378, 391, 379, 380, 390, 379, - 378, 379, 411, 382, 393, 392, 382, 0, 382, 411, - 387, 408, 394, 391, 382, 387, 393, 382, 390, 391, - - 392, 0, 391, 0, 421, 394, 0, 396, 397, 411, - 382, 393, 400, 382, 399, 382, 388, 401, 388, 394, - 391, 397, 401, 396, 388, 402, 399, 463, 388, 404, - 400, 396, 402, 388, 396, 397, 388, 404, 403, 400, - 407, 399, 388, 388, 403, 388, 402, 0, 407, 401, - 396, 388, 402, 406, 463, 388, 404, 0, 405, 402, - 388, 410, 410, 388, 389, 403, 389, 407, 409, 0, - 405, 406, 413, 488, 412, 418, 414, 409, 488, 389, - 406, 413, 389, 797, 389, 405, 389, 412, 410, 415, - 389, 389, 416, 389, 414, 409, 415, 418, 414, 416, - - 488, 412, 418, 414, 413, 417, 389, 419, 413, 389, - 420, 389, 797, 389, 398, 398, 415, 417, 422, 416, - 424, 414, 420, 423, 398, 398, 398, 398, 398, 419, - 423, 398, 417, 425, 419, 424, 426, 420, 427, 398, - 427, 398, 398, 0, 422, 422, 425, 424, 428, 429, - 423, 398, 398, 398, 398, 398, 430, 430, 398, 428, - 425, 433, 431, 432, 437, 427, 434, 435, 426, 431, - 432, 429, 433, 436, 439, 428, 429, 434, 438, 438, - 435, 0, 441, 0, 440, 430, 437, 442, 433, 431, - 432, 437, 443, 434, 435, 442, 438, 439, 436, 440, - - 436, 439, 444, 438, 443, 438, 438, 440, 441, 441, - 451, 440, 445, 444, 442, 446, 449, 450, 452, 443, - 462, 445, 453, 438, 447, 447, 440, 454, 446, 444, - 457, 458, 451, 456, 462, 450, 447, 451, 447, 445, - 453, 452, 446, 447, 450, 452, 459, 462, 449, 453, - 455, 447, 447, 457, 456, 458, 455, 457, 458, 454, - 456, 0, 460, 447, 461, 447, 448, 465, 459, 460, - 464, 467, 466, 459, 448, 448, 0, 455, 448, 448, - 0, 465, 448, 469, 468, 0, 0, 0, 448, 460, - 461, 461, 464, 448, 465, 469, 471, 464, 466, 466, - - 472, 448, 448, 467, 473, 448, 448, 468, 470, 448, - 469, 468, 473, 474, 470, 480, 476, 475, 471, 477, - 479, 478, 472, 471, 475, 476, 479, 472, 474, 481, - 473, 473, 482, 0, 477, 470, 484, 480, 483, 473, - 474, 487, 480, 476, 475, 478, 477, 479, 478, 485, - 490, 481, 486, 483, 491, 482, 481, 0, 486, 482, - 493, 0, 484, 484, 494, 483, 493, 487, 487, 495, - 496, 485, 497, 498, 500, 495, 485, 499, 497, 486, - 491, 491, 490, 494, 499, 505, 507, 493, 496, 500, - 509, 494, 508, 503, 506, 498, 495, 496, 511, 497, - - 498, 500, 503, 502, 499, 502, 504, 506, 517, 510, - 508, 511, 502, 504, 513, 0, 514, 505, 507, 508, - 503, 506, 509, 512, 519, 511, 512, 515, 516, 514, - 502, 510, 502, 504, 520, 0, 510, 518, 513, 515, - 517, 513, 512, 514, 518, 521, 516, 522, 519, 527, - 512, 519, 525, 512, 515, 516, 523, 520, 521, 524, - 526, 523, 530, 529, 518, 524, 520, 532, 528, 522, - 526, 527, 521, 530, 522, 525, 527, 0, 538, 525, - 528, 532, 572, 523, 520, 529, 524, 526, 531, 530, - 529, 535, 537, 536, 532, 528, 531, 0, 535, 536, - - 539, 538, 0, 540, 537, 538, 541, 0, 539, 542, - 0, 555, 544, 555, 572, 531, 533, 541, 535, 537, - 536, 533, 543, 533, 544, 540, 543, 539, 0, 533, - 540, 533, 542, 541, 533, 533, 542, 545, 555, 544, - 550, 533, 533, 533, 543, 551, 0, 547, 533, 543, - 533, 550, 546, 543, 549, 546, 533, 545, 533, 545, - 548, 533, 533, 546, 545, 547, 549, 550, 533, 551, - 548, 552, 551, 553, 547, 552, 554, 0, 556, 546, - 553, 549, 546, 557, 545, 560, 558, 559, 561, 562, - 564, 0, 548, 577, 562, 557, 561, 548, 552, 559, - - 553, 558, 554, 554, 556, 556, 563, 566, 564, 567, - 557, 560, 560, 558, 559, 561, 562, 564, 565, 566, - 569, 570, 573, 571, 575, 577, 565, 574, 563, 576, - 567, 578, 575, 563, 566, 582, 567, 573, 569, 574, - 580, 581, 576, 578, 570, 565, 571, 569, 570, 573, - 571, 575, 579, 584, 574, 581, 576, 585, 578, 586, - 582, 579, 582, 580, 588, 591, 583, 580, 581, 583, - 587, 589, 584, 590, 592, 597, 598, 594, 593, 579, - 584, 598, 595, 603, 585, 587, 597, 592, 590, 591, - 593, 586, 591, 583, 600, 601, 588, 587, 606, 594, - - 590, 592, 597, 589, 594, 593, 595, 596, 598, 595, - 599, 604, 605, 607, 596, 603, 610, 596, 607, 608, - 609, 600, 601, 614, 599, 596, 609, 611, 608, 615, - 606, 610, 613, 612, 596, 616, 620, 599, 604, 605, - 613, 596, 614, 610, 596, 607, 608, 609, 617, 619, - 614, 611, 617, 615, 611, 612, 615, 616, 618, 613, - 612, 622, 616, 621, 623, 624, 618, 625, 620, 626, - 621, 627, 619, 623, 630, 617, 619, 0, 629, 633, - 625, 634, 630, 627, 622, 618, 631, 624, 622, 0, - 621, 623, 624, 628, 625, 626, 626, 631, 627, 628, - - 629, 630, 632, 634, 635, 629, 638, 0, 634, 632, - 636, 633, 637, 631, 639, 636, 640, 635, 636, 636, - 628, 637, 641, 639, 644, 642, 646, 640, 0, 632, - 648, 635, 638, 638, 636, 643, 644, 636, 647, 637, - 651, 639, 636, 640, 641, 636, 636, 642, 643, 641, - 649, 644, 642, 650, 648, 653, 647, 648, 646, 652, - 654, 658, 643, 655, 651, 647, 653, 651, 658, 654, - 656, 657, 649, 649, 659, 650, 660, 649, 664, 668, - 650, 652, 653, 655, 656, 662, 652, 654, 658, 663, - 655, 664, 661, 657, 660, 663, 666, 656, 657, 649, - - 661, 659, 665, 660, 669, 664, 667, 662, 670, 671, - 671, 668, 662, 665, 666, 672, 663, 673, 674, 661, - 680, 667, 0, 666, 676, 669, 672, 675, 678, 665, - 677, 669, 670, 667, 681, 670, 675, 676, 671, 679, - 674, 673, 672, 677, 673, 674, 682, 679, 683, 685, - 678, 676, 680, 686, 675, 678, 681, 677, 684, 688, - 684, 681, 687, 689, 686, 691, 679, 687, 700, 690, - 0, 685, 683, 688, 692, 683, 685, 689, 682, 696, - 686, 693, 692, 690, 690, 684, 688, 694, 695, 701, - 689, 690, 697, 698, 687, 695, 690, 691, 703, 693, - - 700, 692, 699, 703, 701, 696, 696, 704, 693, 694, - 690, 690, 697, 698, 694, 695, 701, 699, 702, 697, - 698, 705, 706, 705, 707, 708, 699, 710, 702, 699, - 703, 709, 707, 704, 704, 0, 710, 709, 715, 714, - 702, 716, 717, 0, 699, 702, 714, 706, 705, 706, - 708, 707, 708, 711, 710, 702, 712, 0, 709, 713, - 717, 718, 711, 719, 716, 712, 714, 713, 716, 717, - 715, 721, 720, 718, 724, 719, 722, 723, 727, 721, - 711, 720, 726, 712, 725, 722, 713, 731, 718, 723, - 719, 725, 0, 727, 728, 726, 0, 0, 721, 720, - - 722, 729, 728, 722, 723, 727, 724, 729, 730, 726, - 731, 725, 722, 732, 731, 733, 730, 736, 734, 738, - 739, 728, 732, 735, 735, 736, 733, 734, 729, 737, - 0, 740, 735, 739, 0, 730, 741, 737, 744, 742, - 732, 738, 733, 0, 736, 734, 738, 739, 746, 745, - 735, 735, 742, 743, 744, 749, 737, 740, 740, 741, - 747, 743, 745, 741, 748, 744, 742, 751, 750, 749, - 746, 747, 748, 752, 753, 746, 745, 753, 0, 758, - 743, 754, 749, 755, 757, 759, 762, 747, 750, 751, - 756, 748, 761, 752, 751, 750, 760, 758, 759, 756, - - 752, 753, 763, 754, 757, 755, 758, 761, 754, 764, - 755, 757, 759, 766, 760, 765, 767, 756, 762, 761, - 768, 769, 770, 760, 763, 771, 766, 772, 774, 763, - 779, 771, 768, 764, 767, 770, 764, 775, 765, 776, - 766, 0, 765, 767, 781, 769, 782, 768, 769, 770, - 773, 781, 771, 778, 772, 774, 786, 776, 773, 775, - 780, 778, 779, 783, 775, 784, 776, 784, 780, 782, - 785, 781, 787, 782, 788, 789, 773, 773, 783, 785, - 778, 790, 791, 790, 789, 773, 815, 780, 786, 791, - 783, 787, 784, 0, 788, 794, 798, 785, 801, 787, - - 0, 788, 789, 0, 807, 802, 798, 794, 790, 791, - 792, 806, 805, 792, 804, 807, 801, 792, 815, 804, - 792, 839, 794, 798, 809, 801, 802, 792, 792, 806, - 792, 807, 802, 805, 810, 792, 808, 792, 806, 805, - 792, 804, 811, 812, 792, 818, 814, 792, 839, 813, - 809, 809, 812, 814, 792, 792, 0, 792, 811, 808, - 810, 810, 813, 808, 817, 820, 821, 818, 854, 811, - 812, 817, 818, 814, 820, 819, 813, 816, 816, 822, - 816, 819, 822, 816, 0, 823, 0, 824, 816, 821, - 825, 817, 820, 821, 816, 816, 826, 816, 825, 827, - - 854, 823, 819, 816, 816, 816, 822, 816, 823, 824, - 816, 827, 823, 829, 824, 816, 831, 825, 826, 832, - 833, 816, 816, 826, 816, 828, 827, 828, 823, 830, - 835, 834, 833, 836, 830, 837, 831, 829, 0, 840, - 829, 838, 0, 831, 844, 832, 832, 833, 0, 843, - 841, 844, 828, 834, 846, 836, 835, 835, 834, 837, - 836, 830, 837, 838, 840, 841, 840, 842, 838, 847, - 845, 844, 843, 846, 848, 842, 843, 841, 845, 849, - 851, 846, 850, 852, 856, 853, 848, 860, 857, 851, - 853, 855, 849, 857, 842, 847, 847, 845, 852, 859, - - 865, 848, 864, 866, 867, 861, 849, 851, 850, 850, - 852, 856, 853, 855, 861, 862, 868, 863, 855, 860, - 857, 859, 865, 862, 863, 870, 859, 865, 867, 869, - 871, 867, 861, 875, 864, 866, 872, 868, 874, 873, - 879, 876, 862, 868, 863, 872, 880, 874, 869, 877, - 878, 879, 870, 881, 880, 875, 869, 871, 873, 878, - 875, 882, 883, 872, 876, 874, 873, 879, 876, 877, - 884, 885, 889, 880, 886, 890, 877, 878, 887, 882, - 881, 883, 891, 886, 892, 891, 887, 896, 882, 883, - 889, 894, 893, 890, 895, 898, 897, 884, 897, 889, - - 896, 886, 890, 885, 901, 887, 892, 902, 0, 891, - 893, 892, 899, 898, 896, 894, 895, 901, 894, 893, - 900, 895, 898, 897, 903, 900, 899, 904, 905, 906, - 911, 901, 906, 902, 902, 904, 903, 908, 907, 899, - 913, 910, 912, 914, 0, 908, 905, 907, 912, 914, - 0, 903, 900, 915, 904, 905, 906, 911, 918, 920, - 925, 908, 913, 918, 908, 907, 910, 913, 910, 912, - 914, 916, 908, 922, 917, 915, 919, 920, 916, 924, - 915, 917, 923, 919, 921, 918, 920, 924, 921, 926, - 927, 923, 925, 928, 929, 930, 922, 931, 916, 933, - - 922, 917, 929, 919, 928, 927, 924, 926, 930, 923, - 932, 921, 933, 934, 935, 936, 926, 927, 931, 0, - 928, 929, 930, 936, 931, 937, 933, 938, 940, 932, - 946, 939, 937, 947, 942, 934, 941, 932, 939, 942, - 934, 935, 936, 941, 944, 938, 945, 940, 943, 949, - 952, 944, 937, 945, 938, 940, 943, 948, 939, 950, - 951, 942, 946, 941, 953, 947, 954, 951, 955, 0, - 948, 944, 950, 945, 958, 943, 955, 956, 957, 960, - 958, 949, 952, 959, 948, 956, 950, 951, 961, 954, - 962, 965, 956, 954, 963, 955, 953, 967, 968, 964, - - 957, 958, 0, 963, 956, 957, 969, 968, 966, 959, - 959, 960, 956, 964, 962, 966, 970, 962, 972, 973, - 961, 963, 971, 965, 967, 968, 964, 971, 969, 970, - 972, 970, 975, 969, 974, 966, 981, 975, 977, 981, - 970, 976, 973, 970, 978, 972, 973, 979, 976, 982, - 977, 988, 0, 984, 971, 979, 970, 985, 970, 975, - 974, 974, 982, 981, 985, 977, 978, 984, 976, 986, - 1015, 978, 0, 988, 979, 986, 982, 990, 988, 991, - 984, 989, 992, 0, 985, 993, 0, 993, 999, 995, - 994, 991, 997, 999, 0, 0, 986, 987, 996, 987, - - 990, 995, 1015, 987, 990, 987, 991, 989, 989, 992, - 987, 996, 993, 994, 997, 987, 995, 994, 998, 997, - 999, 987, 1000, 1001, 987, 996, 987, 1003, 0, 1002, - 987, 998, 987, 1004, 1007, 1006, 1001, 987, 1005, 1003, - 1000, 1002, 987, 1004, 1008, 998, 1010, 1007, 1011, 1000, - 1001, 1013, 1002, 1005, 1003, 1004, 1002, 1006, 1009, 1010, - 1004, 1007, 1006, 1016, 1009, 1005, 1011, 1012, 1002, 1014, - 1004, 1008, 1013, 1010, 1017, 1011, 1019, 1020, 1013, 1021, - 1025, 0, 1020, 1022, 0, 1009, 1026, 1021, 1024, 1012, - 1027, 1014, 1022, 1028, 1012, 1016, 1014, 0, 1032, 1026, - - 1029, 1017, 1025, 1024, 1020, 1027, 1021, 1025, 1019, 1032, - 1022, 1023, 1030, 1026, 1037, 1024, 1023, 1027, 1023, 1028, - 1028, 1031, 1029, 0, 1023, 1032, 1040, 1029, 1033, 1023, - 1023, 1030, 1034, 1036, 1031, 1040, 1023, 1023, 1023, 1030, - 1034, 1033, 1035, 1023, 1036, 1023, 1037, 1039, 1031, 1038, - 1035, 1023, 1042, 1040, 1041, 1033, 1023, 1023, 1043, 1034, - 1036, 1042, 1039, 1023, 1044, 1041, 1045, 1043, 1046, 1035, - 1048, 1038, 1049, 1052, 1039, 1046, 1038, 0, 1050, 1042, - 1053, 1041, 1051, 1057, 1054, 1043, 1050, 1052, 1060, 1045, - 1055, 1044, 1059, 1045, 0, 1046, 1049, 1058, 1055, 1049, - - 1052, 1057, 1048, 1059, 1051, 1050, 1054, 1061, 1062, 1051, - 1057, 1054, 1053, 1065, 1063, 1058, 1062, 1055, 1067, 1059, - 1060, 1064, 1066, 0, 1058, 1061, 1065, 1074, 1064, 1066, - 1070, 1072, 1068, 1067, 1061, 1062, 1063, 1069, 1074, 1077, - 1065, 1063, 1071, 1076, 1080, 1067, 1077, 0, 1064, 1066, - 1068, 1070, 1071, 1079, 1074, 1069, 1076, 1070, 1078, 1068, - 1078, 1082, 1083, 1072, 1069, 1081, 1077, 1084, 1085, 1071, - 1076, 1083, 0, 1081, 1082, 1079, 1080, 1086, 1089, 1084, - 1079, 1090, 1093, 1091, 1094, 1078, 1092, 0, 1082, 1083, - 1085, 1095, 1081, 1100, 1084, 1085, 0, 1097, 1100, 1086, - - 1089, 1091, 1104, 1090, 1086, 1089, 1099, 1096, 1090, 1095, - 1091, 1097, 1092, 1092, 1093, 1103, 1094, 1099, 1095, 1096, - 1102, 1106, 1105, 1102, 1097, 1100, 1104, 1103, 1106, 1104, - 1107, 1108, 1110, 1099, 1096, 1105, 1111, 1109, 1112, 1113, - 1108, 1107, 1103, 1114, 1110, 1112, 1102, 1102, 1106, 1105, - 1102, 1109, 1115, 1116, 1119, 1114, 1118, 1107, 1108, 1110, - 0, 1120, 1121, 1122, 1109, 1112, 1116, 1120, 1111, 1124, - 1114, 1113, 1125, 1126, 1115, 1123, 1127, 1129, 1119, 1115, - 1116, 1119, 1118, 1118, 1121, 1122, 1123, 1124, 1120, 1121, - 1122, 1127, 1131, 1133, 1125, 1126, 1124, 1130, 1129, 1125, - - 1126, 1132, 1123, 1127, 1129, 1134, 1136, 1132, 1130, 1135, - 1137, 0, 1138, 1131, 1139, 1136, 1142, 1143, 1140, 1131, - 1144, 1145, 1141, 1139, 1130, 1133, 1140, 1135, 1132, 1141, - 1146, 1143, 1134, 1136, 1137, 1149, 1135, 1137, 1138, 1138, - 1142, 1139, 1147, 1142, 1143, 1140, 1148, 1151, 1150, 1141, - 1153, 1154, 1144, 1145, 1155, 1156, 1158, 0, 1157, 0, - 1154, 1155, 1146, 0, 1147, 1171, 1159, 1149, 1148, 1147, - 1150, 1160, 1153, 1148, 1161, 1150, 1164, 1153, 1154, 1151, - 1157, 1155, 1162, 1158, 1159, 1157, 1163, 1156, 1165, 1160, - 1166, 1162, 1167, 1159, 1163, 1168, 1161, 1171, 1160, 1170, - - 1164, 1161, 1172, 1164, 1168, 1169, 1166, 1170, 1174, 1162, - 1175, 1173, 1165, 1163, 1167, 1165, 1176, 1166, 1177, 1167, - 1169, 1178, 1168, 1173, 1176, 1184, 1170, 1184, 1182, 1187, - 1174, 1177, 1169, 1179, 1172, 1174, 1178, 1175, 1173, 1183, - 1181, 1197, 1179, 1176, 1188, 1177, 1182, 1183, 1178, 1181, - 1186, 1189, 1184, 1190, 1191, 1182, 1187, 1193, 1186, 1197, - 1179, 1191, 1194, 1188, 1195, 1196, 1183, 1181, 1197, 1199, - 1193, 1188, 1201, 1189, 1194, 1190, 1198, 1186, 1189, 1195, - 1190, 1191, 1202, 1200, 1193, 1204, 1203, 1196, 1198, 1194, - 1200, 1195, 1196, 1205, 1206, 1207, 1199, 1203, 1208, 0, - - 0, 1209, 1212, 1198, 1201, 1210, 1217, 1204, 1207, 0, - 1200, 1208, 1204, 1203, 1202, 1213, 1206, 1210, 1205, 1211, - 1205, 1206, 1207, 1209, 1214, 1208, 1212, 1211, 1209, 1212, - 1215, 1218, 1210, 1217, 1219, 1213, 1214, 1220, 1215, 1221, - 1222, 1223, 1213, 1219, 1218, 1228, 1211, 1222, 1225, 1220, - 1223, 1214, 1223, 0, 1226, 1223, 1227, 1215, 1218, 1239, - 1221, 1219, 1232, 1223, 1220, 1229, 1221, 1222, 1223, 1231, - 1232, 1225, 1228, 1230, 0, 1225, 1234, 1223, 1227, 1223, - 1226, 1226, 1223, 1227, 1236, 1229, 1230, 1237, 1233, 1232, - 1238, 1239, 1229, 1231, 1234, 1237, 1231, 1233, 1240, 1241, - - 1230, 1243, 1242, 1234, 1245, 1238, 1236, 0, 1246, 1243, - 1247, 1236, 1241, 1250, 1237, 1233, 1248, 1238, 1242, 1249, - 1240, 1251, 1252, 1248, 0, 1240, 1241, 1265, 1243, 1242, - 1246, 1245, 1247, 1253, 1252, 1246, 1250, 1247, 1255, 1251, - 1250, 1249, 1254, 1248, 1256, 1253, 1249, 1255, 1251, 1252, - 1254, 1258, 1257, 1259, 1262, 1261, 1256, 1260, 1263, 1265, - 1253, 1259, 1255, 1260, 1261, 1255, 1258, 1264, 0, 1254, - 1263, 1256, 1257, 1268, 1255, 1262, 0, 1269, 1258, 1257, - 1259, 1262, 1261, 1264, 1260, 1263, 1266, 1271, 1267, 1269, - 1270, 1268, 0, 1266, 1264, 1267, 1274, 1272, 1270, 1273, - - 1268, 1273, 1271, 1275, 1269, 1272, 1278, 1279, 1274, 1276, - 1281, 0, 1280, 1266, 1271, 1267, 1276, 1270, 1284, 1279, - 1282, 1283, 1287, 1274, 1272, 1280, 1273, 1282, 1285, 1281, - 1287, 1288, 1283, 1290, 1279, 1275, 1276, 1281, 1278, 1280, - 1284, 1286, 1289, 1285, 1288, 1284, 1286, 1282, 1283, 1287, - 1292, 1294, 1293, 1296, 0, 1285, 1289, 1298, 1288, 1290, - 1290, 1295, 0, 1299, 1292, 0, 1297, 0, 0, 1289, - 1293, 1301, 1300, 1286, 1291, 1296, 1303, 1292, 1291, 1293, - 1296, 1291, 1291, 1294, 1297, 1299, 1291, 1295, 1295, 1298, - 1299, 0, 1291, 1297, 1300, 1307, 1291, 1301, 1301, 1300, - - 1291, 1291, 1303, 1303, 1302, 1291, 1306, 1310, 1291, 1291, - 1302, 1305, 1304, 1291, 1304, 1306, 1308, 0, 1305, 1291, - 1309, 0, 1311, 1291, 1312, 1310, 1314, 1307, 1315, 1311, - 1313, 1302, 1318, 1306, 1310, 1314, 1304, 1316, 1305, 1304, - 1317, 1304, 1319, 1313, 1309, 0, 1312, 1309, 1308, 1311, - 0, 1312, 1320, 1314, 1318, 1322, 0, 1313, 1316, 1318, - 1315, 1323, 0, 1328, 1316, 1319, 1320, 1324, 1326, 1319, - 1325, 1325, 1317, 1335, 1323, 0, 1330, 1322, 1335, 1320, - 1321, 0, 1322, 1330, 1326, 1321, 1328, 1321, 1323, 1321, - 1328, 1321, 1329, 1324, 1324, 1326, 1331, 1332, 1321, 1325, - - 1335, 1333, 1334, 1330, 1329, 1331, 1333, 1321, 1336, 1337, - 1338, 1342, 1321, 1339, 1321, 1332, 1321, 1340, 1321, 1329, - 1334, 1339, 1337, 1331, 1332, 1340, 1341, 1344, 1338, 1334, - 1336, 1343, 1345, 1333, 1346, 1336, 1337, 1338, 1347, 1341, - 1339, 1351, 1344, 1342, 1340, 1349, 1350, 1346, 1353, 1348, - 1351, 1345, 1354, 1341, 1344, 1356, 0, 1343, 1343, 1345, - 1347, 1346, 1348, 1349, 1357, 1347, 1350, 1352, 1351, 1352, - 1353, 1355, 1349, 1350, 1358, 1353, 1348, 1362, 1360, 1354, - 1364, 1361, 1356, 1355, 1366, 1362, 1357, 1367, 1363, 1365, - 1368, 1357, 0, 0, 1352, 1372, 1365, 1377, 1355, 1358, - - 1374, 1358, 1360, 1361, 1362, 1360, 1363, 1364, 1361, 1375, - 1374, 1366, 1368, 1367, 1367, 1363, 1365, 1368, 1369, 1370, - 1371, 1373, 1372, 1376, 1369, 1370, 1371, 1374, 1373, 1377, - 1376, 1378, 1380, 1375, 1379, 1381, 1375, 1384, 1386, 1383, - 1385, 0, 1387, 0, 1381, 1369, 1370, 1371, 1373, 1384, - 1376, 1388, 1379, 1378, 1385, 1387, 1389, 1380, 1378, 1380, - 1386, 1379, 1381, 1383, 1384, 1386, 1383, 1385, 1390, 1387, - 1391, 1392, 0, 1388, 1393, 1389, 1395, 1394, 1388, 1400, - 1401, 1396, 1398, 1389, 1404, 1395, 1397, 0, 1402, 0, - 1390, 1407, 1403, 1392, 1391, 1390, 1398, 1391, 1392, 1394, - - 1393, 1393, 1396, 1395, 1394, 1405, 1397, 1407, 1396, 1398, - 1402, 1400, 1401, 1397, 1403, 1402, 1404, 1406, 1407, 1403, - 1408, 1409, 1412, 1405, 1411, 1406, 1413, 1414, 1409, 1415, - 1416, 1412, 1405, 1417, 1416, 1418, 1415, 1419, 1422, 1414, - 0, 0, 1435, 1413, 1406, 1420, 1411, 1408, 1409, 1412, - 1429, 1411, 1424, 1413, 1414, 1425, 1415, 1416, 1419, 1424, - 1423, 1420, 1425, 1426, 1419, 1417, 1423, 1418, 1427, 1435, - 1422, 1428, 1420, 1423, 1433, 0, 1429, 1429, 1426, 1424, - 1428, 1427, 1425, 1431, 1430, 1431, 1437, 1423, 1432, 0, - 1426, 1430, 0, 1423, 1434, 1427, 1433, 1432, 1428, 1439, - - 1436, 1433, 1442, 1434, 1436, 1443, 1444, 1439, 1437, 1440, - 1431, 1430, 0, 1437, 1440, 1432, 1441, 1448, 1445, 1444, - 1442, 1434, 1449, 1450, 1443, 1441, 1439, 1436, 1446, 1442, - 1445, 1446, 1443, 1444, 1447, 1448, 1450, 1447, 1452, 1453, - 1446, 1440, 0, 1441, 1448, 1445, 1456, 1449, 1455, 1449, - 1450, 1454, 1459, 1455, 1456, 1446, 1447, 0, 1446, 1457, - 1457, 1447, 1453, 1458, 1447, 1460, 1453, 1454, 1462, 1461, - 1452, 1464, 1458, 1456, 1459, 1463, 1465, 1462, 1454, 1459, - 1455, 1467, 1463, 1465, 1470, 1474, 1457, 1460, 1468, 1471, - 1458, 1461, 1460, 1464, 1467, 1462, 1461, 1468, 1464, 1473, - - 1469, 0, 1463, 1465, 1472, 1475, 1478, 1473, 1467, 1469, - 1470, 1470, 1471, 1472, 1476, 1468, 1471, 1474, 1479, 1478, - 1475, 1477, 1480, 1483, 1482, 1476, 1473, 1469, 1481, 1477, - 1479, 1472, 1475, 1478, 1480, 1484, 1481, 1489, 1485, 1486, - 1488, 1476, 1490, 1483, 1493, 1479, 1482, 1485, 1477, 1480, - 1483, 1482, 1486, 1487, 1490, 1481, 1491, 1484, 1488, 1487, - 1494, 1492, 1484, 1489, 1489, 1485, 1486, 1488, 1492, 1490, - 1493, 1493, 1495, 1496, 1491, 1497, 1498, 1503, 1499, 1500, - 1487, 1501, 1504, 1491, 1505, 1502, 1496, 1501, 1492, 0, - 1500, 1506, 1494, 0, 1507, 1509, 1510, 0, 0, 1499, - - 1496, 1497, 1497, 1498, 1495, 1499, 1500, 1502, 1501, 1503, - 1511, 1513, 1502, 1507, 1504, 1507, 1505, 1506, 1506, 1510, - 1507, 1507, 1509, 1510, 1512, 1516, 1513, 1515, 1511, 1517, - 1514, 1519, 0, 1512, 1518, 1521, 0, 1511, 1513, 1515, - 1507, 1518, 1507, 1514, 1520, 1516, 1525, 1534, 1521, 1526, - 1519, 1512, 1516, 1525, 1515, 1517, 1517, 1514, 1519, 1522, - 1523, 1518, 1521, 1524, 1527, 1523, 1520, 1522, 1524, 1528, - 1529, 1520, 1527, 1525, 1531, 1526, 1526, 1528, 1530, 1534, - 1532, 1533, 1531, 1540, 1535, 1536, 1522, 1532, 1529, 0, - 1533, 1527, 1523, 1542, 1536, 1524, 1528, 1529, 1538, 1543, - - 1530, 1531, 1537, 1539, 1539, 1530, 1535, 1532, 1533, 1537, - 1538, 1535, 1536, 1541, 1542, 1540, 1544, 1545, 1546, 1547, - 1542, 1541, 0, 0, 1544, 1538, 1546, 1547, 1548, 1537, - 1539, 1543, 1551, 1549, 1550, 1545, 1548, 1552, 1551, 1553, - 1541, 1549, 1555, 1544, 1545, 1546, 1547, 1550, 1554, 1552, - 1555, 1558, 1557, 1559, 1556, 1548, 1562, 0, 0, 1551, - 1549, 1550, 1556, 1560, 1552, 1553, 1553, 1557, 1561, 1555, - 1562, 1564, 1554, 1565, 1563, 1554, 0, 1569, 1558, 1557, - 1559, 1556, 1570, 1562, 1568, 1560, 1563, 1565, 1566, 1564, - 1560, 1561, 1566, 1568, 1570, 1561, 1571, 1572, 1564, 1569, - - 1565, 1563, 1573, 1571, 1569, 1566, 1574, 1575, 1572, 1570, - 1576, 1568, 1578, 1566, 1579, 1566, 1577, 0, 1586, 1566, - 1582, 0, 1576, 1571, 1572, 1580, 1581, 1582, 1574, 1573, - 1577, 1583, 1566, 1574, 1587, 1585, 1579, 1576, 1584, 1575, - 1583, 1579, 1585, 1577, 1578, 1589, 1591, 1582, 1580, 1581, - 1586, 1595, 1580, 1581, 1589, 1593, 1584, 1592, 1583, 1594, - 1596, 1587, 1585, 1592, 1598, 1584, 1600, 1596, 1601, 1602, - 1603, 0, 1589, 1607, 1606, 0, 1609, 1593, 1591, 1607, - 1602, 1603, 1593, 1595, 1592, 1594, 1594, 1596, 1604, 1617, - 1600, 1598, 1611, 1600, 1609, 1601, 1602, 1603, 1606, 1604, - - 1607, 1606, 1608, 1609, 1610, 1612, 1613, 1616, 1614, 1608, - 1619, 1610, 1613, 1618, 1615, 1604, 1614, 1612, 1611, 1611, - 1616, 1617, 1622, 0, 1622, 1624, 0, 1629, 1619, 1608, - 1621, 1610, 1612, 1613, 1616, 1614, 1615, 1619, 1620, 1618, - 1618, 1615, 1621, 1623, 1626, 1625, 1627, 1620, 1628, 1622, - 1623, 1624, 1624, 1626, 1629, 1630, 1631, 1621, 1625, 1632, - 1628, 1633, 1640, 1631, 1635, 1620, 1633, 1636, 1627, 1634, - 1623, 1626, 1625, 1627, 0, 1628, 1637, 1634, 1630, 1638, - 1635, 1641, 1630, 1631, 1637, 1632, 1632, 1643, 1633, 1640, - 1636, 1635, 0, 1642, 1636, 1645, 1634, 0, 1646, 1644, - - 1648, 1638, 1651, 1637, 1645, 1641, 1638, 1642, 1641, 1643, - 1644, 1646, 1650, 1648, 1643, 1647, 1647, 1649, 1652, 1649, - 1642, 1655, 1645, 1647, 1653, 1646, 1644, 1648, 1651, 1651, - 1650, 1653, 1656, 1657, 1654, 1661, 1660, 1659, 1663, 1650, - 1652, 1654, 1647, 1647, 1649, 1652, 1658, 1662, 1655, 1664, - 1656, 1653, 1666, 1658, 1662, 1657, 1667, 1669, 1660, 1656, - 1657, 1654, 1659, 1660, 1659, 1666, 1671, 1661, 1673, 1668, - 1663, 1664, 1672, 1658, 1662, 1672, 1664, 1668, 1669, 1666, - 1674, 1676, 0, 1667, 1669, 1675, 1678, 1681, 1671, 1677, - 1676, 1679, 0, 1671, 1673, 1673, 1668, 1682, 1675, 1672, - - 1680, 1677, 1681, 1684, 1682, 1686, 1674, 1674, 1676, 1680, - 1678, 1685, 1675, 1678, 1681, 1689, 1677, 1679, 1679, 1683, - 1691, 1686, 1683, 1688, 1682, 1692, 1690, 1680, 1690, 1686, - 1694, 1697, 1686, 1685, 1683, 1684, 1693, 1689, 1685, 1693, - 1695, 1688, 1689, 1683, 1691, 1699, 1683, 1691, 1686, 1683, - 1688, 1696, 1692, 1690, 1698, 0, 1701, 1697, 1697, 1702, - 1700, 1683, 1694, 1693, 1704, 1705, 1703, 1706, 1702, 1707, - 1701, 1704, 1695, 1696, 1703, 1708, 1709, 1699, 1696, 1710, - 1698, 1698, 1700, 1701, 0, 1713, 1702, 1700, 1712, 1705, - 1711, 1704, 1705, 1703, 1711, 1715, 1714, 1718, 1709, 1706, - - 0, 1707, 1716, 1709, 1715, 1718, 1719, 1708, 1717, 1716, - 1712, 1710, 1713, 1719, 1720, 1712, 1723, 1711, 1714, 1721, - 1717, 1722, 1715, 1714, 1718, 1723, 1724, 1720, 1724, 1716, - 1726, 1725, 1721, 1719, 1722, 1717, 1727, 1730, 1733, 1728, - 1734, 1720, 1732, 1723, 1727, 1731, 1721, 1734, 1722, 1737, - 1735, 1742, 1730, 1724, 1725, 1726, 1732, 1726, 1725, 1728, - 1731, 1735, 1737, 1727, 1730, 1738, 1728, 1734, 1736, 1732, - 1733, 1739, 1731, 1740, 1743, 1736, 1737, 1735, 1742, 1745, - 1744, 1743, 1746, 1738, 1747, 1749, 1748, 0, 1749, 1738, - 0, 1740, 1738, 0, 1745, 1736, 1747, 1739, 1739, 1748, - - 1740, 1743, 1744, 1751, 1752, 1750, 1745, 1744, 1746, 1746, - 1738, 1747, 1749, 1748, 1750, 1753, 1752, 1755, 1759, 1754, - 1759, 1751, 1754, 1760, 1757, 1761, 1762, 1766, 1755, 1757, - 1751, 1752, 1750, 1763, 1764, 1753, 1757, 1754, 1765, 0, - 1771, 1767, 1753, 1764, 1755, 1759, 1754, 1760, 1763, 1754, - 1760, 1757, 1761, 1762, 1766, 1767, 1757, 1769, 1768, 1770, - 1763, 1764, 1765, 1772, 1771, 1765, 1768, 1771, 1767, 1772, - 1773, 1775, 1774, 1776, 1779, 1777, 1780, 1779, 1781, 1769, - 1774, 1770, 1775, 1777, 1769, 1768, 1770, 1782, 1783, 0, - 1772, 1776, 1773, 1778, 1780, 1785, 1778, 1773, 1775, 1774, - - 1776, 1779, 1777, 1780, 1786, 1784, 1787, 1788, 1783, 1785, - 1781, 1778, 1784, 1786, 1782, 1783, 1789, 1790, 1788, 1787, - 1778, 1789, 1785, 1778, 1794, 1791, 1794, 1795, 0, 1796, - 1798, 1786, 1784, 1787, 1788, 1797, 1795, 1804, 0, 1790, - 1791, 1798, 1799, 1803, 1790, 1800, 1804, 1801, 1789, 1800, - 1802, 1794, 1791, 1802, 1795, 1796, 1796, 1798, 1806, 1797, - 1799, 1801, 1797, 1814, 1804, 1803, 1809, 1806, 1802, 1799, - 1803, 1800, 1800, 1801, 1801, 1805, 1800, 1802, 1807, 1809, - 1802, 1805, 1810, 1807, 1811, 1806, 1812, 1813, 1801, 1811, - 1815, 1816, 1817, 1809, 1810, 1814, 1820, 1826, 1818, 1815, - - 1813, 0, 1805, 1819, 1829, 1821, 0, 0, 1812, 1810, - 1807, 1811, 1823, 1812, 1813, 1824, 1819, 1815, 1816, 1823, - 1818, 1825, 1824, 1827, 1817, 1818, 1821, 1828, 1820, 1826, - 1819, 1837, 1821, 1828, 1825, 1833, 1829, 1827, 1831, 1823, - 1836, 1834, 1824, 1833, 1835, 1838, 1840, 1839, 1825, 1834, - 1827, 1828, 1835, 1837, 1828, 1841, 1845, 1831, 1837, 1836, - 1828, 1839, 1833, 1838, 1840, 1831, 1842, 1836, 1834, 1841, - 1843, 1835, 1838, 1840, 1839, 1844, 1846, 1847, 1848, 1842, - 1849, 0, 1841, 1843, 1850, 1851, 1853, 1852, 1845, 1854, - 1855, 1850, 1848, 1842, 1851, 1852, 1844, 1843, 1857, 0, - - 1860, 1847, 1844, 1854, 1847, 1848, 1862, 1849, 1846, 1857, - 1856, 1850, 1851, 1853, 1852, 1856, 1854, 1858, 1863, 1865, - 1866, 1861, 1855, 1844, 1864, 1857, 1858, 1860, 1861, 1862, - 1868, 1864, 1867, 1862, 1868, 1871, 1870, 1856, 1875, 1873, - 1863, 1865, 1866, 1872, 1858, 1863, 1865, 1866, 1861, 1874, - 1867, 1864, 1870, 1871, 1873, 1879, 1876, 1868, 1877, 1867, - 1878, 1874, 1871, 1870, 1876, 1875, 1873, 1872, 1878, 1880, - 1872, 1881, 1882, 1877, 1883, 1884, 1874, 1888, 1886, 1889, - 1892, 1887, 1879, 1876, 1881, 1877, 1886, 1878, 1887, 1883, - 1884, 1880, 1882, 1891, 1889, 1890, 1880, 1893, 1881, 1882, - - 1895, 1883, 1884, 1894, 1890, 1886, 1889, 1892, 1887, 1888, - 1894, 1897, 1899, 1898, 1891, 1900, 1902, 0, 1904, 1901, - 1891, 1893, 1890, 1903, 1893, 1904, 1906, 1895, 1920, 1908, - 1894, 1898, 1905, 1897, 1901, 1906, 1909, 1905, 1897, 1907, - 1898, 1902, 1900, 1902, 1899, 1904, 1901, 1903, 1907, 1910, - 1903, 1908, 1912, 1906, 1911, 1913, 1908, 1914, 1909, 1905, - 1920, 1915, 1918, 1909, 1912, 1916, 1907, 1910, 1915, 1911, - 1914, 1917, 1916, 1919, 1918, 1914, 1910, 1913, 1927, 1912, - 1921, 1911, 1913, 1923, 1914, 1927, 1921, 1916, 1915, 1918, - 1926, 1928, 1916, 1917, 1923, 1924, 1925, 1914, 1917, 1916, - - 1919, 1926, 1930, 1924, 1925, 1927, 1929, 1921, 1929, 1931, - 1923, 1932, 1934, 1933, 1941, 1935, 1928, 1926, 1928, 1929, - 1933, 1936, 1924, 1925, 1937, 1938, 1939, 1936, 1930, 1930, - 1937, 1938, 1940, 1929, 1942, 1929, 1931, 1944, 1932, 1934, - 1933, 1935, 1935, 1946, 1948, 1945, 1941, 1949, 1936, 1949, - 1951, 1937, 1938, 1939, 1945, 1940, 1947, 1950, 1942, 1940, - 1947, 1942, 1954, 1952, 1953, 1957, 1948, 1955, 0, 1944, - 1952, 1948, 1945, 1958, 1949, 1946, 1956, 1951, 1959, 1955, - 1960, 1950, 1956, 1947, 1950, 1961, 1953, 1957, 0, 1954, - 1952, 1953, 1957, 1966, 1955, 1958, 1972, 0, 1978, 1963, - - 1958, 1972, 1960, 1956, 1959, 1959, 1963, 1960, 1962, 1962, - 1962, 1964, 1965, 1969, 1967, 1962, 0, 1961, 1973, 1965, - 1964, 1967, 1968, 1962, 1970, 1966, 1963, 1975, 1972, 1968, - 1978, 1973, 1974, 1969, 1976, 1962, 1962, 1962, 1964, 1965, - 1969, 1967, 1962, 1977, 1974, 1973, 1970, 1979, 1982, 1968, - 1976, 1970, 1975, 1980, 1975, 1977, 1981, 1983, 1983, 1974, - 1980, 1976, 1981, 1984, 1985, 1979, 1987, 1986, 1988, 1989, - 1977, 1985, 1986, 1992, 1979, 1982, 1989, 1993, 1998, 1993, - 1980, 1994, 1997, 1981, 1983, 1996, 2002, 2000, 1997, 1984, - 1984, 1985, 1987, 1987, 1986, 1988, 1989, 1999, 2000, 1994, - - 1992, 2003, 2001, 1996, 1993, 1999, 2004, 2003, 1994, 1997, - 1998, 2005, 1996, 2002, 2000, 2001, 2006, 2009, 2004, 2007, - 2007, 2008, 2010, 2010, 1999, 2011, 2013, 0, 2003, 2001, - 2015, 2005, 2014, 2004, 2006, 0, 2011, 2018, 2005, 2019, - 2017, 2022, 2035, 2006, 2009, 2021, 2007, 2008, 2008, 2010, - 2016, 2023, 2011, 2021, 2014, 0, 0, 2016, 2013, 2014, - 2017, 2024, 2015, 2025, 2019, 2029, 2019, 2017, 2026, 2018, - 2030, 2028, 2021, 2022, 2035, 2027, 2031, 2016, 2023, 2028, - 2026, 2025, 2027, 2024, 2032, 2030, 2033, 2033, 2024, 2029, - 2025, 2034, 2029, 2032, 2036, 2026, 2039, 2030, 2028, 0, - - 2031, 2037, 2027, 2031, 2038, 2042, 2044, 2041, 2037, 0, - 2042, 2032, 2039, 2033, 2041, 2043, 2038, 2034, 2034, 2039, - 2050, 2045, 2046, 2039, 2045, 2051, 2036, 2049, 2037, 2047, - 2046, 2038, 2042, 2044, 2041, 2049, 2052, 2043, 2054, 2039, - 2053, 2047, 2043, 2050, 2055, 2056, 2058, 2050, 2045, 2046, - 2057, 2051, 2051, 2059, 2049, 2057, 2047, 2052, 2053, 2059, - 0, 2060, 2055, 2052, 2062, 2054, 2057, 2053, 2056, 2063, - 2061, 2055, 2056, 2058, 2060, 2066, 2063, 2057, 2061, 2069, - 2059, 2070, 2057, 2064, 2067, 2065, 2062, 2068, 2060, 2071, - 2064, 2062, 2065, 2067, 2072, 2070, 2063, 2061, 2077, 2068, - - 2073, 2069, 2083, 2079, 2075, 2077, 2069, 2066, 2070, 2081, - 2064, 2067, 2065, 2076, 2068, 2078, 2071, 2085, 2076, 2082, - 2072, 2072, 2075, 2073, 2082, 2077, 2087, 2073, 2088, 2076, - 2079, 2075, 2086, 2086, 2083, 2089, 2081, 2078, 2092, 2091, - 2076, 2093, 2078, 2088, 2094, 2076, 2096, 2098, 2087, 2085, - 2095, 2082, 2095, 2087, 2091, 2088, 2093, 2097, 2099, 2086, - 2102, 2092, 2097, 2109, 2100, 2092, 2091, 2089, 2093, 2101, - 2094, 2094, 2100, 2103, 2105, 2106, 2101, 2095, 2096, 2098, - 2110, 2107, 2102, 2106, 2097, 2099, 2111, 2102, 2103, 2105, - 2109, 2100, 2112, 2113, 2115, 2116, 2101, 2118, 2114, 0, - - 2103, 2105, 2106, 2107, 2110, 2114, 2117, 2110, 2107, 2119, - 2121, 2122, 2111, 2111, 2125, 2124, 2116, 2126, 2118, 2112, - 2113, 2131, 2116, 2136, 2118, 2114, 2115, 2119, 2117, 2125, - 2128, 2129, 2121, 2117, 2130, 2132, 2119, 2121, 2122, 2124, - 2135, 2125, 2124, 2126, 2126, 2128, 2129, 2133, 2131, 2134, - 2136, 2139, 2137, 2132, 2138, 2140, 2130, 2128, 2129, 2137, - 2139, 2130, 2132, 2140, 2135, 2141, 2143, 2135, 2142, 2133, - 2147, 2134, 2138, 2145, 2133, 2144, 2134, 2146, 2139, 2137, - 2150, 2138, 2140, 2147, 2144, 2149, 2146, 2151, 2141, 2150, - 2142, 2145, 2141, 2154, 2153, 2142, 2149, 2147, 2143, 2152, - - 2145, 2153, 2144, 2156, 2146, 2151, 2155, 2150, 2159, 2157, - 2158, 2149, 2149, 2162, 2151, 2157, 2165, 2152, 2156, 2154, - 2154, 2153, 2159, 2149, 2155, 2164, 2152, 2165, 2166, 2169, - 2156, 2167, 2158, 2155, 2170, 2159, 2157, 2158, 2171, 2166, - 2162, 2169, 2167, 2165, 2172, 0, 2173, 2170, 0, 2164, - 2174, 2175, 2164, 2176, 2172, 2166, 2169, 2177, 2167, 2180, - 2178, 2170, 2176, 2181, 2175, 2183, 2185, 2184, 2186, 2183, - 2171, 2172, 2173, 2173, 0, 2174, 2187, 2174, 2175, 2178, - 2176, 2186, 2190, 2228, 2177, 0, 2180, 2178, 2184, 2181, - 2181, 2191, 2183, 2189, 2184, 2186, 2187, 2188, 2185, 2191, - - 2189, 2192, 2188, 2187, 2193, 2198, 2194, 2192, 2190, 2190, - 2195, 2200, 2196, 2197, 2197, 2228, 2200, 2191, 2191, 2193, - 2189, 2194, 2195, 2198, 2188, 2207, 2191, 2196, 2192, 2199, - 2201, 2193, 2198, 2194, 2201, 2204, 2206, 2195, 2208, 2196, - 2197, 2199, 2204, 2200, 2202, 2202, 2205, 2208, 2202, 2215, - 2205, 2206, 2207, 2209, 2210, 2211, 2199, 2201, 0, 2212, - 2209, 2202, 2204, 2206, 2218, 2208, 2212, 2214, 2217, 2202, - 2216, 2202, 2202, 2205, 2215, 2202, 2215, 2211, 2210, 2216, - 2209, 2210, 2211, 2220, 2218, 2223, 2212, 2222, 2202, 2214, - 2217, 2218, 2224, 2225, 2214, 2217, 2222, 2216, 2226, 2231, - - 2232, 2220, 2227, 2223, 2229, 2233, 2226, 2224, 2235, 2227, - 2220, 2229, 2223, 2232, 2222, 2234, 2234, 2238, 2225, 2224, - 2225, 2236, 2243, 2239, 2231, 2226, 2231, 2232, 2240, 2227, - 2235, 2229, 2233, 2242, 2241, 2235, 2244, 2240, 2245, 2238, - 2242, 2246, 2234, 2241, 2238, 2239, 2236, 2248, 2236, 2253, - 2239, 2250, 2245, 2254, 2243, 2240, 2246, 2247, 2244, 2250, - 2242, 2241, 2247, 2244, 2251, 2245, 2248, 2252, 2246, 2255, - 2258, 2256, 2260, 2259, 2248, 2325, 2253, 2251, 2250, 2254, - 2254, 2257, 2252, 2256, 2261, 2255, 2263, 2288, 2257, 2247, - 2264, 2251, 2265, 2261, 2252, 2259, 2255, 2260, 2256, 2260, - - 2259, 2262, 2258, 2266, 2267, 2264, 2269, 2325, 2257, 2262, - 2268, 2261, 2271, 2263, 2288, 2269, 0, 2264, 2265, 2265, - 2262, 2273, 2267, 2272, 0, 2282, 2272, 2276, 2262, 2266, - 2266, 2267, 2268, 2269, 2274, 2271, 2262, 2268, 2275, 2271, - 2274, 2272, 2276, 2275, 2277, 2278, 2273, 2282, 2273, 2280, - 2272, 2281, 2282, 2272, 2276, 2283, 2286, 0, 0, 2285, - 2278, 2274, 2277, 2280, 0, 2289, 2281, 2287, 2286, 2295, - 2275, 2277, 2278, 2285, 2289, 2286, 2280, 2283, 2281, 2290, - 2291, 2295, 2283, 2286, 2294, 2287, 2285, 2292, 2290, 2291, - 2296, 2293, 2289, 2293, 2287, 2286, 2295, 2294, 2292, 2301, - - 2298, 2299, 2300, 2302, 2303, 0, 2290, 2291, 0, 2300, - 2304, 2294, 2296, 2309, 2292, 2298, 2299, 2296, 2293, 2304, - 2307, 2301, 2303, 2311, 2315, 2302, 2301, 2298, 2299, 2300, - 2302, 2303, 2310, 2307, 2309, 2311, 2310, 2304, 2314, 2312, - 2309, 2307, 2313, 2316, 2313, 2317, 2318, 2307, 2312, 2319, - 2311, 2315, 2320, 0, 2322, 2318, 2314, 2319, 2321, 2310, - 2307, 2316, 2326, 2324, 2328, 2314, 2312, 2326, 2322, 2313, - 2316, 2324, 2317, 2318, 2329, 2320, 2319, 2327, 2330, 2320, - 2321, 2322, 2327, 2336, 2332, 2321, 2333, 2339, 0, 2326, - 2324, 2340, 0, 2333, 2337, 2342, 2328, 2338, 2344, 2346, - - 2347, 2341, 2330, 2332, 2342, 2330, 2329, 2345, 2337, 2327, - 2336, 2332, 2349, 2333, 2339, 2338, 2341, 2340, 2340, 2337, - 2337, 2337, 2342, 2348, 2338, 2346, 2346, 2347, 2341, 2345, - 2344, 2351, 2352, 2353, 2345, 2337, 2354, 0, 2356, 2352, - 2356, 2359, 2357, 2354, 2349, 2348, 2337, 2358, 2360, 2366, - 2348, 2358, 2361, 2359, 2351, 2362, 2353, 0, 2351, 2352, - 2353, 2361, 2364, 2354, 2357, 2356, 2362, 2365, 2359, 2357, - 2360, 2363, 2365, 2367, 2358, 2360, 2366, 2369, 2363, 2361, - 2368, 2370, 2362, 2374, 2364, 2371, 2371, 2373, 2372, 2364, - 2370, 2374, 2368, 2378, 2365, 2375, 2367, 2372, 2363, 2369, - - 2367, 0, 2373, 2381, 2369, 2376, 2380, 2368, 2370, 2377, - 2374, 2381, 2371, 2382, 2373, 2372, 2383, 2375, 2377, 2376, - 2378, 2382, 2375, 2384, 2383, 2380, 2385, 2384, 2387, 2385, - 2381, 2386, 2376, 2380, 2387, 2389, 2377, 2388, 2390, 2386, - 2382, 2389, 2391, 2383, 2393, 2395, 2397, 2464, 2396, 0, - 2384, 2398, 2388, 2385, 2400, 2387, 2393, 0, 2386, 2395, - 2401, 2396, 2389, 2408, 2388, 2402, 2403, 2397, 2407, 2410, - 2390, 2393, 2395, 2397, 2391, 2396, 2398, 2399, 2398, 2464, - 2403, 2400, 2401, 2404, 2399, 2405, 2404, 2401, 2406, 2402, - 2408, 2409, 2402, 2403, 2407, 2407, 2410, 2411, 2405, 2412, - - 2413, 2416, 2406, 2414, 2399, 2417, 2414, 2418, 0, 2411, - 2404, 2412, 2405, 2419, 2413, 2406, 2409, 2420, 2409, 2418, - 2420, 2421, 2422, 2423, 2411, 0, 2412, 2413, 2416, 2414, - 2414, 2417, 2417, 2414, 2418, 2420, 2425, 2429, 2430, 2419, - 2419, 2428, 2432, 2431, 2420, 2423, 2426, 2420, 2421, 2422, - 2423, 2431, 2427, 2426, 2434, 2435, 2428, 2433, 2425, 2427, - 2437, 2436, 2438, 2425, 2429, 2430, 2433, 2435, 2428, 2432, - 2431, 2441, 2439, 2426, 2440, 2443, 2442, 2444, 2448, 2427, - 2450, 2434, 2435, 2436, 2433, 2439, 2442, 2437, 2436, 2438, - 2444, 2447, 2440, 2452, 2456, 2453, 0, 2441, 2441, 2439, - - 2445, 2440, 2443, 2442, 2444, 2448, 2449, 2450, 2445, 2459, - 2451, 2454, 2458, 2447, 2449, 2452, 2453, 2455, 2447, 2451, - 2452, 2456, 2453, 2457, 2458, 2463, 0, 2445, 2461, 2471, - 2467, 2457, 2455, 2449, 2459, 2454, 2459, 2451, 2454, 2458, - 2461, 2462, 2467, 2455, 2455, 2473, 2466, 2468, 2469, 2462, - 2457, 2468, 2463, 2466, 2470, 2461, 2471, 2467, 2472, 2455, - 2469, 2477, 2479, 2478, 2474, 2480, 2472, 2473, 2462, 2475, - 2478, 2481, 2473, 2466, 2468, 2469, 2474, 2470, 2480, 2485, - 2481, 2470, 2479, 2475, 2482, 2472, 2486, 2483, 2477, 2479, - 2478, 2474, 2480, 2482, 2487, 2475, 2475, 2490, 2481, 2483, - - 2484, 2484, 0, 2491, 2486, 2485, 2485, 2488, 0, 0, - 2475, 2482, 0, 2486, 2483, 2492, 2493, 2494, 2491, 2487, - 0, 2487, 2488, 2495, 2488, 2495, 2496, 2484, 2498, 2490, - 2491, 2488, 2499, 2506, 2488, 2497, 2502, 2492, 2493, 2494, - 2496, 2497, 2492, 2493, 2494, 2503, 2498, 2500, 2500, 2488, - 2495, 2488, 2505, 2496, 2499, 2498, 2504, 2507, 2502, 2499, - 2508, 2509, 2497, 2502, 2505, 2506, 2508, 2503, 2510, 2511, - 2512, 2514, 2503, 2509, 2500, 2513, 2517, 2513, 2504, 2505, - 2515, 2518, 2521, 2504, 2522, 2514, 2516, 2508, 2509, 2507, - 2523, 2511, 2512, 2516, 2517, 2521, 2511, 2512, 2514, 2518, - - 2510, 2519, 2513, 2517, 2515, 2520, 2524, 2515, 2518, 2521, - 2526, 2528, 2529, 2516, 2530, 2531, 2522, 2526, 2528, 2519, - 0, 2535, 2523, 2520, 2533, 0, 2532, 2540, 2519, 2524, - 2529, 2534, 2520, 2524, 2532, 0, 0, 2526, 2528, 2529, - 2530, 2530, 2533, 2535, 2538, 2539, 2542, 2531, 2535, 2553, - 2544, 2533, 2532, 2532, 2540, 2538, 2539, 2534, 2534, 2545, - 2536, 2532, 2536, 2541, 2542, 2544, 2546, 2536, 2547, 2550, - 2545, 2538, 2539, 2542, 2549, 2541, 2553, 2544, 2546, 2552, - 2556, 2551, 0, 2547, 2554, 2557, 2545, 2536, 2551, 2536, - 2541, 2550, 2558, 2546, 2552, 2547, 2550, 2559, 2549, 2560, - - 2561, 2549, 0, 2562, 2569, 2565, 2552, 2556, 2551, 2557, - 2554, 2554, 2557, 2563, 2558, 2564, 2567, 2571, 2561, 2558, - 2565, 2566, 0, 2568, 2567, 2570, 2563, 2561, 2573, 2559, - 2562, 2560, 2565, 2574, 2566, 2575, 2569, 2576, 2570, 2571, - 2563, 2564, 2564, 2567, 2571, 2577, 2581, 2578, 2566, 2568, - 2568, 2573, 2570, 2579, 2580, 2573, 2582, 2574, 0, 2576, - 2574, 2580, 2575, 2583, 2576, 2578, 2585, 2577, 2586, 2581, - 2592, 2579, 2577, 2581, 2578, 2586, 2589, 2583, 2587, 2588, - 2579, 2580, 2595, 2582, 2590, 2587, 2588, 2591, 2585, 2589, - 2583, 2593, 2592, 2585, 2591, 2586, 0, 2592, 2594, 0, - - 2596, 2597, 2600, 2589, 2598, 2587, 2588, 2590, 2595, 2595, - 2597, 2590, 2598, 2599, 2591, 2602, 2601, 2604, 2607, 2594, - 2608, 2599, 2601, 2593, 2600, 2594, 2596, 2596, 2597, 2600, - 2605, 2598, 2604, 2606, 2609, 0, 2612, 2610, 2614, 0, - 2599, 2605, 2602, 2601, 2604, 2615, 2628, 2616, 0, 2618, - 2607, 2614, 2608, 2609, 2612, 2606, 2617, 2605, 2615, 2621, - 2606, 2609, 2610, 2612, 2610, 2614, 2620, 2622, 2623, 2623, - 2624, 2621, 2615, 2616, 2616, 2618, 2618, 2627, 2628, 2630, - 2617, 2634, 0, 2617, 2629, 2631, 2621, 2642, 2638, 2636, - 2620, 2622, 2653, 2620, 2622, 2623, 2624, 2624, 2636, 2629, - - 2627, 2638, 2639, 2631, 2627, 2647, 2630, 2649, 2634, 2642, - 2644, 2629, 2631, 2639, 2642, 2638, 2636, 2643, 2643, 2644, - 2645, 2648, 2651, 2654, 2653, 2655, 2645, 2647, 2656, 2639, - 2654, 2657, 2647, 2660, 2649, 2658, 2657, 2644, 2662, 2656, - 2661, 2660, 2664, 2648, 2643, 2666, 2663, 2645, 2648, 2651, - 2654, 2655, 2655, 2662, 2668, 2656, 2666, 2658, 2657, 2667, - 2660, 2663, 2658, 2669, 2661, 2662, 2671, 2661, 0, 2664, - 2670, 2673, 2666, 2663, 2675, 2668, 2674, 2667, 2671, 2670, - 2677, 2668, 2675, 2676, 2676, 2680, 2667, 2679, 2683, 2677, - 2682, 2676, 0, 2671, 2681, 2669, 2687, 2670, 2673, 2682, - - 2674, 2675, 2685, 2674, 2684, 2686, 2683, 2677, 0, 2687, - 2676, 2676, 2680, 2679, 2679, 2683, 2681, 2682, 2684, 2689, - 2688, 2681, 2690, 2687, 2685, 2694, 2693, 2695, 2691, 2685, - 2686, 2684, 2686, 2688, 2689, 2691, 2692, 2696, 2697, 2695, - 2698, 2699, 2701, 2692, 2690, 2700, 2689, 2688, 2693, 2690, - 2703, 2701, 2694, 2693, 2695, 2691, 2699, 2702, 0, 2704, - 0, 2705, 0, 2692, 2696, 2697, 2706, 2698, 2699, 2701, - 2700, 2707, 2700, 2709, 2708, 2712, 2703, 2703, 2707, 2702, - 2709, 2706, 2714, 2711, 2702, 2704, 2704, 2705, 2705, 2708, - 2710, 2713, 2715, 2706, 2711, 2716, 2710, 2717, 2707, 2713, - - 2709, 2708, 2712, 2719, 2722, 2718, 2720, 2721, 2723, 2714, - 2711, 2716, 2725, 2727, 2721, 2723, 0, 2710, 2713, 2715, - 2718, 2720, 2716, 2719, 2717, 2726, 2722, 2728, 2728, 2724, - 2719, 2722, 2718, 2720, 2721, 2723, 2724, 2729, 2732, 2725, - 2727, 2730, 2731, 2726, 2729, 2731, 2734, 2735, 2733, 0, - 2736, 2732, 2726, 2733, 2728, 2730, 2724, 2741, 2738, 0, - 2737, 0, 2735, 2748, 2729, 2732, 2741, 2739, 2730, 2731, - 2738, 2734, 2744, 2734, 2735, 2733, 2736, 2736, 2737, 2739, - 2745, 2742, 2746, 2747, 2741, 2738, 2742, 2737, 2743, 2749, - 2748, 2750, 2743, 2745, 2739, 2752, 2744, 2754, 2756, 2744, - - 0, 2758, 2755, 0, 2746, 2747, 0, 2745, 2742, 2746, - 2747, 2755, 2757, 2758, 2756, 2743, 2749, 2750, 2750, 2760, - 2757, 2752, 2752, 2754, 2754, 2756, 2760, 2761, 2758, 2755, - 2762, 2763, 2764, 2765, 2767, 2762, 2761, 2766, 2763, 2757, - 2765, 2767, 2768, 2769, 0, 2770, 2760, 2773, 2776, 0, - 2764, 2768, 2769, 2772, 2761, 2774, 2777, 2762, 2763, 2764, - 2765, 2767, 2766, 2779, 2766, 2780, 2776, 2784, 2774, 2768, - 2769, 2770, 2770, 2775, 2773, 2776, 2772, 2781, 2775, 2782, - 2772, 2779, 2774, 2777, 2783, 2785, 2781, 2784, 2782, 2786, - 2779, 2788, 2780, 2783, 2784, 2789, 2787, 2785, 2786, 2791, - - 2775, 2790, 2788, 2789, 2781, 2787, 2782, 2792, 2793, 2796, - 2794, 2783, 2785, 2798, 2799, 0, 2786, 2794, 2788, 2791, - 2795, 2800, 2789, 2787, 2790, 2807, 2791, 2806, 2790, 2795, - 2796, 2803, 2805, 2801, 2792, 2793, 2796, 2794, 2804, 2802, - 2798, 2799, 2801, 2803, 2808, 2805, 2804, 2795, 2802, 2806, - 2809, 2808, 2807, 2800, 2806, 2810, 2811, 2809, 2803, 2805, - 2801, 2813, 2810, 2812, 2814, 2804, 2802, 2815, 2813, 2816, - 2817, 2808, 2811, 2818, 0, 2822, 2820, 2809, 2825, 2812, - 0, 2823, 2810, 2811, 2820, 2825, 2814, 2826, 2813, 2823, - 2812, 2814, 2815, 2822, 2815, 2817, 2816, 2817, 2824, 2827, - - 2818, 2828, 2822, 2820, 2829, 2825, 2827, 2830, 2823, 2826, - 2833, 2829, 2834, 2824, 2826, 2830, 2835, 2833, 2836, 2839, - 2837, 2834, 2840, 2828, 2838, 2824, 2827, 2842, 2828, 2841, - 2844, 2829, 2837, 2838, 2830, 2847, 2845, 2833, 2840, 2834, - 2835, 2841, 2844, 2835, 2846, 2836, 2839, 2837, 2845, 2840, - 2842, 2838, 2848, 2849, 2842, 2854, 2841, 2844, 2847, 2852, - 2851, 2853, 2847, 2845, 2856, 2846, 2852, 2849, 2855, 2853, - 2858, 2846, 2851, 2860, 2854, 2855, 2859, 0, 2861, 2848, - 2849, 2862, 2854, 2864, 2863, 2858, 2852, 2851, 2853, 2866, - 2865, 2856, 2863, 2870, 2859, 2855, 2860, 2858, 2867, 2868, - - 2860, 2876, 2879, 2859, 2861, 2861, 2869, 2866, 2862, 2867, - 2864, 2863, 2865, 2869, 2868, 2872, 2866, 2865, 2877, 2878, - 2870, 2872, 2883, 2880, 2878, 2867, 2868, 2876, 2876, 2879, - 2881, 2886, 2887, 2869, 2882, 2884, 2877, 2880, 2885, 2887, - 2883, 2890, 2872, 2888, 2881, 2877, 2878, 2893, 2882, 2883, - 2880, 2895, 2898, 2884, 2896, 2888, 2885, 2881, 2886, 2887, - 2897, 2882, 2884, 2905, 2899, 2885, 2900, 2896, 2890, 2893, - 2888, 2898, 2899, 2895, 2893, 2901, 2903, 2906, 2895, 2898, - 2907, 2896, 2897, 2908, 2900, 2905, 2909, 2897, 2903, 2910, - 2905, 2899, 2907, 2900, 2901, 2912, 0, 2911, 2913, 2906, - - 2915, 2914, 2901, 2903, 2906, 2911, 2916, 2907, 2917, 2915, - 2908, 2910, 2918, 2909, 2920, 2916, 2910, 2919, 2913, 2922, - 2921, 2923, 2912, 2914, 2911, 2913, 2920, 2915, 2914, 2927, - 2928, 2926, 2929, 2916, 2918, 2933, 2940, 2929, 2930, 2918, - 2917, 2920, 2921, 2919, 2919, 2926, 2922, 2921, 2923, 2931, - 2932, 2934, 2936, 2935, 2928, 2941, 2927, 2928, 2926, 2944, - 2930, 2937, 2938, 2932, 2929, 2930, 2939, 2933, 2940, 2942, - 2936, 2931, 2939, 2937, 2934, 2935, 2931, 2932, 2934, 2936, - 2935, 2938, 2943, 2946, 2947, 2950, 2944, 2941, 2937, 2938, - 2948, 2942, 0, 2939, 2952, 2955, 2942, 2943, 2953, 2956, - - 2950, 2954, 2962, 2946, 2955, 2959, 2947, 2961, 2966, 2943, - 2946, 2947, 2950, 2956, 2948, 2957, 2952, 2948, 2958, 2960, - 2953, 2952, 2955, 2954, 2962, 2953, 2956, 2967, 2954, 2962, - 2961, 2959, 2959, 2957, 2961, 2965, 2958, 2960, 2974, 2970, - 2966, 2975, 2957, 2971, 2965, 2958, 2960, 2970, 2967, 2972, - 2971, 2973, 2976, 2978, 2967, 2979, 2972, 2980, 0, 2973, - 2976, 2975, 2965, 2981, 2984, 2974, 2970, 2982, 2975, 2983, - 2971, 2978, 0, 2979, 2987, 2981, 2972, 2990, 2973, 2976, - 2978, 2983, 2979, 2980, 2980, 2982, 2987, 2985, 2991, 2993, - 2981, 2984, 2989, 2994, 2982, 2985, 2983, 2996, 0, 2989, - - 2990, 2987, 2995, 2992, 2990, 2992, 2996, 2997, 2998, 2999, - 2995, 3000, 0, 3000, 2985, 2991, 3003, 3004, 3001, 2989, - 3006, 2993, 3007, 0, 2996, 2994, 3011, 3008, 2999, 2995, - 2992, 3004, 3009, 0, 3003, 2998, 2999, 3014, 3000, 2997, - 3001, 3009, 3010, 3003, 3004, 3001, 3007, 3015, 3012, 3007, - 3008, 3016, 3006, 3011, 3008, 3010, 3015, 3017, 3018, 3009, - 3012, 3017, 3019, 3014, 3014, 3021, 3023, 3022, 3024, 3010, - 3026, 0, 3028, 3034, 3015, 3012, 3029, 3031, 3016, 3028, - 3034, 3030, 3031, 3039, 3017, 3018, 3024, 3032, 3023, 3019, - 3022, 3037, 3021, 3023, 3022, 3024, 3030, 3026, 3029, 3028, - - 3034, 3040, 3032, 3029, 3035, 3036, 3041, 3043, 3030, 3031, - 3039, 3035, 3036, 3042, 3032, 3044, 3046, 3037, 3037, 3050, - 3049, 3043, 3051, 3052, 3053, 3054, 3047, 3049, 3040, 3044, - 3055, 3035, 3036, 3041, 3043, 3047, 3053, 3042, 3058, 3059, - 3042, 3063, 3044, 3046, 3055, 3056, 3050, 3049, 3051, 3051, - 3052, 3053, 3054, 3047, 3056, 3057, 3060, 3055, 3064, 3066, - 3068, 3067, 3069, 3070, 3066, 3067, 3059, 3068, 3057, 3069, - 3058, 3071, 3056, 3063, 3072, 3073, 3072, 3074, 3077, 3060, - 3064, 3084, 3057, 3060, 3070, 3064, 3080, 3068, 3067, 3069, - 3070, 3066, 3079, 3082, 3083, 3082, 3085, 3085, 3073, 3089, - - 3077, 3072, 3073, 3071, 3074, 3077, 3085, 3084, 3084, 3086, - 3080, 3079, 3089, 3080, 3090, 3088, 3087, 3091, 3083, 3079, - 3082, 3083, 3088, 3085, 3085, 3087, 3089, 3092, 3095, 3094, - 3091, 3086, 3093, 3097, 3098, 3092, 3086, 3094, 3097, 3098, - 3099, 3090, 3088, 3087, 3091, 3093, 3100, 3095, 3099, 3101, - 3106, 3092, 3102, 0, 3092, 3095, 3094, 3103, 3107, 3093, - 3104, 3106, 3092, 3105, 3108, 3097, 3098, 3099, 3109, 3109, - 3110, 3108, 0, 3100, 3112, 3101, 3101, 3106, 3102, 3102, - 3107, 3111, 3114, 3103, 3103, 3107, 3104, 3104, 3110, 3105, - 3105, 3108, 3113, 3115, 3111, 3109, 3112, 3110, 3116, 3117, - - 3113, 3112, 3120, 3118, 3114, 3116, 3117, 3121, 3111, 3114, - 3118, 3115, 3122, 3124, 3125, 3123, 3126, 3129, 3131, 3113, - 3115, 0, 3127, 3134, 3132, 3116, 3117, 3123, 3130, 3120, - 3118, 3127, 3137, 3142, 3121, 3125, 3122, 3143, 3126, 3122, - 3124, 3125, 3123, 3126, 3129, 3131, 3132, 3135, 3130, 3127, - 3134, 3132, 3136, 3138, 3139, 3130, 0, 3141, 0, 3137, - 3142, 3146, 3144, 3148, 3143, 3135, 3141, 3147, 3145, 3146, - 3136, 3138, 3139, 3150, 3135, 3148, 3154, 3161, 3150, 3136, - 3138, 3139, 3152, 3147, 3141, 3144, 3145, 0, 3146, 3144, - 3148, 3149, 3153, 3160, 3147, 3145, 3152, 3164, 3149, 3154, - - 3156, 3162, 3169, 3154, 3161, 3150, 3170, 3167, 3165, 3152, - 3153, 3166, 3156, 3166, 3162, 3160, 3167, 3173, 3149, 3153, - 3160, 3165, 3171, 3172, 3164, 3178, 3182, 3156, 3162, 3169, - 3179, 0, 3173, 3170, 3167, 3165, 3181, 3177, 3166, 3177, - 3171, 3184, 3191, 3181, 3173, 3186, 3198, 3178, 3179, 3171, - 3199, 3186, 3178, 3188, 3189, 3172, 3184, 3179, 3182, 3190, - 3191, 3193, 3200, 3181, 3177, 3194, 0, 3196, 3184, 3191, - 3196, 3195, 3186, 3198, 3203, 3188, 3189, 3199, 3201, 3194, - 3188, 3189, 3203, 3193, 3195, 3190, 3190, 3204, 3193, 3200, - 3207, 3206, 3194, 3196, 3196, 3202, 3201, 3196, 3195, 3208, - - 3209, 3203, 3202, 3211, 3210, 3201, 3213, 3215, 3217, 3204, - 3212, 3214, 3207, 3210, 3204, 0, 3212, 3207, 3211, 3219, - 3214, 3208, 3202, 3206, 0, 3220, 3208, 3209, 3213, 3221, - 3211, 3210, 3216, 3213, 3216, 3217, 3222, 3212, 3214, 3215, - 3223, 3224, 3219, 3225, 3229, 0, 3219, 3220, 3223, 0, - 3227, 3221, 3220, 3224, 3236, 3225, 3221, 3227, 3231, 3216, - 3232, 3233, 3222, 3222, 3235, 3236, 3234, 3223, 3224, 0, - 3225, 3229, 3231, 3238, 3232, 3233, 3237, 3227, 3242, 3239, - 3243, 3236, 3235, 3240, 3237, 3231, 3246, 3232, 3233, 3234, - 3240, 3235, 3238, 3234, 3247, 3241, 3245, 3245, 3243, 3244, - - 3238, 3239, 3241, 3237, 3242, 3242, 3239, 3243, 3244, 3248, - 3240, 3251, 3252, 3246, 3254, 3255, 3251, 3248, 3256, 3260, - 3262, 3247, 3241, 3245, 3258, 3252, 3244, 3263, 3265, 3266, - 3258, 3262, 0, 3270, 3272, 3254, 3248, 3267, 3263, 3252, - 3266, 3254, 3255, 3251, 3273, 3256, 3260, 3262, 3275, 0, - 3265, 3258, 3272, 3274, 3263, 3265, 3266, 3274, 3271, 3267, - 3270, 3272, 3276, 3280, 3267, 3271, 3278, 3282, 3279, 3281, - 3276, 3280, 3284, 3287, 3293, 3275, 3273, 0, 3281, 3286, - 3274, 3279, 0, 3291, 3294, 3271, 3286, 3288, 3291, 3276, - 3280, 3295, 3278, 3278, 3282, 3279, 3281, 3292, 3292, 3298, - - 3296, 3293, 3297, 3295, 3284, 3287, 3286, 3296, 3302, 3288, - 3291, 3294, 3299, 3300, 3288, 3298, 3302, 3301, 3295, 3303, - 3300, 3297, 0, 3305, 3292, 3304, 3298, 3296, 3309, 3297, - 3299, 3306, 3304, 3307, 3303, 3302, 3313, 3308, 3314, 3299, - 3300, 3315, 3316, 3306, 3317, 3314, 3303, 3318, 3297, 3301, - 3305, 3313, 3304, 3319, 3309, 3309, 3321, 3307, 3306, 3322, - 3307, 3308, 3319, 3313, 3308, 3314, 3323, 3324, 3317, 3316, - 3325, 3317, 3327, 3315, 3329, 3324, 3330, 3333, 3321, 3318, - 3319, 3326, 3326, 3321, 3332, 3330, 3322, 3334, 3323, 3329, - 3331, 3326, 3331, 3323, 3324, 3334, 3335, 3336, 3332, 3327, - - 3338, 3329, 3325, 3330, 3333, 3339, 3340, 3335, 3326, 3326, - 3344, 3332, 3341, 3342, 3334, 3336, 3343, 3331, 3345, 3346, - 3351, 3348, 3349, 3335, 3336, 0, 3342, 3338, 3352, 3347, - 3350, 3350, 3339, 3340, 3341, 3355, 3349, 3344, 3343, 3341, - 3342, 3358, 3356, 3343, 3359, 3345, 3346, 3347, 3348, 3349, - 3352, 3362, 3351, 3356, 3368, 3352, 3347, 3350, 3364, 3362, - 3365, 3367, 3355, 3364, 3366, 3365, 3367, 3370, 3358, 3356, - 3375, 3359, 3366, 3371, 3371, 3372, 3373, 3375, 3362, 3377, - 3368, 3368, 3378, 3372, 3379, 3364, 3376, 3365, 3367, 3373, - 3381, 3366, 3382, 3384, 3370, 3390, 3385, 3375, 3383, 3381, - - 3371, 3384, 3372, 3373, 3376, 3383, 3377, 3379, 3386, 3378, - 3389, 3379, 3392, 3376, 3393, 3394, 3389, 3381, 3385, 3395, - 3384, 3397, 3390, 3385, 3382, 3383, 3398, 3399, 3394, 3396, - 3386, 3422, 3401, 0, 3488, 3386, 3393, 3389, 3402, 3392, - 3397, 3393, 3394, 3403, 3396, 3404, 3405, 3406, 3397, 3399, - 3403, 3395, 3404, 3398, 3399, 3401, 3396, 3407, 3409, 3401, - 3402, 3410, 3406, 3422, 3411, 3402, 3488, 3414, 3405, 3410, - 3403, 3411, 3404, 3405, 3406, 3412, 3414, 3409, 3407, 3415, - 0, 3418, 3412, 3417, 3407, 3409, 3416, 3416, 3410, 3417, - 3415, 3411, 3421, 3420, 3414, 3423, 3416, 3425, 0, 3421, - - 3431, 3426, 3412, 3418, 3425, 3432, 3415, 3427, 3418, 3439, - 3417, 3437, 3433, 3416, 3416, 3420, 3442, 3423, 3440, 3421, - 3420, 3427, 3423, 3437, 3425, 3426, 3447, 3431, 3426, 3441, - 3444, 3450, 3432, 3454, 3427, 3433, 3439, 3441, 3437, 3433, - 3440, 3452, 3444, 3442, 3455, 3440, 3448, 3448, 3449, 3449, - 3451, 3451, 0, 3447, 3456, 3454, 3441, 3444, 3450, 3458, - 3454, 3457, 3455, 3461, 3452, 3462, 3463, 3464, 3452, 3466, - 3457, 3455, 3458, 3463, 3464, 3448, 3465, 3449, 3467, 3451, - 3472, 3456, 3468, 3471, 3474, 3471, 3458, 3467, 3457, 3468, - 3461, 3462, 3462, 3463, 3464, 3473, 3466, 3477, 3465, 3478, - - 3472, 3475, 3474, 3465, 3479, 3467, 3477, 3472, 3481, 3468, - 3471, 3474, 3480, 3475, 3482, 3483, 3485, 3484, 3473, 0, - 3487, 3478, 3473, 3496, 3477, 3487, 3478, 0, 3475, 3484, - 3480, 3479, 3492, 3486, 3481, 3481, 3486, 3490, 3485, 3480, - 3491, 3482, 3483, 3485, 3484, 3489, 3491, 3489, 3493, 3490, - 3494, 3486, 3487, 3495, 3492, 3496, 3498, 3497, 3494, 3492, - 3486, 3499, 3500, 3486, 3490, 3501, 3504, 3491, 3505, 3507, - 3493, 3512, 3489, 3508, 3500, 3493, 3510, 3494, 3497, 3513, - 3495, 3505, 3514, 3498, 3497, 3510, 3515, 3501, 3499, 3500, - 3517, 3508, 3501, 3504, 3518, 3505, 3507, 3519, 3512, 3520, - - 3508, 3521, 3521, 3510, 3523, 3524, 3513, 3526, 3528, 3514, - 3532, 3527, 3529, 3515, 3534, 3531, 3539, 3517, 3535, 3529, - 3538, 3518, 3523, 3528, 3519, 3533, 3520, 3531, 3521, 3527, - 3535, 3523, 3524, 3533, 3526, 3528, 3536, 3532, 3527, 3529, - 3537, 3534, 3531, 3539, 3541, 3535, 3538, 3538, 3542, 3545, - 3536, 0, 3533, 3546, 3551, 3537, 3541, 3548, 3545, 3547, - 3547, 3549, 3552, 3536, 3555, 3554, 3553, 3537, 3559, 0, - 3549, 3541, 3555, 3556, 3557, 3542, 3545, 3546, 3551, 3553, - 3546, 3551, 3556, 3548, 3548, 3557, 3547, 3554, 3549, 3559, - 3560, 3555, 3554, 3553, 3552, 3559, 3563, 3564, 0, 3566, - - 3556, 3557, 3568, 3568, 3569, 3578, 3579, 3582, 3560, 3564, - 3583, 3569, 3584, 3585, 3587, 3591, 3589, 3560, 3590, 3563, - 3589, 3582, 3615, 3563, 3564, 3566, 3566, 3578, 3592, 3568, - 3579, 3569, 3578, 3579, 3582, 3592, 3590, 3583, 3591, 3584, - 3585, 3587, 3591, 3589, 3594, 3590, 3596, 3597, 3598, 3615, - 3596, 3599, 3600, 0, 3601, 3592, 3604, 3594, 3602, 3603, - 3606, 0, 3606, 3597, 3600, 3604, 3605, 3603, 3610, 3624, - 3598, 3594, 3602, 3596, 3597, 3598, 3599, 3605, 3599, 3600, - 3601, 3601, 3607, 3604, 3608, 3602, 3603, 3606, 3609, 3612, - 3610, 3611, 3613, 3605, 3607, 3610, 3624, 3611, 3614, 3617, - - 3616, 3623, 3608, 3609, 3612, 3626, 3614, 3616, 3623, 3607, - 3622, 3608, 3625, 3628, 3613, 3609, 3612, 3627, 3611, 3613, - 3629, 3617, 3631, 3622, 3632, 3614, 3617, 3616, 3623, 3631, - 3625, 3633, 3626, 3630, 3634, 3637, 3635, 3622, 3635, 3625, - 3628, 3630, 3636, 3627, 3627, 3641, 3638, 3629, 3632, 3631, - 3639, 3632, 3640, 3633, 3636, 3642, 3634, 3643, 3633, 3638, - 3630, 3634, 3642, 3635, 3644, 3639, 3645, 3637, 3647, 3636, - 3649, 3648, 3641, 3638, 3640, 3650, 3652, 3639, 3649, 3640, - 3654, 3657, 3642, 3648, 3643, 3658, 3659, 3664, 3652, 3654, - 3661, 3644, 3660, 3645, 3662, 3647, 3663, 3649, 3648, 0, - - 3660, 3664, 3650, 3652, 3667, 3659, 3666, 3654, 3657, 3663, - 3665, 3658, 3658, 3659, 3664, 3669, 3677, 3675, 3665, 3660, - 0, 3674, 3661, 3663, 3675, 3680, 3662, 3674, 3666, 3677, - 3678, 3667, 3680, 3666, 3681, 3683, 3684, 3665, 3682, 3685, - 0, 3688, 3669, 3677, 3675, 3686, 3682, 3685, 3674, 3683, - 3684, 3687, 3680, 3678, 3694, 0, 3681, 3678, 3695, 0, - 3692, 3681, 3683, 3684, 3691, 3682, 3685, 3686, 3688, 3692, - 3696, 3691, 3686, 3687, 3693, 3702, 0, 3697, 3687, 0, - 3695, 3694, 3693, 3698, 3699, 3695, 3700, 3692, 3701, 3704, - 3705, 3691, 3706, 3713, 3710, 3708, 3701, 0, 0, 0, - - 0, 3693, 3696, 3697, 3697, 3698, 3699, 3702, 3700, 3717, - 3698, 3699, 3705, 3700, 3710, 3701, 3704, 3705, 3708, 3706, - 3709, 3710, 3708, 3711, 3712, 3713, 3714, 3715, 3709, 3719, - 3720, 3711, 3712, 3720, 3714, 3717, 3717, 3721, 3722, 0, - 3725, 3715, 3729, 3729, 3723, 0, 3722, 3709, 3720, 3724, - 3711, 3712, 3723, 3714, 3715, 3726, 3719, 3720, 3727, 3721, - 3720, 3730, 3731, 3724, 3721, 3722, 3725, 3725, 3732, 3729, - 3731, 3723, 3727, 3733, 3734, 3736, 3724, 3726, 3735, 3737, - 3740, 3738, 3726, 3736, 3739, 3727, 0, 3730, 3730, 3731, - 3741, 3747, 3742, 3744, 3732, 3732, 3734, 0, 3735, 3733, - - 3733, 3734, 3736, 3738, 3750, 3735, 3737, 3740, 3738, 3739, - 3741, 3739, 3742, 3743, 3745, 3744, 3748, 3741, 3747, 3742, - 3744, 3743, 3745, 3751, 3748, 3752, 3750, 3753, 0, 3754, - 3756, 3750, 3759, 3752, 3757, 3753, 3758, 3760, 3763, 0, - 3743, 3745, 3757, 3748, 3758, 3751, 3761, 3764, 3765, 3767, - 3751, 3773, 3752, 3774, 3753, 3754, 3754, 3756, 3759, 3759, - 3770, 3757, 3771, 3758, 3760, 3763, 3761, 0, 3765, 3772, - 3771, 3767, 0, 3761, 3764, 3765, 3767, 3772, 3773, 0, - 3774, 0, 3770, 0, 0, 0, 0, 3770, 0, 3771, - 0, 0, 0, 0, 0, 0, 3772, 3778, 3778, 3778, - - 3778, 3778, 3778, 3778, 3779, 3779, 3779, 3779, 3779, 3779, - 3779, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3781, 3781, - 3781, 3781, 3781, 3781, 3781, 3782, 3782, 3782, 3782, 3782, - 3782, 3782, 3783, 3783, 3783, 3783, 3783, 3783, 3783, 3784, - 3784, 3784, 3784, 3784, 3784, 3784, 3786, 3786, 0, 3786, - 3786, 3786, 3786, 3787, 3787, 0, 0, 0, 3787, 3787, - 3788, 3788, 0, 0, 3788, 0, 3788, 3789, 0, 0, - 0, 0, 0, 3789, 3790, 3790, 0, 0, 0, 3790, - 3790, 3791, 0, 0, 0, 0, 0, 3791, 3792, 3792, - 0, 3792, 3792, 3792, 3792, 3793, 0, 0, 0, 0, - - 0, 3793, 3794, 3794, 0, 0, 0, 3794, 3794, 3795, - 3795, 0, 3795, 3795, 3795, 3795, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, 3777, - 3777, 3777, 3777 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -extern int yy_flex_debug; -int yy_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -static int yy_more_flag = 0; -static int yy_more_len = 0; -#define yymore() ((yy_more_flag) = 1) -#define YY_MORE_ADJ (yy_more_len) -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "util/configlexer.lex" -#line 2 "util/configlexer.lex" -/* - * configlexer.lex - lexical analyzer for unbound config file - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved - * - * See LICENSE for the license. - * - */ - -/* because flex keeps having sign-unsigned compare problems that are unfixed*/ -#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2)))) -#pragma GCC diagnostic ignored "-Wsign-compare" -#endif - -#include -#include -#ifdef HAVE_GLOB_H -# include -#endif - -#include "util/config_file.h" -#include "util/configparser.h" -void ub_c_error(const char *message); - -#if 0 -#define LEXOUT(s) printf s /* used ONLY when debugging */ -#else -#define LEXOUT(s) -#endif - -/** avoid warning in about fwrite return value */ -#define ECHO ub_c_error_msg("syntax error at text: %s", yytext) - -/** A parser variable, this is a statement in the config file which is - * of the form variable: value1 value2 ... nargs is the number of values. */ -#define YDVAR(nargs, var) \ - num_args=(nargs); \ - LEXOUT(("v(%s%d) ", yytext, num_args)); \ - if(num_args > 0) { BEGIN(val); } \ - return (var); - -struct inc_state { - char* filename; - int line; - YY_BUFFER_STATE buffer; - struct inc_state* next; - int inc_toplevel; -}; -static struct inc_state* config_include_stack = NULL; -static int inc_depth = 0; -static int inc_prev = 0; -static int num_args = 0; -static int inc_toplevel = 0; - -void init_cfg_parse(void) -{ - config_include_stack = NULL; - inc_depth = 0; - inc_prev = 0; - num_args = 0; - inc_toplevel = 0; -} - -static void config_start_include(const char* filename, int toplevel) -{ - FILE *input; - struct inc_state* s; - char* nm; - if(inc_depth+1 > 100000) { - ub_c_error_msg("too many include files"); - return; - } - if(*filename == '\0') { - ub_c_error_msg("empty include file name"); - return; - } - s = (struct inc_state*)malloc(sizeof(*s)); - if(!s) { - ub_c_error_msg("include %s: malloc failure", filename); - return; - } - if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, - strlen(cfg_parser->chroot)) == 0) { - filename += strlen(cfg_parser->chroot); - } - nm = strdup(filename); - if(!nm) { - ub_c_error_msg("include %s: strdup failure", filename); - free(s); - return; - } - input = fopen(filename, "r"); - if(!input) { - ub_c_error_msg("cannot open include file '%s': %s", - filename, strerror(errno)); - free(s); - free(nm); - return; - } - LEXOUT(("switch_to_include_file(%s)\n", filename)); - inc_depth++; - s->filename = cfg_parser->filename; - s->line = cfg_parser->line; - s->buffer = YY_CURRENT_BUFFER; - s->inc_toplevel = inc_toplevel; - s->next = config_include_stack; - config_include_stack = s; - cfg_parser->filename = nm; - cfg_parser->line = 1; - inc_toplevel = toplevel; - yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE)); -} - -static void config_start_include_glob(const char* filename, int toplevel) -{ - - /* check for wildcards */ -#ifdef HAVE_GLOB - glob_t g; - int i, r, flags; - if(!(!strchr(filename, '*') && !strchr(filename, '?') && !strchr(filename, '[') && - !strchr(filename, '{') && !strchr(filename, '~'))) { - flags = 0 -#ifdef GLOB_ERR - | GLOB_ERR -#endif - /* do not set GLOB_NOSORT so the results are sorted - and in a predictable order. */ -#ifdef GLOB_BRACE - | GLOB_BRACE -#endif -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif - ; - memset(&g, 0, sizeof(g)); - if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, - strlen(cfg_parser->chroot)) == 0) { - filename += strlen(cfg_parser->chroot); - } - r = glob(filename, flags, NULL, &g); - if(r) { - /* some error */ - globfree(&g); - if(r == GLOB_NOMATCH) - return; /* no matches for pattern */ - config_start_include(filename, toplevel); /* let original deal with it */ - return; - } - /* process files found, if any */ - for(i=(int)g.gl_pathc-1; i>=0; i--) { - config_start_include(g.gl_pathv[i], toplevel); - } - globfree(&g); - return; - } -#endif /* HAVE_GLOB */ - - config_start_include(filename, toplevel); -} - -static void config_end_include(void) -{ - struct inc_state* s = config_include_stack; - --inc_depth; - if(!s) return; - free(cfg_parser->filename); - cfg_parser->filename = s->filename; - cfg_parser->line = s->line; - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(s->buffer); - config_include_stack = s->next; - inc_toplevel = s->inc_toplevel; - free(s); -} - -#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ - } -#endif - -#line 4253 "" -#define YY_NO_INPUT 1 -#line 191 "util/configlexer.lex" -#ifndef YY_NO_UNPUT -#define YY_NO_UNPUT 1 -#endif -#ifndef YY_NO_INPUT -#define YY_NO_INPUT 1 -#endif -#line 4262 "" - -#line 4264 "" - -#define INITIAL 0 -#define quotedstring 1 -#define singlequotedstr 2 -#define include 3 -#define include_quoted 4 -#define val 5 -#define include_toplevel 6 -#define include_toplevel_quoted 7 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals ( void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int yylex_destroy ( void ); - -int yyget_debug ( void ); - -void yyset_debug ( int debug_flag ); - -YY_EXTRA_TYPE yyget_extra ( void ); - -void yyset_extra ( YY_EXTRA_TYPE user_defined ); - -FILE *yyget_in ( void ); - -void yyset_in ( FILE * _in_str ); - -FILE *yyget_out ( void ); - -void yyset_out ( FILE * _out_str ); - - int yyget_leng ( void ); - -char *yyget_text ( void ); - -int yyget_lineno ( void ); - -void yyset_lineno ( int _line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap ( void ); -#else -extern int yywrap ( void ); -#endif -#endif - -#ifndef YY_NO_UNPUT - -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char * ); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput ( void ); -#else -static int input ( void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - int n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (void); - -#define YY_DECL int yylex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_load_buffer_state( ); - } - - { -#line 211 "util/configlexer.lex" - -#line 4488 "" - - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - (yy_more_len) = 0; - if ( (yy_more_flag) ) - { - (yy_more_len) = (int) ((yy_c_buf_p) - (yytext_ptr)); - (yy_more_flag) = 0; - } - yy_cp = (yy_c_buf_p); - - /* Support of yytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 3778 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 10717 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 212 "util/configlexer.lex" -{ - LEXOUT(("SP ")); /* ignore */ } - YY_BREAK -case 2: -YY_RULE_SETUP -#line 214 "util/configlexer.lex" -{ - /* note that flex makes the longest match and '.' is any but not nl */ - LEXOUT(("comment(%s) ", yytext)); /* ignore */ } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 217 "util/configlexer.lex" -{ YDVAR(0, VAR_SERVER) } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 218 "util/configlexer.lex" -{ YDVAR(1, VAR_QNAME_MINIMISATION) } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 219 "util/configlexer.lex" -{ YDVAR(1, VAR_QNAME_MINIMISATION_STRICT) } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 220 "util/configlexer.lex" -{ YDVAR(1, VAR_NUM_THREADS) } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 221 "util/configlexer.lex" -{ YDVAR(1, VAR_VERBOSITY) } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 222 "util/configlexer.lex" -{ YDVAR(1, VAR_PORT) } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 223 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_RANGE) } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 224 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_PORT_PERMIT) } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 225 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_PORT_AVOID) } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 226 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_NUM_TCP) } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 227 "util/configlexer.lex" -{ YDVAR(1, VAR_INCOMING_NUM_TCP) } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 228 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_IP4) } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 229 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_IP6) } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 230 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_NAT64) } - YY_BREAK -case 17: -YY_RULE_SETUP -#line 231 "util/configlexer.lex" -{ YDVAR(1, VAR_PREFER_IP4) } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 232 "util/configlexer.lex" -{ YDVAR(1, VAR_PREFER_IP6) } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 233 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_UDP) } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 234 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_TCP) } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 235 "util/configlexer.lex" -{ YDVAR(1, VAR_TCP_UPSTREAM) } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 236 "util/configlexer.lex" -{ YDVAR(1, VAR_TCP_MSS) } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 237 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_TCP_MSS) } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 238 "util/configlexer.lex" -{ YDVAR(1, VAR_TCP_IDLE_TIMEOUT) } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 239 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_REUSE_TCP_QUERIES) } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 240 "util/configlexer.lex" -{ YDVAR(1, VAR_TCP_REUSE_TIMEOUT) } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 241 "util/configlexer.lex" -{ YDVAR(1, VAR_TCP_AUTH_QUERY_TIMEOUT) } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 242 "util/configlexer.lex" -{ YDVAR(1, VAR_EDNS_TCP_KEEPALIVE) } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 243 "util/configlexer.lex" -{ YDVAR(1, VAR_EDNS_TCP_KEEPALIVE_TIMEOUT) } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 244 "util/configlexer.lex" -{ YDVAR(1, VAR_SOCK_QUEUE_TIMEOUT) } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 245 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_UPSTREAM) } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 246 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_UPSTREAM) } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 247 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_SERVICE_KEY) } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 248 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_SERVICE_KEY) } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 249 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_SERVICE_PEM) } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 250 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_SERVICE_PEM) } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 251 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_PORT) } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 252 "util/configlexer.lex" -{ YDVAR(1, VAR_SSL_PORT) } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 253 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_CERT_BUNDLE) } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 254 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_CERT_BUNDLE) } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 255 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_WIN_CERT) } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 256 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_WIN_CERT) } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 257 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 258 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 259 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 260 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 261 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 262 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_CIPHERS) } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 263 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_CIPHERSUITES) } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 264 "util/configlexer.lex" -{ YDVAR(1, VAR_TLS_USE_SNI) } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 265 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTPS_PORT) } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 266 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_ENDPOINT) } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 267 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_MAX_STREAMS) } - YY_BREAK -case 54: -YY_RULE_SETUP -#line 268 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_QUERY_BUFFER_SIZE) } - YY_BREAK -case 55: -YY_RULE_SETUP -#line 269 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_RESPONSE_BUFFER_SIZE) } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 270 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_NODELAY) } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 271 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_NOTLS_DOWNSTREAM) } - YY_BREAK -case 58: -YY_RULE_SETUP -#line 272 "util/configlexer.lex" -{ YDVAR(1, VAR_USE_SYSTEMD) } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 273 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_DAEMONIZE) } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 274 "util/configlexer.lex" -{ YDVAR(1, VAR_INTERFACE) } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 275 "util/configlexer.lex" -{ YDVAR(1, VAR_INTERFACE) } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 276 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTGOING_INTERFACE) } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 277 "util/configlexer.lex" -{ YDVAR(1, VAR_INTERFACE_AUTOMATIC) } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 278 "util/configlexer.lex" -{ YDVAR(1, VAR_INTERFACE_AUTOMATIC_PORTS) } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 279 "util/configlexer.lex" -{ YDVAR(1, VAR_SO_RCVBUF) } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 280 "util/configlexer.lex" -{ YDVAR(1, VAR_SO_SNDBUF) } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 281 "util/configlexer.lex" -{ YDVAR(1, VAR_SO_REUSEPORT) } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 282 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_TRANSPARENT) } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 283 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_FREEBIND) } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 284 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_DSCP) } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 285 "util/configlexer.lex" -{ YDVAR(1, VAR_CHROOT) } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 286 "util/configlexer.lex" -{ YDVAR(1, VAR_USERNAME) } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 287 "util/configlexer.lex" -{ YDVAR(1, VAR_DIRECTORY) } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 288 "util/configlexer.lex" -{ YDVAR(1, VAR_LOGFILE) } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 289 "util/configlexer.lex" -{ YDVAR(1, VAR_PIDFILE) } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 290 "util/configlexer.lex" -{ YDVAR(1, VAR_ROOT_HINTS) } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 291 "util/configlexer.lex" -{ YDVAR(1, VAR_STREAM_WAIT_SIZE) } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 292 "util/configlexer.lex" -{ YDVAR(1, VAR_EDNS_BUFFER_SIZE) } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 293 "util/configlexer.lex" -{ YDVAR(1, VAR_MSG_BUFFER_SIZE) } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 294 "util/configlexer.lex" -{ YDVAR(1, VAR_MSG_CACHE_SIZE) } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 295 "util/configlexer.lex" -{ YDVAR(1, VAR_MSG_CACHE_SLABS) } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 296 "util/configlexer.lex" -{ YDVAR(1, VAR_RRSET_CACHE_SIZE) } - YY_BREAK -case 83: -YY_RULE_SETUP -#line 297 "util/configlexer.lex" -{ YDVAR(1, VAR_RRSET_CACHE_SLABS) } - YY_BREAK -case 84: -YY_RULE_SETUP -#line 298 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHE_MAX_TTL) } - YY_BREAK -case 85: -YY_RULE_SETUP -#line 299 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHE_MAX_NEGATIVE_TTL) } - YY_BREAK -case 86: -YY_RULE_SETUP -#line 300 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHE_MIN_TTL) } - YY_BREAK -case 87: -YY_RULE_SETUP -#line 301 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_HOST_TTL) } - YY_BREAK -case 88: -YY_RULE_SETUP -#line 302 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_LAME_TTL) } - YY_BREAK -case 89: -YY_RULE_SETUP -#line 303 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_CACHE_SLABS) } - YY_BREAK -case 90: -YY_RULE_SETUP -#line 304 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) } - YY_BREAK -case 91: -YY_RULE_SETUP -#line 305 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) } - YY_BREAK -case 92: -YY_RULE_SETUP -#line 306 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_CACHE_MIN_RTT) } - YY_BREAK -case 93: -YY_RULE_SETUP -#line 307 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_CACHE_MAX_RTT) } - YY_BREAK -case 94: -YY_RULE_SETUP -#line 308 "util/configlexer.lex" -{ YDVAR(1, VAR_INFRA_KEEP_PROBING) } - YY_BREAK -case 95: -YY_RULE_SETUP -#line 309 "util/configlexer.lex" -{ YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) } - YY_BREAK -case 96: -YY_RULE_SETUP -#line 310 "util/configlexer.lex" -{ YDVAR(1, VAR_JOSTLE_TIMEOUT) } - YY_BREAK -case 97: -YY_RULE_SETUP -#line 311 "util/configlexer.lex" -{ YDVAR(1, VAR_DELAY_CLOSE) } - YY_BREAK -case 98: -YY_RULE_SETUP -#line 312 "util/configlexer.lex" -{ YDVAR(1, VAR_UDP_CONNECT) } - YY_BREAK -case 99: -YY_RULE_SETUP -#line 313 "util/configlexer.lex" -{ YDVAR(1, VAR_TARGET_FETCH_POLICY) } - YY_BREAK -case 100: -YY_RULE_SETUP -#line 314 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) } - YY_BREAK -case 101: -YY_RULE_SETUP -#line 315 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_LARGE_QUERIES) } - YY_BREAK -case 102: -YY_RULE_SETUP -#line 316 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_GLUE) } - YY_BREAK -case 103: -YY_RULE_SETUP -#line 317 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) } - YY_BREAK -case 104: -YY_RULE_SETUP -#line 318 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) } - YY_BREAK -case 105: -YY_RULE_SETUP -#line 319 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_REFERRAL_PATH) } - YY_BREAK -case 106: -YY_RULE_SETUP -#line 320 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) } - YY_BREAK -case 107: -YY_RULE_SETUP -#line 321 "util/configlexer.lex" -{ YDVAR(1, VAR_HARDEN_UNKNOWN_ADDITIONAL) } - YY_BREAK -case 108: -YY_RULE_SETUP -#line 322 "util/configlexer.lex" -{ YDVAR(1, VAR_USE_CAPS_FOR_ID) } - YY_BREAK -case 109: -YY_RULE_SETUP -#line 323 "util/configlexer.lex" -{ YDVAR(1, VAR_CAPS_WHITELIST) } - YY_BREAK -case 110: -YY_RULE_SETUP -#line 324 "util/configlexer.lex" -{ YDVAR(1, VAR_CAPS_WHITELIST) } - YY_BREAK -case 111: -YY_RULE_SETUP -#line 325 "util/configlexer.lex" -{ YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) } - YY_BREAK -case 112: -YY_RULE_SETUP -#line 326 "util/configlexer.lex" -{ YDVAR(1, VAR_PRIVATE_ADDRESS) } - YY_BREAK -case 113: -YY_RULE_SETUP -#line 327 "util/configlexer.lex" -{ YDVAR(1, VAR_PRIVATE_DOMAIN) } - YY_BREAK -case 114: -YY_RULE_SETUP -#line 328 "util/configlexer.lex" -{ YDVAR(1, VAR_PREFETCH_KEY) } - YY_BREAK -case 115: -YY_RULE_SETUP -#line 329 "util/configlexer.lex" -{ YDVAR(1, VAR_PREFETCH) } - YY_BREAK -case 116: -YY_RULE_SETUP -#line 330 "util/configlexer.lex" -{ YDVAR(1, VAR_DENY_ANY) } - YY_BREAK -case 117: -YY_RULE_SETUP -#line 331 "util/configlexer.lex" -{ YDVAR(0, VAR_STUB_ZONE) } - YY_BREAK -case 118: -YY_RULE_SETUP -#line 332 "util/configlexer.lex" -{ YDVAR(1, VAR_NAME) } - YY_BREAK -case 119: -YY_RULE_SETUP -#line 333 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_ADDR) } - YY_BREAK -case 120: -YY_RULE_SETUP -#line 334 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_HOST) } - YY_BREAK -case 121: -YY_RULE_SETUP -#line 335 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_PRIME) } - YY_BREAK -case 122: -YY_RULE_SETUP -#line 336 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_FIRST) } - YY_BREAK -case 123: -YY_RULE_SETUP -#line 337 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_NO_CACHE) } - YY_BREAK -case 124: -YY_RULE_SETUP -#line 338 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_SSL_UPSTREAM) } - YY_BREAK -case 125: -YY_RULE_SETUP -#line 339 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_SSL_UPSTREAM) } - YY_BREAK -case 126: -YY_RULE_SETUP -#line 340 "util/configlexer.lex" -{ YDVAR(1, VAR_STUB_TCP_UPSTREAM) } - YY_BREAK -case 127: -YY_RULE_SETUP -#line 341 "util/configlexer.lex" -{ YDVAR(0, VAR_FORWARD_ZONE) } - YY_BREAK -case 128: -YY_RULE_SETUP -#line 342 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_ADDR) } - YY_BREAK -case 129: -YY_RULE_SETUP -#line 343 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_HOST) } - YY_BREAK -case 130: -YY_RULE_SETUP -#line 344 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_FIRST) } - YY_BREAK -case 131: -YY_RULE_SETUP -#line 345 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_NO_CACHE) } - YY_BREAK -case 132: -YY_RULE_SETUP -#line 346 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } - YY_BREAK -case 133: -YY_RULE_SETUP -#line 347 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } - YY_BREAK -case 134: -YY_RULE_SETUP -#line 348 "util/configlexer.lex" -{ YDVAR(1, VAR_FORWARD_TCP_UPSTREAM) } - YY_BREAK -case 135: -YY_RULE_SETUP -#line 349 "util/configlexer.lex" -{ YDVAR(0, VAR_AUTH_ZONE) } - YY_BREAK -case 136: -YY_RULE_SETUP -#line 350 "util/configlexer.lex" -{ YDVAR(0, VAR_RPZ) } - YY_BREAK -case 137: -YY_RULE_SETUP -#line 351 "util/configlexer.lex" -{ YDVAR(1, VAR_TAGS) } - YY_BREAK -case 138: -YY_RULE_SETUP -#line 352 "util/configlexer.lex" -{ YDVAR(1, VAR_RPZ_ACTION_OVERRIDE) } - YY_BREAK -case 139: -YY_RULE_SETUP -#line 353 "util/configlexer.lex" -{ YDVAR(1, VAR_RPZ_CNAME_OVERRIDE) } - YY_BREAK -case 140: -YY_RULE_SETUP -#line 354 "util/configlexer.lex" -{ YDVAR(1, VAR_RPZ_LOG) } - YY_BREAK -case 141: -YY_RULE_SETUP -#line 355 "util/configlexer.lex" -{ YDVAR(1, VAR_RPZ_LOG_NAME) } - YY_BREAK -case 142: -YY_RULE_SETUP -#line 356 "util/configlexer.lex" -{ YDVAR(1, VAR_RPZ_SIGNAL_NXDOMAIN_RA) } - YY_BREAK -case 143: -YY_RULE_SETUP -#line 357 "util/configlexer.lex" -{ YDVAR(1, VAR_ZONEFILE) } - YY_BREAK -case 144: -YY_RULE_SETUP -#line 358 "util/configlexer.lex" -{ YDVAR(1, VAR_MASTER) } - YY_BREAK -case 145: -YY_RULE_SETUP -#line 359 "util/configlexer.lex" -{ YDVAR(1, VAR_MASTER) } - YY_BREAK -case 146: -YY_RULE_SETUP -#line 360 "util/configlexer.lex" -{ YDVAR(1, VAR_URL) } - YY_BREAK -case 147: -YY_RULE_SETUP -#line 361 "util/configlexer.lex" -{ YDVAR(1, VAR_ALLOW_NOTIFY) } - YY_BREAK -case 148: -YY_RULE_SETUP -#line 362 "util/configlexer.lex" -{ YDVAR(1, VAR_FOR_DOWNSTREAM) } - YY_BREAK -case 149: -YY_RULE_SETUP -#line 363 "util/configlexer.lex" -{ YDVAR(1, VAR_FOR_UPSTREAM) } - YY_BREAK -case 150: -YY_RULE_SETUP -#line 364 "util/configlexer.lex" -{ YDVAR(1, VAR_FALLBACK_ENABLED) } - YY_BREAK -case 151: -YY_RULE_SETUP -#line 365 "util/configlexer.lex" -{ YDVAR(0, VAR_VIEW) } - YY_BREAK -case 152: -YY_RULE_SETUP -#line 366 "util/configlexer.lex" -{ YDVAR(1, VAR_VIEW_FIRST) } - YY_BREAK -case 153: -YY_RULE_SETUP -#line 367 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) } - YY_BREAK -case 154: -YY_RULE_SETUP -#line 368 "util/configlexer.lex" -{ YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) } - YY_BREAK -case 155: -YY_RULE_SETUP -#line 369 "util/configlexer.lex" -{ YDVAR(2, VAR_ACCESS_CONTROL) } - YY_BREAK -case 156: -YY_RULE_SETUP -#line 370 "util/configlexer.lex" -{ YDVAR(2, VAR_INTERFACE_ACTION) } - YY_BREAK -case 157: -YY_RULE_SETUP -#line 371 "util/configlexer.lex" -{ YDVAR(1, VAR_SEND_CLIENT_SUBNET) } - YY_BREAK -case 158: -YY_RULE_SETUP -#line 372 "util/configlexer.lex" -{ YDVAR(1, VAR_CLIENT_SUBNET_ZONE) } - YY_BREAK -case 159: -YY_RULE_SETUP -#line 373 "util/configlexer.lex" -{ YDVAR(1, VAR_CLIENT_SUBNET_ALWAYS_FORWARD) } - YY_BREAK -case 160: -YY_RULE_SETUP -#line 374 "util/configlexer.lex" -{ YDVAR(1, VAR_CLIENT_SUBNET_OPCODE) } - YY_BREAK -case 161: -YY_RULE_SETUP -#line 375 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV4) } - YY_BREAK -case 162: -YY_RULE_SETUP -#line 376 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV6) } - YY_BREAK -case 163: -YY_RULE_SETUP -#line 377 "util/configlexer.lex" -{ YDVAR(1, VAR_MIN_CLIENT_SUBNET_IPV4) } - YY_BREAK -case 164: -YY_RULE_SETUP -#line 378 "util/configlexer.lex" -{ YDVAR(1, VAR_MIN_CLIENT_SUBNET_IPV6) } - YY_BREAK -case 165: -YY_RULE_SETUP -#line 379 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_ECS_TREE_SIZE_IPV4) } - YY_BREAK -case 166: -YY_RULE_SETUP -#line 380 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_ECS_TREE_SIZE_IPV6) } - YY_BREAK -case 167: -YY_RULE_SETUP -#line 381 "util/configlexer.lex" -{ YDVAR(1, VAR_HIDE_IDENTITY) } - YY_BREAK -case 168: -YY_RULE_SETUP -#line 382 "util/configlexer.lex" -{ YDVAR(1, VAR_HIDE_VERSION) } - YY_BREAK -case 169: -YY_RULE_SETUP -#line 383 "util/configlexer.lex" -{ YDVAR(1, VAR_HIDE_TRUSTANCHOR) } - YY_BREAK -case 170: -YY_RULE_SETUP -#line 384 "util/configlexer.lex" -{ YDVAR(1, VAR_HIDE_HTTP_USER_AGENT) } - YY_BREAK -case 171: -YY_RULE_SETUP -#line 385 "util/configlexer.lex" -{ YDVAR(1, VAR_IDENTITY) } - YY_BREAK -case 172: -YY_RULE_SETUP -#line 386 "util/configlexer.lex" -{ YDVAR(1, VAR_VERSION) } - YY_BREAK -case 173: -YY_RULE_SETUP -#line 387 "util/configlexer.lex" -{ YDVAR(1, VAR_HTTP_USER_AGENT) } - YY_BREAK -case 174: -YY_RULE_SETUP -#line 388 "util/configlexer.lex" -{ YDVAR(1, VAR_MODULE_CONF) } - YY_BREAK -case 175: -YY_RULE_SETUP -#line 389 "util/configlexer.lex" -{ YDVAR(1, VAR_DLV_ANCHOR) } - YY_BREAK -case 176: -YY_RULE_SETUP -#line 390 "util/configlexer.lex" -{ YDVAR(1, VAR_DLV_ANCHOR_FILE) } - YY_BREAK -case 177: -YY_RULE_SETUP -#line 391 "util/configlexer.lex" -{ YDVAR(1, VAR_TRUST_ANCHOR_FILE) } - YY_BREAK -case 178: -YY_RULE_SETUP -#line 392 "util/configlexer.lex" -{ YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) } - YY_BREAK -case 179: -YY_RULE_SETUP -#line 393 "util/configlexer.lex" -{ YDVAR(1, VAR_TRUSTED_KEYS_FILE) } - YY_BREAK -case 180: -YY_RULE_SETUP -#line 394 "util/configlexer.lex" -{ YDVAR(1, VAR_TRUST_ANCHOR) } - YY_BREAK -case 181: -YY_RULE_SETUP -#line 395 "util/configlexer.lex" -{ YDVAR(1, VAR_TRUST_ANCHOR_SIGNALING) } - YY_BREAK -case 182: -YY_RULE_SETUP -#line 396 "util/configlexer.lex" -{ YDVAR(1, VAR_ROOT_KEY_SENTINEL) } - YY_BREAK -case 183: -YY_RULE_SETUP -#line 397 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_OVERRIDE_DATE) } - YY_BREAK -case 184: -YY_RULE_SETUP -#line 398 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } - YY_BREAK -case 185: -YY_RULE_SETUP -#line 399 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } - YY_BREAK -case 186: -YY_RULE_SETUP -#line 400 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_MAX_RESTART) } - YY_BREAK -case 187: -YY_RULE_SETUP -#line 401 "util/configlexer.lex" -{ YDVAR(1, VAR_BOGUS_TTL) } - YY_BREAK -case 188: -YY_RULE_SETUP -#line 402 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } - YY_BREAK -case 189: -YY_RULE_SETUP -#line 403 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } - YY_BREAK -case 190: -YY_RULE_SETUP -#line 404 "util/configlexer.lex" -{ YDVAR(1, VAR_AGGRESSIVE_NSEC) } - YY_BREAK -case 191: -YY_RULE_SETUP -#line 405 "util/configlexer.lex" -{ YDVAR(1, VAR_IGNORE_CD_FLAG) } - YY_BREAK -case 192: -YY_RULE_SETUP -#line 406 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_EXPIRED) } - YY_BREAK -case 193: -YY_RULE_SETUP -#line 407 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_EXPIRED_TTL) } - YY_BREAK -case 194: -YY_RULE_SETUP -#line 408 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) } - YY_BREAK -case 195: -YY_RULE_SETUP -#line 409 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) } - YY_BREAK -case 196: -YY_RULE_SETUP -#line 410 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) } - YY_BREAK -case 197: -YY_RULE_SETUP -#line 411 "util/configlexer.lex" -{ YDVAR(1, VAR_EDE_SERVE_EXPIRED) } - YY_BREAK -case 198: -YY_RULE_SETUP -#line 412 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVE_ORIGINAL_TTL) } - YY_BREAK -case 199: -YY_RULE_SETUP -#line 413 "util/configlexer.lex" -{ YDVAR(1, VAR_FAKE_DSA) } - YY_BREAK -case 200: -YY_RULE_SETUP -#line 414 "util/configlexer.lex" -{ YDVAR(1, VAR_FAKE_SHA1) } - YY_BREAK -case 201: -YY_RULE_SETUP -#line 415 "util/configlexer.lex" -{ YDVAR(1, VAR_VAL_LOG_LEVEL) } - YY_BREAK -case 202: -YY_RULE_SETUP -#line 416 "util/configlexer.lex" -{ YDVAR(1, VAR_KEY_CACHE_SIZE) } - YY_BREAK -case 203: -YY_RULE_SETUP -#line 417 "util/configlexer.lex" -{ YDVAR(1, VAR_KEY_CACHE_SLABS) } - YY_BREAK -case 204: -YY_RULE_SETUP -#line 418 "util/configlexer.lex" -{ YDVAR(1, VAR_NEG_CACHE_SIZE) } - YY_BREAK -case 205: -YY_RULE_SETUP -#line 419 "util/configlexer.lex" -{ - YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) } - YY_BREAK -case 206: -YY_RULE_SETUP -#line 421 "util/configlexer.lex" -{ YDVAR(1, VAR_ZONEMD_PERMISSIVE_MODE) } - YY_BREAK -case 207: -YY_RULE_SETUP -#line 422 "util/configlexer.lex" -{ YDVAR(1, VAR_ZONEMD_CHECK) } - YY_BREAK -case 208: -YY_RULE_SETUP -#line 423 "util/configlexer.lex" -{ YDVAR(1, VAR_ZONEMD_REJECT_ABSENCE) } - YY_BREAK -case 209: -YY_RULE_SETUP -#line 424 "util/configlexer.lex" -{ YDVAR(1, VAR_ADD_HOLDDOWN) } - YY_BREAK -case 210: -YY_RULE_SETUP -#line 425 "util/configlexer.lex" -{ YDVAR(1, VAR_DEL_HOLDDOWN) } - YY_BREAK -case 211: -YY_RULE_SETUP -#line 426 "util/configlexer.lex" -{ YDVAR(1, VAR_KEEP_MISSING) } - YY_BREAK -case 212: -YY_RULE_SETUP -#line 427 "util/configlexer.lex" -{ YDVAR(1, VAR_PERMIT_SMALL_HOLDDOWN) } - YY_BREAK -case 213: -YY_RULE_SETUP -#line 428 "util/configlexer.lex" -{ YDVAR(1, VAR_USE_SYSLOG) } - YY_BREAK -case 214: -YY_RULE_SETUP -#line 429 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_IDENTITY) } - YY_BREAK -case 215: -YY_RULE_SETUP -#line 430 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_TIME_ASCII) } - YY_BREAK -case 216: -YY_RULE_SETUP -#line 431 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_QUERIES) } - YY_BREAK -case 217: -YY_RULE_SETUP -#line 432 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_REPLIES) } - YY_BREAK -case 218: -YY_RULE_SETUP -#line 433 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_TAG_QUERYREPLY) } - YY_BREAK -case 219: -YY_RULE_SETUP -#line 434 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_LOCAL_ACTIONS) } - YY_BREAK -case 220: -YY_RULE_SETUP -#line 435 "util/configlexer.lex" -{ YDVAR(1, VAR_LOG_SERVFAIL) } - YY_BREAK -case 221: -YY_RULE_SETUP -#line 436 "util/configlexer.lex" -{ YDVAR(2, VAR_LOCAL_ZONE) } - YY_BREAK -case 222: -YY_RULE_SETUP -#line 437 "util/configlexer.lex" -{ YDVAR(1, VAR_LOCAL_DATA) } - YY_BREAK -case 223: -YY_RULE_SETUP -#line 438 "util/configlexer.lex" -{ YDVAR(1, VAR_LOCAL_DATA_PTR) } - YY_BREAK -case 224: -YY_RULE_SETUP -#line 439 "util/configlexer.lex" -{ YDVAR(1, VAR_UNBLOCK_LAN_ZONES) } - YY_BREAK -case 225: -YY_RULE_SETUP -#line 440 "util/configlexer.lex" -{ YDVAR(1, VAR_INSECURE_LAN_ZONES) } - YY_BREAK -case 226: -YY_RULE_SETUP -#line 441 "util/configlexer.lex" -{ YDVAR(1, VAR_STATISTICS_INTERVAL) } - YY_BREAK -case 227: -YY_RULE_SETUP -#line 442 "util/configlexer.lex" -{ YDVAR(1, VAR_STATISTICS_CUMULATIVE) } - YY_BREAK -case 228: -YY_RULE_SETUP -#line 443 "util/configlexer.lex" -{ YDVAR(1, VAR_EXTENDED_STATISTICS) } - YY_BREAK -case 229: -YY_RULE_SETUP -#line 444 "util/configlexer.lex" -{ YDVAR(1, VAR_STATISTICS_INHIBIT_ZERO) } - YY_BREAK -case 230: -YY_RULE_SETUP -#line 445 "util/configlexer.lex" -{ YDVAR(1, VAR_SHM_ENABLE) } - YY_BREAK -case 231: -YY_RULE_SETUP -#line 446 "util/configlexer.lex" -{ YDVAR(1, VAR_SHM_KEY) } - YY_BREAK -case 232: -YY_RULE_SETUP -#line 447 "util/configlexer.lex" -{ YDVAR(0, VAR_REMOTE_CONTROL) } - YY_BREAK -case 233: -YY_RULE_SETUP -#line 448 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_ENABLE) } - YY_BREAK -case 234: -YY_RULE_SETUP -#line 449 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_INTERFACE) } - YY_BREAK -case 235: -YY_RULE_SETUP -#line 450 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_PORT) } - YY_BREAK -case 236: -YY_RULE_SETUP -#line 451 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_USE_CERT) } - YY_BREAK -case 237: -YY_RULE_SETUP -#line 452 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVER_KEY_FILE) } - YY_BREAK -case 238: -YY_RULE_SETUP -#line 453 "util/configlexer.lex" -{ YDVAR(1, VAR_SERVER_CERT_FILE) } - YY_BREAK -case 239: -YY_RULE_SETUP -#line 454 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_KEY_FILE) } - YY_BREAK -case 240: -YY_RULE_SETUP -#line 455 "util/configlexer.lex" -{ YDVAR(1, VAR_CONTROL_CERT_FILE) } - YY_BREAK -case 241: -YY_RULE_SETUP -#line 456 "util/configlexer.lex" -{ YDVAR(1, VAR_PYTHON_SCRIPT) } - YY_BREAK -case 242: -YY_RULE_SETUP -#line 457 "util/configlexer.lex" -{ YDVAR(0, VAR_PYTHON) } - YY_BREAK -case 243: -YY_RULE_SETUP -#line 458 "util/configlexer.lex" -{ YDVAR(1, VAR_DYNLIB_FILE) } - YY_BREAK -case 244: -YY_RULE_SETUP -#line 459 "util/configlexer.lex" -{ YDVAR(0, VAR_DYNLIB) } - YY_BREAK -case 245: -YY_RULE_SETUP -#line 460 "util/configlexer.lex" -{ YDVAR(1, VAR_DOMAIN_INSECURE) } - YY_BREAK -case 246: -YY_RULE_SETUP -#line 461 "util/configlexer.lex" -{ YDVAR(1, VAR_MINIMAL_RESPONSES) } - YY_BREAK -case 247: -YY_RULE_SETUP -#line 462 "util/configlexer.lex" -{ YDVAR(1, VAR_RRSET_ROUNDROBIN) } - YY_BREAK -case 248: -YY_RULE_SETUP -#line 463 "util/configlexer.lex" -{ YDVAR(1, VAR_UNKNOWN_SERVER_TIME_LIMIT) } - YY_BREAK -case 249: -YY_RULE_SETUP -#line 464 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_UDP_SIZE) } - YY_BREAK -case 250: -YY_RULE_SETUP -#line 465 "util/configlexer.lex" -{ YDVAR(1, VAR_DNS64_PREFIX) } - YY_BREAK -case 251: -YY_RULE_SETUP -#line 466 "util/configlexer.lex" -{ YDVAR(1, VAR_DNS64_SYNTHALL) } - YY_BREAK -case 252: -YY_RULE_SETUP -#line 467 "util/configlexer.lex" -{ YDVAR(1, VAR_DNS64_IGNORE_AAAA) } - YY_BREAK -case 253: -YY_RULE_SETUP -#line 468 "util/configlexer.lex" -{ YDVAR(1, VAR_NAT64_PREFIX) } - YY_BREAK -case 254: -YY_RULE_SETUP -#line 469 "util/configlexer.lex" -{ YDVAR(1, VAR_DEFINE_TAG) } - YY_BREAK -case 255: -YY_RULE_SETUP -#line 470 "util/configlexer.lex" -{ YDVAR(2, VAR_LOCAL_ZONE_TAG) } - YY_BREAK -case 256: -YY_RULE_SETUP -#line 471 "util/configlexer.lex" -{ YDVAR(2, VAR_ACCESS_CONTROL_TAG) } - YY_BREAK -case 257: -YY_RULE_SETUP -#line 472 "util/configlexer.lex" -{ YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) } - YY_BREAK -case 258: -YY_RULE_SETUP -#line 473 "util/configlexer.lex" -{ YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) } - YY_BREAK -case 259: -YY_RULE_SETUP -#line 474 "util/configlexer.lex" -{ YDVAR(2, VAR_ACCESS_CONTROL_VIEW) } - YY_BREAK -case 260: -YY_RULE_SETUP -#line 475 "util/configlexer.lex" -{ YDVAR(2, VAR_INTERFACE_TAG) } - YY_BREAK -case 261: -YY_RULE_SETUP -#line 476 "util/configlexer.lex" -{ YDVAR(3, VAR_INTERFACE_TAG_ACTION) } - YY_BREAK -case 262: -YY_RULE_SETUP -#line 477 "util/configlexer.lex" -{ YDVAR(3, VAR_INTERFACE_TAG_DATA) } - YY_BREAK -case 263: -YY_RULE_SETUP -#line 478 "util/configlexer.lex" -{ YDVAR(2, VAR_INTERFACE_VIEW) } - YY_BREAK -case 264: -YY_RULE_SETUP -#line 479 "util/configlexer.lex" -{ YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) } - YY_BREAK -case 265: -YY_RULE_SETUP -#line 480 "util/configlexer.lex" -{ YDVAR(0, VAR_DNSTAP) } - YY_BREAK -case 266: -YY_RULE_SETUP -#line 481 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_ENABLE) } - YY_BREAK -case 267: -YY_RULE_SETUP -#line 482 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_BIDIRECTIONAL) } - YY_BREAK -case 268: -YY_RULE_SETUP -#line 483 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_SOCKET_PATH) } - YY_BREAK -case 269: -YY_RULE_SETUP -#line 484 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_IP) } - YY_BREAK -case 270: -YY_RULE_SETUP -#line 485 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_TLS) } - YY_BREAK -case 271: -YY_RULE_SETUP -#line 486 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_TLS_SERVER_NAME) } - YY_BREAK -case 272: -YY_RULE_SETUP -#line 487 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_TLS_CERT_BUNDLE) } - YY_BREAK -case 273: -YY_RULE_SETUP -#line 488 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_TLS_CLIENT_KEY_FILE) } - YY_BREAK -case 274: -YY_RULE_SETUP -#line 490 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_TLS_CLIENT_CERT_FILE) } - YY_BREAK -case 275: -YY_RULE_SETUP -#line 492 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_SEND_IDENTITY) } - YY_BREAK -case 276: -YY_RULE_SETUP -#line 493 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_SEND_VERSION) } - YY_BREAK -case 277: -YY_RULE_SETUP -#line 494 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_IDENTITY) } - YY_BREAK -case 278: -YY_RULE_SETUP -#line 495 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSTAP_VERSION) } - YY_BREAK -case 279: -YY_RULE_SETUP -#line 496 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES) } - YY_BREAK -case 280: -YY_RULE_SETUP -#line 498 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES) } - YY_BREAK -case 281: -YY_RULE_SETUP -#line 500 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES) } - YY_BREAK -case 282: -YY_RULE_SETUP -#line 502 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES) } - YY_BREAK -case 283: -YY_RULE_SETUP -#line 504 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) } - YY_BREAK -case 284: -YY_RULE_SETUP -#line 506 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } - YY_BREAK -case 285: -YY_RULE_SETUP -#line 508 "util/configlexer.lex" -{ YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) } - YY_BREAK -case 286: -YY_RULE_SETUP -#line 509 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT) } - YY_BREAK -case 287: -YY_RULE_SETUP -#line 510 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT_COOKIE) } - YY_BREAK -case 288: -YY_RULE_SETUP -#line 511 "util/configlexer.lex" -{ YDVAR(1, VAR_RATELIMIT) } - YY_BREAK -case 289: -YY_RULE_SETUP -#line 512 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT_SLABS) } - YY_BREAK -case 290: -YY_RULE_SETUP -#line 513 "util/configlexer.lex" -{ YDVAR(1, VAR_RATELIMIT_SLABS) } - YY_BREAK -case 291: -YY_RULE_SETUP -#line 514 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT_SIZE) } - YY_BREAK -case 292: -YY_RULE_SETUP -#line 515 "util/configlexer.lex" -{ YDVAR(1, VAR_RATELIMIT_SIZE) } - YY_BREAK -case 293: -YY_RULE_SETUP -#line 516 "util/configlexer.lex" -{ YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) } - YY_BREAK -case 294: -YY_RULE_SETUP -#line 517 "util/configlexer.lex" -{ YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) } - YY_BREAK -case 295: -YY_RULE_SETUP -#line 518 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT_FACTOR) } - YY_BREAK -case 296: -YY_RULE_SETUP -#line 519 "util/configlexer.lex" -{ YDVAR(1, VAR_RATELIMIT_FACTOR) } - YY_BREAK -case 297: -YY_RULE_SETUP -#line 520 "util/configlexer.lex" -{ YDVAR(1, VAR_IP_RATELIMIT_BACKOFF) } - YY_BREAK -case 298: -YY_RULE_SETUP -#line 521 "util/configlexer.lex" -{ YDVAR(1, VAR_RATELIMIT_BACKOFF) } - YY_BREAK -case 299: -YY_RULE_SETUP -#line 522 "util/configlexer.lex" -{ YDVAR(1, VAR_OUTBOUND_MSG_RETRY) } - YY_BREAK -case 300: -YY_RULE_SETUP -#line 523 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_SENT_COUNT) } - YY_BREAK -case 301: -YY_RULE_SETUP -#line 524 "util/configlexer.lex" -{ YDVAR(1, VAR_MAX_QUERY_RESTARTS) } - YY_BREAK -case 302: -YY_RULE_SETUP -#line 525 "util/configlexer.lex" -{ YDVAR(1, VAR_LOW_RTT) } - YY_BREAK -case 303: -YY_RULE_SETUP -#line 526 "util/configlexer.lex" -{ YDVAR(1, VAR_FAST_SERVER_NUM) } - YY_BREAK -case 304: -YY_RULE_SETUP -#line 527 "util/configlexer.lex" -{ YDVAR(1, VAR_FAST_SERVER_PERMIL) } - YY_BREAK -case 305: -YY_RULE_SETUP -#line 528 "util/configlexer.lex" -{ YDVAR(1, VAR_FAST_SERVER_PERMIL) } - YY_BREAK -case 306: -YY_RULE_SETUP -#line 529 "util/configlexer.lex" -{ YDVAR(1, VAR_FAST_SERVER_PERMIL) } - YY_BREAK -case 307: -YY_RULE_SETUP -#line 530 "util/configlexer.lex" -{ YDVAR(2, VAR_RESPONSE_IP_TAG) } - YY_BREAK -case 308: -YY_RULE_SETUP -#line 531 "util/configlexer.lex" -{ YDVAR(2, VAR_RESPONSE_IP) } - YY_BREAK -case 309: -YY_RULE_SETUP -#line 532 "util/configlexer.lex" -{ YDVAR(2, VAR_RESPONSE_IP_DATA) } - YY_BREAK -case 310: -YY_RULE_SETUP -#line 533 "util/configlexer.lex" -{ YDVAR(0, VAR_DNSCRYPT) } - YY_BREAK -case 311: -YY_RULE_SETUP -#line 534 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_ENABLE) } - YY_BREAK -case 312: -YY_RULE_SETUP -#line 535 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_PORT) } - YY_BREAK -case 313: -YY_RULE_SETUP -#line 536 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_PROVIDER) } - YY_BREAK -case 314: -YY_RULE_SETUP -#line 537 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_SECRET_KEY) } - YY_BREAK -case 315: -YY_RULE_SETUP -#line 538 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_PROVIDER_CERT) } - YY_BREAK -case 316: -YY_RULE_SETUP -#line 539 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_PROVIDER_CERT_ROTATED) } - YY_BREAK -case 317: -YY_RULE_SETUP -#line 540 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE) } - YY_BREAK -case 318: -YY_RULE_SETUP -#line 542 "util/configlexer.lex" -{ - YDVAR(1, VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS) } - YY_BREAK -case 319: -YY_RULE_SETUP -#line 544 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_NONCE_CACHE_SIZE) } - YY_BREAK -case 320: -YY_RULE_SETUP -#line 545 "util/configlexer.lex" -{ YDVAR(1, VAR_DNSCRYPT_NONCE_CACHE_SLABS) } - YY_BREAK -case 321: -YY_RULE_SETUP -#line 546 "util/configlexer.lex" -{ YDVAR(1, VAR_PAD_RESPONSES) } - YY_BREAK -case 322: -YY_RULE_SETUP -#line 547 "util/configlexer.lex" -{ YDVAR(1, VAR_PAD_RESPONSES_BLOCK_SIZE) } - YY_BREAK -case 323: -YY_RULE_SETUP -#line 548 "util/configlexer.lex" -{ YDVAR(1, VAR_PAD_QUERIES) } - YY_BREAK -case 324: -YY_RULE_SETUP -#line 549 "util/configlexer.lex" -{ YDVAR(1, VAR_PAD_QUERIES_BLOCK_SIZE) } - YY_BREAK -case 325: -YY_RULE_SETUP -#line 550 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_ENABLED) } - YY_BREAK -case 326: -YY_RULE_SETUP -#line 551 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_IGNORE_BOGUS) } - YY_BREAK -case 327: -YY_RULE_SETUP -#line 552 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_HOOK) } - YY_BREAK -case 328: -YY_RULE_SETUP -#line 553 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_MAX_TTL) } - YY_BREAK -case 329: -YY_RULE_SETUP -#line 554 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_WHITELIST) } - YY_BREAK -case 330: -YY_RULE_SETUP -#line 555 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_WHITELIST) } - YY_BREAK -case 331: -YY_RULE_SETUP -#line 556 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSECMOD_STRICT) } - YY_BREAK -case 332: -YY_RULE_SETUP -#line 557 "util/configlexer.lex" -{ YDVAR(0, VAR_CACHEDB) } - YY_BREAK -case 333: -YY_RULE_SETUP -#line 558 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_BACKEND) } - YY_BREAK -case 334: -YY_RULE_SETUP -#line 559 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_SECRETSEED) } - YY_BREAK -case 335: -YY_RULE_SETUP -#line 560 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISHOST) } - YY_BREAK -case 336: -YY_RULE_SETUP -#line 561 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISPORT) } - YY_BREAK -case 337: -YY_RULE_SETUP -#line 562 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISPATH) } - YY_BREAK -case 338: -YY_RULE_SETUP -#line 563 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISPASSWORD) } - YY_BREAK -case 339: -YY_RULE_SETUP -#line 564 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) } - YY_BREAK -case 340: -YY_RULE_SETUP -#line 565 "util/configlexer.lex" -{ YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) } - YY_BREAK -case 341: -YY_RULE_SETUP -#line 566 "util/configlexer.lex" -{ YDVAR(0, VAR_IPSET) } - YY_BREAK -case 342: -YY_RULE_SETUP -#line 567 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSET_NAME_V4) } - YY_BREAK -case 343: -YY_RULE_SETUP -#line 568 "util/configlexer.lex" -{ YDVAR(1, VAR_IPSET_NAME_V6) } - YY_BREAK -case 344: -YY_RULE_SETUP -#line 569 "util/configlexer.lex" -{ YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) } - YY_BREAK -case 345: -YY_RULE_SETUP -#line 570 "util/configlexer.lex" -{ YDVAR(2, VAR_TCP_CONNECTION_LIMIT) } - YY_BREAK -case 346: -YY_RULE_SETUP -#line 571 "util/configlexer.lex" -{ YDVAR(1, VAR_ANSWER_COOKIE ) } - YY_BREAK -case 347: -YY_RULE_SETUP -#line 572 "util/configlexer.lex" -{ YDVAR(1, VAR_COOKIE_SECRET) } - YY_BREAK -case 348: -YY_RULE_SETUP -#line 573 "util/configlexer.lex" -{ YDVAR(2, VAR_EDNS_CLIENT_STRING) } - YY_BREAK -case 349: -YY_RULE_SETUP -#line 574 "util/configlexer.lex" -{ YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) } - YY_BREAK -case 350: -YY_RULE_SETUP -#line 575 "util/configlexer.lex" -{ YDVAR(1, VAR_NSID ) } - YY_BREAK -case 351: -YY_RULE_SETUP -#line 576 "util/configlexer.lex" -{ YDVAR(1, VAR_EDE ) } - YY_BREAK -case 352: -YY_RULE_SETUP -#line 577 "util/configlexer.lex" -{ YDVAR(1, VAR_PROXY_PROTOCOL_PORT) } - YY_BREAK -case 353: -/* rule 353 can match eol */ -YY_RULE_SETUP -#line 578 "util/configlexer.lex" -{ LEXOUT(("NL\n")); cfg_parser->line++; } - YY_BREAK -/* Quoted strings. Strip leading and ending quotes */ -case 354: -YY_RULE_SETUP -#line 581 "util/configlexer.lex" -{ BEGIN(quotedstring); LEXOUT(("QS ")); } - YY_BREAK -case YY_STATE_EOF(quotedstring): -#line 582 "util/configlexer.lex" -{ - yyerror("EOF inside quoted string"); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } -} - YY_BREAK -case 355: -YY_RULE_SETUP -#line 587 "util/configlexer.lex" -{ LEXOUT(("STR(%s) ", yytext)); yymore(); } - YY_BREAK -case 356: -/* rule 356 can match eol */ -YY_RULE_SETUP -#line 588 "util/configlexer.lex" -{ yyerror("newline inside quoted string, no end \""); - cfg_parser->line++; BEGIN(INITIAL); } - YY_BREAK -case 357: -YY_RULE_SETUP -#line 590 "util/configlexer.lex" -{ - LEXOUT(("QE ")); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } - yytext[yyleng - 1] = '\0'; - yylval.str = strdup(yytext); - if(!yylval.str) - yyerror("out of memory"); - return STRING_ARG; -} - YY_BREAK -/* Single Quoted strings. Strip leading and ending quotes */ -case 358: -YY_RULE_SETUP -#line 602 "util/configlexer.lex" -{ BEGIN(singlequotedstr); LEXOUT(("SQS ")); } - YY_BREAK -case YY_STATE_EOF(singlequotedstr): -#line 603 "util/configlexer.lex" -{ - yyerror("EOF inside quoted string"); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } -} - YY_BREAK -case 359: -YY_RULE_SETUP -#line 608 "util/configlexer.lex" -{ LEXOUT(("STR(%s) ", yytext)); yymore(); } - YY_BREAK -case 360: -/* rule 360 can match eol */ -YY_RULE_SETUP -#line 609 "util/configlexer.lex" -{ yyerror("newline inside quoted string, no end '"); - cfg_parser->line++; BEGIN(INITIAL); } - YY_BREAK -case 361: -YY_RULE_SETUP -#line 611 "util/configlexer.lex" -{ - LEXOUT(("SQE ")); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } - yytext[yyleng - 1] = '\0'; - yylval.str = strdup(yytext); - if(!yylval.str) - yyerror("out of memory"); - return STRING_ARG; -} - YY_BREAK -/* include: directive */ -case 362: -YY_RULE_SETUP -#line 623 "util/configlexer.lex" -{ - LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); } - YY_BREAK -case YY_STATE_EOF(include): -#line 625 "util/configlexer.lex" -{ - yyerror("EOF inside include directive"); - BEGIN(inc_prev); -} - YY_BREAK -case 363: -YY_RULE_SETUP -#line 629 "util/configlexer.lex" -{ LEXOUT(("ISP ")); /* ignore */ } - YY_BREAK -case 364: -/* rule 364 can match eol */ -YY_RULE_SETUP -#line 630 "util/configlexer.lex" -{ LEXOUT(("NL\n")); cfg_parser->line++;} - YY_BREAK -case 365: -YY_RULE_SETUP -#line 631 "util/configlexer.lex" -{ LEXOUT(("IQS ")); BEGIN(include_quoted); } - YY_BREAK -case 366: -YY_RULE_SETUP -#line 632 "util/configlexer.lex" -{ - LEXOUT(("Iunquotedstr(%s) ", yytext)); - config_start_include_glob(yytext, 0); - BEGIN(inc_prev); -} - YY_BREAK -case YY_STATE_EOF(include_quoted): -#line 637 "util/configlexer.lex" -{ - yyerror("EOF inside quoted string"); - BEGIN(inc_prev); -} - YY_BREAK -case 367: -YY_RULE_SETUP -#line 641 "util/configlexer.lex" -{ LEXOUT(("ISTR(%s) ", yytext)); yymore(); } - YY_BREAK -case 368: -/* rule 368 can match eol */ -YY_RULE_SETUP -#line 642 "util/configlexer.lex" -{ yyerror("newline before \" in include name"); - cfg_parser->line++; BEGIN(inc_prev); } - YY_BREAK -case 369: -YY_RULE_SETUP -#line 644 "util/configlexer.lex" -{ - LEXOUT(("IQE ")); - yytext[yyleng - 1] = '\0'; - config_start_include_glob(yytext, 0); - BEGIN(inc_prev); -} - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(val): -#line 650 "util/configlexer.lex" -{ - LEXOUT(("LEXEOF ")); - yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ - if (!config_include_stack) { - yyterminate(); - } else { - int prev_toplevel = inc_toplevel; - fclose(yyin); - config_end_include(); - if(prev_toplevel) return (VAR_FORCE_TOPLEVEL); - } -} - YY_BREAK -/* include-toplevel: directive */ -case 370: -YY_RULE_SETUP -#line 664 "util/configlexer.lex" -{ - LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include_toplevel); -} - YY_BREAK -case YY_STATE_EOF(include_toplevel): -#line 667 "util/configlexer.lex" -{ - yyerror("EOF inside include_toplevel directive"); - BEGIN(inc_prev); -} - YY_BREAK -case 371: -YY_RULE_SETUP -#line 671 "util/configlexer.lex" -{ LEXOUT(("ITSP ")); /* ignore */ } - YY_BREAK -case 372: -/* rule 372 can match eol */ -YY_RULE_SETUP -#line 672 "util/configlexer.lex" -{ LEXOUT(("NL\n")); cfg_parser->line++; } - YY_BREAK -case 373: -YY_RULE_SETUP -#line 673 "util/configlexer.lex" -{ LEXOUT(("ITQS ")); BEGIN(include_toplevel_quoted); } - YY_BREAK -case 374: -YY_RULE_SETUP -#line 674 "util/configlexer.lex" -{ - LEXOUT(("ITunquotedstr(%s) ", yytext)); - config_start_include_glob(yytext, 1); - BEGIN(inc_prev); - return (VAR_FORCE_TOPLEVEL); -} - YY_BREAK -case YY_STATE_EOF(include_toplevel_quoted): -#line 680 "util/configlexer.lex" -{ - yyerror("EOF inside quoted string"); - BEGIN(inc_prev); -} - YY_BREAK -case 375: -YY_RULE_SETUP -#line 684 "util/configlexer.lex" -{ LEXOUT(("ITSTR(%s) ", yytext)); yymore(); } - YY_BREAK -case 376: -/* rule 376 can match eol */ -YY_RULE_SETUP -#line 685 "util/configlexer.lex" -{ - yyerror("newline before \" in include name"); - cfg_parser->line++; BEGIN(inc_prev); -} - YY_BREAK -case 377: -YY_RULE_SETUP -#line 689 "util/configlexer.lex" -{ - LEXOUT(("ITQE ")); - yytext[yyleng - 1] = '\0'; - config_start_include_glob(yytext, 1); - BEGIN(inc_prev); - return (VAR_FORCE_TOPLEVEL); -} - YY_BREAK -case 378: -YY_RULE_SETUP -#line 697 "util/configlexer.lex" -{ LEXOUT(("unquotedstr(%s) ", yytext)); - if(--num_args == 0) { BEGIN(INITIAL); } - yylval.str = strdup(yytext); return STRING_ARG; } - YY_BREAK -case 379: -YY_RULE_SETUP -#line 701 "util/configlexer.lex" -{ - ub_c_error_msg("unknown keyword '%s'", yytext); - } - YY_BREAK -case 380: -YY_RULE_SETUP -#line 705 "util/configlexer.lex" -{ - ub_c_error_msg("stray '%s'", yytext); - } - YY_BREAK -case 381: -YY_RULE_SETUP -#line 709 "util/configlexer.lex" -ECHO; - YY_BREAK -#line 6594 "" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( yywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of yylex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = (yytext_ptr); - int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yyrealloc( (void *) b->yy_ch_buf, - (yy_size_t) (b->yy_buf_size + 2) ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( - (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - /* "- 2" to take care of EOB's */ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - yy_state_type yy_current_state; - char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 3778 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - int yy_is_jam; - char *yy_cp = (yy_c_buf_p); - - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 3778 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 3777); - - return yy_is_jam ? 0 : yy_current_state; -} - -#ifndef YY_NO_UNPUT - -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap( ) ) - return 0; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE ); - } - - yy_init_buffer( YY_CURRENT_BUFFER, input_file ); - yy_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void yy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yy_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yyfree( (void *) b->yy_ch_buf ); - - yyfree( (void *) b ); -} - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void yyensure_buffer_stack (void) -{ - yy_size_t num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return NULL; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (const char * yystr ) -{ - - return yy_scan_bytes( yystr, (int) strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) (_yybytes_len + 2); - buf = (char *) yyalloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yynoreturn yy_fatal_error (const char* msg ) -{ - fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int yyget_lineno (void) -{ - - return yylineno; -} - -/** Get the input stream. - * - */ -FILE *yyget_in (void) -{ - return yyin; -} - -/** Get the output stream. - * - */ -FILE *yyget_out (void) -{ - return yyout; -} - -/** Get the length of the current token. - * - */ -int yyget_leng (void) -{ - return yyleng; -} - -/** Get the current token. - * - */ - -char *yyget_text (void) -{ - return yytext; -} - -/** Set the current line number. - * @param _line_number line number - * - */ -void yyset_lineno (int _line_number ) -{ - - yylineno = _line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param _in_str A readable stream. - * - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * _in_str ) -{ - yyin = _in_str ; -} - -void yyset_out (FILE * _out_str ) -{ - yyout = _out_str ; -} - -int yyget_debug (void) -{ - return yy_flex_debug; -} - -void yyset_debug (int _bdebug ) -{ - yy_flex_debug = _bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = NULL; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = NULL; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; -#else - yyin = NULL; - yyout = NULL; -#endif - - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} - -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer( YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(); - } - - /* Destroy the stack itself. */ - yyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, const char * s2, int n ) -{ - - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (const char * s ) -{ - int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *yyalloc (yy_size_t size ) -{ - return malloc(size); -} - -void *yyrealloc (void * ptr, yy_size_t size ) -{ - - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return realloc(ptr, size); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 709 "util/configlexer.lex" - - diff --git a/crates/libunbound-sys/unbound/util/configlexer.lex b/crates/libunbound-sys/unbound/util/configlexer.lex deleted file mode 100644 index 3fcdfa62..00000000 --- a/crates/libunbound-sys/unbound/util/configlexer.lex +++ /dev/null @@ -1,709 +0,0 @@ -%{ -/* - * configlexer.lex - lexical analyzer for unbound config file - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved - * - * See LICENSE for the license. - * - */ - -/* because flex keeps having sign-unsigned compare problems that are unfixed*/ -#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2)))) -#pragma GCC diagnostic ignored "-Wsign-compare" -#endif - -#include -#include -#ifdef HAVE_GLOB_H -# include -#endif - -#include "util/config_file.h" -#include "util/configparser.h" -void ub_c_error(const char *message); - -#if 0 -#define LEXOUT(s) printf s /* used ONLY when debugging */ -#else -#define LEXOUT(s) -#endif - -/** avoid warning in about fwrite return value */ -#define ECHO ub_c_error_msg("syntax error at text: %s", yytext) - -/** A parser variable, this is a statement in the config file which is - * of the form variable: value1 value2 ... nargs is the number of values. */ -#define YDVAR(nargs, var) \ - num_args=(nargs); \ - LEXOUT(("v(%s%d) ", yytext, num_args)); \ - if(num_args > 0) { BEGIN(val); } \ - return (var); - -struct inc_state { - char* filename; - int line; - YY_BUFFER_STATE buffer; - struct inc_state* next; - int inc_toplevel; -}; -static struct inc_state* config_include_stack = NULL; -static int inc_depth = 0; -static int inc_prev = 0; -static int num_args = 0; -static int inc_toplevel = 0; - -void init_cfg_parse(void) -{ - config_include_stack = NULL; - inc_depth = 0; - inc_prev = 0; - num_args = 0; - inc_toplevel = 0; -} - -static void config_start_include(const char* filename, int toplevel) -{ - FILE *input; - struct inc_state* s; - char* nm; - if(inc_depth+1 > 100000) { - ub_c_error_msg("too many include files"); - return; - } - if(*filename == '\0') { - ub_c_error_msg("empty include file name"); - return; - } - s = (struct inc_state*)malloc(sizeof(*s)); - if(!s) { - ub_c_error_msg("include %s: malloc failure", filename); - return; - } - if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, - strlen(cfg_parser->chroot)) == 0) { - filename += strlen(cfg_parser->chroot); - } - nm = strdup(filename); - if(!nm) { - ub_c_error_msg("include %s: strdup failure", filename); - free(s); - return; - } - input = fopen(filename, "r"); - if(!input) { - ub_c_error_msg("cannot open include file '%s': %s", - filename, strerror(errno)); - free(s); - free(nm); - return; - } - LEXOUT(("switch_to_include_file(%s)\n", filename)); - inc_depth++; - s->filename = cfg_parser->filename; - s->line = cfg_parser->line; - s->buffer = YY_CURRENT_BUFFER; - s->inc_toplevel = inc_toplevel; - s->next = config_include_stack; - config_include_stack = s; - cfg_parser->filename = nm; - cfg_parser->line = 1; - inc_toplevel = toplevel; - yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE)); -} - -static void config_start_include_glob(const char* filename, int toplevel) -{ - - /* check for wildcards */ -#ifdef HAVE_GLOB - glob_t g; - int i, r, flags; - if(!(!strchr(filename, '*') && !strchr(filename, '?') && !strchr(filename, '[') && - !strchr(filename, '{') && !strchr(filename, '~'))) { - flags = 0 -#ifdef GLOB_ERR - | GLOB_ERR -#endif - /* do not set GLOB_NOSORT so the results are sorted - and in a predictable order. */ -#ifdef GLOB_BRACE - | GLOB_BRACE -#endif -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif - ; - memset(&g, 0, sizeof(g)); - if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, - strlen(cfg_parser->chroot)) == 0) { - filename += strlen(cfg_parser->chroot); - } - r = glob(filename, flags, NULL, &g); - if(r) { - /* some error */ - globfree(&g); - if(r == GLOB_NOMATCH) - return; /* no matches for pattern */ - config_start_include(filename, toplevel); /* let original deal with it */ - return; - } - /* process files found, if any */ - for(i=(int)g.gl_pathc-1; i>=0; i--) { - config_start_include(g.gl_pathv[i], toplevel); - } - globfree(&g); - return; - } -#endif /* HAVE_GLOB */ - - config_start_include(filename, toplevel); -} - -static void config_end_include(void) -{ - struct inc_state* s = config_include_stack; - --inc_depth; - if(!s) return; - free(cfg_parser->filename); - cfg_parser->filename = s->filename; - cfg_parser->line = s->line; - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(s->buffer); - config_include_stack = s->next; - inc_toplevel = s->inc_toplevel; - free(s); -} - -#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ - } -#endif - -%} -%option noinput -%option nounput -%{ -#ifndef YY_NO_UNPUT -#define YY_NO_UNPUT 1 -#endif -#ifndef YY_NO_INPUT -#define YY_NO_INPUT 1 -#endif -%} - -SPACE [ \t] -LETTER [a-zA-Z] -UNQUOTEDLETTER [^\'\"\n\r \t\\]|\\. -UNQUOTEDLETTER_NOCOLON [^\:\'\"\n\r \t\\]|\\. -NEWLINE [\r\n] -COMMENT \# -COLON \: -DQANY [^\"\n\r\\]|\\. -SQANY [^\'\n\r\\]|\\. - -%x quotedstring singlequotedstr include include_quoted val include_toplevel include_toplevel_quoted - -%% -{SPACE}* { - LEXOUT(("SP ")); /* ignore */ } -{SPACE}*{COMMENT}.* { - /* note that flex makes the longest match and '.' is any but not nl */ - LEXOUT(("comment(%s) ", yytext)); /* ignore */ } -server{COLON} { YDVAR(0, VAR_SERVER) } -qname-minimisation{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION) } -qname-minimisation-strict{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION_STRICT) } -num-threads{COLON} { YDVAR(1, VAR_NUM_THREADS) } -verbosity{COLON} { YDVAR(1, VAR_VERBOSITY) } -port{COLON} { YDVAR(1, VAR_PORT) } -outgoing-range{COLON} { YDVAR(1, VAR_OUTGOING_RANGE) } -outgoing-port-permit{COLON} { YDVAR(1, VAR_OUTGOING_PORT_PERMIT) } -outgoing-port-avoid{COLON} { YDVAR(1, VAR_OUTGOING_PORT_AVOID) } -outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) } -incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) } -do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) } -do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) } -do-nat64{COLON} { YDVAR(1, VAR_DO_NAT64) } -prefer-ip4{COLON} { YDVAR(1, VAR_PREFER_IP4) } -prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) } -do-udp{COLON} { YDVAR(1, VAR_DO_UDP) } -do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) } -tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) } -tcp-mss{COLON} { YDVAR(1, VAR_TCP_MSS) } -outgoing-tcp-mss{COLON} { YDVAR(1, VAR_OUTGOING_TCP_MSS) } -tcp-idle-timeout{COLON} { YDVAR(1, VAR_TCP_IDLE_TIMEOUT) } -max-reuse-tcp-queries{COLON} { YDVAR(1, VAR_MAX_REUSE_TCP_QUERIES) } -tcp-reuse-timeout{COLON} { YDVAR(1, VAR_TCP_REUSE_TIMEOUT) } -tcp-auth-query-timeout{COLON} { YDVAR(1, VAR_TCP_AUTH_QUERY_TIMEOUT) } -edns-tcp-keepalive{COLON} { YDVAR(1, VAR_EDNS_TCP_KEEPALIVE) } -edns-tcp-keepalive-timeout{COLON} { YDVAR(1, VAR_EDNS_TCP_KEEPALIVE_TIMEOUT) } -sock-queue-timeout{COLON} { YDVAR(1, VAR_SOCK_QUEUE_TIMEOUT) } -ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } -tls-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } -ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) } -tls-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) } -ssl-service-pem{COLON} { YDVAR(1, VAR_SSL_SERVICE_PEM) } -tls-service-pem{COLON} { YDVAR(1, VAR_SSL_SERVICE_PEM) } -ssl-port{COLON} { YDVAR(1, VAR_SSL_PORT) } -tls-port{COLON} { YDVAR(1, VAR_SSL_PORT) } -ssl-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) } -tls-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) } -tls-win-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) } -tls-system-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) } -additional-ssl-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } -additional-tls-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } -tls-additional-ports{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } -tls-additional-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } -tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) } -tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) } -tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) } -tls-use-sni{COLON} { YDVAR(1, VAR_TLS_USE_SNI) } -https-port{COLON} { YDVAR(1, VAR_HTTPS_PORT) } -http-endpoint{COLON} { YDVAR(1, VAR_HTTP_ENDPOINT) } -http-max-streams{COLON} { YDVAR(1, VAR_HTTP_MAX_STREAMS) } -http-query-buffer-size{COLON} { YDVAR(1, VAR_HTTP_QUERY_BUFFER_SIZE) } -http-response-buffer-size{COLON} { YDVAR(1, VAR_HTTP_RESPONSE_BUFFER_SIZE) } -http-nodelay{COLON} { YDVAR(1, VAR_HTTP_NODELAY) } -http-notls-downstream{COLON} { YDVAR(1, VAR_HTTP_NOTLS_DOWNSTREAM) } -use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) } -do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) } -interface{COLON} { YDVAR(1, VAR_INTERFACE) } -ip-address{COLON} { YDVAR(1, VAR_INTERFACE) } -outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) } -interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) } -interface-automatic-ports{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC_PORTS) } -so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) } -so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) } -so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) } -ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) } -ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) } -ip-dscp{COLON} { YDVAR(1, VAR_IP_DSCP) } -chroot{COLON} { YDVAR(1, VAR_CHROOT) } -username{COLON} { YDVAR(1, VAR_USERNAME) } -directory{COLON} { YDVAR(1, VAR_DIRECTORY) } -logfile{COLON} { YDVAR(1, VAR_LOGFILE) } -pidfile{COLON} { YDVAR(1, VAR_PIDFILE) } -root-hints{COLON} { YDVAR(1, VAR_ROOT_HINTS) } -stream-wait-size{COLON} { YDVAR(1, VAR_STREAM_WAIT_SIZE) } -edns-buffer-size{COLON} { YDVAR(1, VAR_EDNS_BUFFER_SIZE) } -msg-buffer-size{COLON} { YDVAR(1, VAR_MSG_BUFFER_SIZE) } -msg-cache-size{COLON} { YDVAR(1, VAR_MSG_CACHE_SIZE) } -msg-cache-slabs{COLON} { YDVAR(1, VAR_MSG_CACHE_SLABS) } -rrset-cache-size{COLON} { YDVAR(1, VAR_RRSET_CACHE_SIZE) } -rrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) } -cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) } -cache-max-negative-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_NEGATIVE_TTL) } -cache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) } -infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) } -infra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_TTL) } -infra-cache-slabs{COLON} { YDVAR(1, VAR_INFRA_CACHE_SLABS) } -infra-cache-numhosts{COLON} { YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) } -infra-cache-lame-size{COLON} { YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) } -infra-cache-min-rtt{COLON} { YDVAR(1, VAR_INFRA_CACHE_MIN_RTT) } -infra-cache-max-rtt{COLON} { YDVAR(1, VAR_INFRA_CACHE_MAX_RTT) } -infra-keep-probing{COLON} { YDVAR(1, VAR_INFRA_KEEP_PROBING) } -num-queries-per-thread{COLON} { YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) } -jostle-timeout{COLON} { YDVAR(1, VAR_JOSTLE_TIMEOUT) } -delay-close{COLON} { YDVAR(1, VAR_DELAY_CLOSE) } -udp-connect{COLON} { YDVAR(1, VAR_UDP_CONNECT) } -target-fetch-policy{COLON} { YDVAR(1, VAR_TARGET_FETCH_POLICY) } -harden-short-bufsize{COLON} { YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) } -harden-large-queries{COLON} { YDVAR(1, VAR_HARDEN_LARGE_QUERIES) } -harden-glue{COLON} { YDVAR(1, VAR_HARDEN_GLUE) } -harden-dnssec-stripped{COLON} { YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) } -harden-below-nxdomain{COLON} { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) } -harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) } -harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) } -harden-unknown-additional{COLON} { YDVAR(1, VAR_HARDEN_UNKNOWN_ADDITIONAL) } -use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) } -caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) } -caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) } -unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) } -private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) } -private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) } -prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) } -prefetch{COLON} { YDVAR(1, VAR_PREFETCH) } -deny-any{COLON} { YDVAR(1, VAR_DENY_ANY) } -stub-zone{COLON} { YDVAR(0, VAR_STUB_ZONE) } -name{COLON} { YDVAR(1, VAR_NAME) } -stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) } -stub-host{COLON} { YDVAR(1, VAR_STUB_HOST) } -stub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) } -stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) } -stub-no-cache{COLON} { YDVAR(1, VAR_STUB_NO_CACHE) } -stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } -stub-tls-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } -stub-tcp-upstream{COLON} { YDVAR(1, VAR_STUB_TCP_UPSTREAM) } -forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) } -forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) } -forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) } -forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) } -forward-no-cache{COLON} { YDVAR(1, VAR_FORWARD_NO_CACHE) } -forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } -forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } -forward-tcp-upstream{COLON} { YDVAR(1, VAR_FORWARD_TCP_UPSTREAM) } -auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) } -rpz{COLON} { YDVAR(0, VAR_RPZ) } -tags{COLON} { YDVAR(1, VAR_TAGS) } -rpz-action-override{COLON} { YDVAR(1, VAR_RPZ_ACTION_OVERRIDE) } -rpz-cname-override{COLON} { YDVAR(1, VAR_RPZ_CNAME_OVERRIDE) } -rpz-log{COLON} { YDVAR(1, VAR_RPZ_LOG) } -rpz-log-name{COLON} { YDVAR(1, VAR_RPZ_LOG_NAME) } -rpz-signal-nxdomain-ra{COLON} { YDVAR(1, VAR_RPZ_SIGNAL_NXDOMAIN_RA) } -zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) } -master{COLON} { YDVAR(1, VAR_MASTER) } -primary{COLON} { YDVAR(1, VAR_MASTER) } -url{COLON} { YDVAR(1, VAR_URL) } -allow-notify{COLON} { YDVAR(1, VAR_ALLOW_NOTIFY) } -for-downstream{COLON} { YDVAR(1, VAR_FOR_DOWNSTREAM) } -for-upstream{COLON} { YDVAR(1, VAR_FOR_UPSTREAM) } -fallback-enabled{COLON} { YDVAR(1, VAR_FALLBACK_ENABLED) } -view{COLON} { YDVAR(0, VAR_VIEW) } -view-first{COLON} { YDVAR(1, VAR_VIEW_FIRST) } -do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) } -do-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) } -access-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) } -interface-action{COLON} { YDVAR(2, VAR_INTERFACE_ACTION) } -send-client-subnet{COLON} { YDVAR(1, VAR_SEND_CLIENT_SUBNET) } -client-subnet-zone{COLON} { YDVAR(1, VAR_CLIENT_SUBNET_ZONE) } -client-subnet-always-forward{COLON} { YDVAR(1, VAR_CLIENT_SUBNET_ALWAYS_FORWARD) } -client-subnet-opcode{COLON} { YDVAR(1, VAR_CLIENT_SUBNET_OPCODE) } -max-client-subnet-ipv4{COLON} { YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV4) } -max-client-subnet-ipv6{COLON} { YDVAR(1, VAR_MAX_CLIENT_SUBNET_IPV6) } -min-client-subnet-ipv4{COLON} { YDVAR(1, VAR_MIN_CLIENT_SUBNET_IPV4) } -min-client-subnet-ipv6{COLON} { YDVAR(1, VAR_MIN_CLIENT_SUBNET_IPV6) } -max-ecs-tree-size-ipv4{COLON} { YDVAR(1, VAR_MAX_ECS_TREE_SIZE_IPV4) } -max-ecs-tree-size-ipv6{COLON} { YDVAR(1, VAR_MAX_ECS_TREE_SIZE_IPV6) } -hide-identity{COLON} { YDVAR(1, VAR_HIDE_IDENTITY) } -hide-version{COLON} { YDVAR(1, VAR_HIDE_VERSION) } -hide-trustanchor{COLON} { YDVAR(1, VAR_HIDE_TRUSTANCHOR) } -hide-http-user-agent{COLON} { YDVAR(1, VAR_HIDE_HTTP_USER_AGENT) } -identity{COLON} { YDVAR(1, VAR_IDENTITY) } -version{COLON} { YDVAR(1, VAR_VERSION) } -http-user-agent{COLON} { YDVAR(1, VAR_HTTP_USER_AGENT) } -module-config{COLON} { YDVAR(1, VAR_MODULE_CONF) } -dlv-anchor{COLON} { YDVAR(1, VAR_DLV_ANCHOR) } -dlv-anchor-file{COLON} { YDVAR(1, VAR_DLV_ANCHOR_FILE) } -trust-anchor-file{COLON} { YDVAR(1, VAR_TRUST_ANCHOR_FILE) } -auto-trust-anchor-file{COLON} { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) } -trusted-keys-file{COLON} { YDVAR(1, VAR_TRUSTED_KEYS_FILE) } -trust-anchor{COLON} { YDVAR(1, VAR_TRUST_ANCHOR) } -trust-anchor-signaling{COLON} { YDVAR(1, VAR_TRUST_ANCHOR_SIGNALING) } -root-key-sentinel{COLON} { YDVAR(1, VAR_ROOT_KEY_SENTINEL) } -val-override-date{COLON} { YDVAR(1, VAR_VAL_OVERRIDE_DATE) } -val-sig-skew-min{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } -val-sig-skew-max{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } -val-max-restart{COLON} { YDVAR(1, VAR_VAL_MAX_RESTART) } -val-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) } -val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } -val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } -aggressive-nsec{COLON} { YDVAR(1, VAR_AGGRESSIVE_NSEC) } -ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) } -serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) } -serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) } -serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) } -serve-expired-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) } -serve-expired-client-timeout{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) } -ede-serve-expired{COLON} { YDVAR(1, VAR_EDE_SERVE_EXPIRED) } -serve-original-ttl{COLON} { YDVAR(1, VAR_SERVE_ORIGINAL_TTL) } -fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) } -fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) } -val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) } -key-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) } -key-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) } -neg-cache-size{COLON} { YDVAR(1, VAR_NEG_CACHE_SIZE) } -val-nsec3-keysize-iterations{COLON} { - YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) } -zonemd-permissive-mode{COLON} { YDVAR(1, VAR_ZONEMD_PERMISSIVE_MODE) } -zonemd-check{COLON} { YDVAR(1, VAR_ZONEMD_CHECK) } -zonemd-reject-absence{COLON} { YDVAR(1, VAR_ZONEMD_REJECT_ABSENCE) } -add-holddown{COLON} { YDVAR(1, VAR_ADD_HOLDDOWN) } -del-holddown{COLON} { YDVAR(1, VAR_DEL_HOLDDOWN) } -keep-missing{COLON} { YDVAR(1, VAR_KEEP_MISSING) } -permit-small-holddown{COLON} { YDVAR(1, VAR_PERMIT_SMALL_HOLDDOWN) } -use-syslog{COLON} { YDVAR(1, VAR_USE_SYSLOG) } -log-identity{COLON} { YDVAR(1, VAR_LOG_IDENTITY) } -log-time-ascii{COLON} { YDVAR(1, VAR_LOG_TIME_ASCII) } -log-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) } -log-replies{COLON} { YDVAR(1, VAR_LOG_REPLIES) } -log-tag-queryreply{COLON} { YDVAR(1, VAR_LOG_TAG_QUERYREPLY) } -log-local-actions{COLON} { YDVAR(1, VAR_LOG_LOCAL_ACTIONS) } -log-servfail{COLON} { YDVAR(1, VAR_LOG_SERVFAIL) } -local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) } -local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) } -local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) } -unblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) } -insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) } -statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) } -statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) } -extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) } -statistics-inhibit-zero{COLON} { YDVAR(1, VAR_STATISTICS_INHIBIT_ZERO) } -shm-enable{COLON} { YDVAR(1, VAR_SHM_ENABLE) } -shm-key{COLON} { YDVAR(1, VAR_SHM_KEY) } -remote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) } -control-enable{COLON} { YDVAR(1, VAR_CONTROL_ENABLE) } -control-interface{COLON} { YDVAR(1, VAR_CONTROL_INTERFACE) } -control-port{COLON} { YDVAR(1, VAR_CONTROL_PORT) } -control-use-cert{COLON} { YDVAR(1, VAR_CONTROL_USE_CERT) } -server-key-file{COLON} { YDVAR(1, VAR_SERVER_KEY_FILE) } -server-cert-file{COLON} { YDVAR(1, VAR_SERVER_CERT_FILE) } -control-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) } -control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) } -python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) } -python{COLON} { YDVAR(0, VAR_PYTHON) } -dynlib-file{COLON} { YDVAR(1, VAR_DYNLIB_FILE) } -dynlib{COLON} { YDVAR(0, VAR_DYNLIB) } -domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) } -minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) } -rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) } -unknown-server-time-limit{COLON} { YDVAR(1, VAR_UNKNOWN_SERVER_TIME_LIMIT) } -max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) } -dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) } -dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) } -dns64-ignore-aaaa{COLON} { YDVAR(1, VAR_DNS64_IGNORE_AAAA) } -nat64-prefix{COLON} { YDVAR(1, VAR_NAT64_PREFIX) } -define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) } -local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) } -access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) } -access-control-tag-action{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) } -access-control-tag-data{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) } -access-control-view{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_VIEW) } -interface-tag{COLON} { YDVAR(2, VAR_INTERFACE_TAG) } -interface-tag-action{COLON} { YDVAR(3, VAR_INTERFACE_TAG_ACTION) } -interface-tag-data{COLON} { YDVAR(3, VAR_INTERFACE_TAG_DATA) } -interface-view{COLON} { YDVAR(2, VAR_INTERFACE_VIEW) } -local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) } -dnstap{COLON} { YDVAR(0, VAR_DNSTAP) } -dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) } -dnstap-bidirectional{COLON} { YDVAR(1, VAR_DNSTAP_BIDIRECTIONAL) } -dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) } -dnstap-ip{COLON} { YDVAR(1, VAR_DNSTAP_IP) } -dnstap-tls{COLON} { YDVAR(1, VAR_DNSTAP_TLS) } -dnstap-tls-server-name{COLON} { YDVAR(1, VAR_DNSTAP_TLS_SERVER_NAME) } -dnstap-tls-cert-bundle{COLON} { YDVAR(1, VAR_DNSTAP_TLS_CERT_BUNDLE) } -dnstap-tls-client-key-file{COLON} { - YDVAR(1, VAR_DNSTAP_TLS_CLIENT_KEY_FILE) } -dnstap-tls-client-cert-file{COLON} { - YDVAR(1, VAR_DNSTAP_TLS_CLIENT_CERT_FILE) } -dnstap-send-identity{COLON} { YDVAR(1, VAR_DNSTAP_SEND_IDENTITY) } -dnstap-send-version{COLON} { YDVAR(1, VAR_DNSTAP_SEND_VERSION) } -dnstap-identity{COLON} { YDVAR(1, VAR_DNSTAP_IDENTITY) } -dnstap-version{COLON} { YDVAR(1, VAR_DNSTAP_VERSION) } -dnstap-log-resolver-query-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES) } -dnstap-log-resolver-response-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES) } -dnstap-log-client-query-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES) } -dnstap-log-client-response-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES) } -dnstap-log-forwarder-query-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) } -dnstap-log-forwarder-response-messages{COLON} { - YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } -disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) } -ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) } -ip-ratelimit-cookie{COLON} { YDVAR(1, VAR_IP_RATELIMIT_COOKIE) } -ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) } -ip-ratelimit-slabs{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SLABS) } -ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) } -ip-ratelimit-size{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SIZE) } -ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) } -ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) } -ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) } -ip-ratelimit-factor{COLON} { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) } -ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) } -ip-ratelimit-backoff{COLON} { YDVAR(1, VAR_IP_RATELIMIT_BACKOFF) } -ratelimit-backoff{COLON} { YDVAR(1, VAR_RATELIMIT_BACKOFF) } -outbound-msg-retry{COLON} { YDVAR(1, VAR_OUTBOUND_MSG_RETRY) } -max-sent-count{COLON} { YDVAR(1, VAR_MAX_SENT_COUNT) } -max-query-restarts{COLON} { YDVAR(1, VAR_MAX_QUERY_RESTARTS) } -low-rtt{COLON} { YDVAR(1, VAR_LOW_RTT) } -fast-server-num{COLON} { YDVAR(1, VAR_FAST_SERVER_NUM) } -low-rtt-pct{COLON} { YDVAR(1, VAR_FAST_SERVER_PERMIL) } -low-rtt-permil{COLON} { YDVAR(1, VAR_FAST_SERVER_PERMIL) } -fast-server-permil{COLON} { YDVAR(1, VAR_FAST_SERVER_PERMIL) } -response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) } -response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) } -response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) } -dnscrypt{COLON} { YDVAR(0, VAR_DNSCRYPT) } -dnscrypt-enable{COLON} { YDVAR(1, VAR_DNSCRYPT_ENABLE) } -dnscrypt-port{COLON} { YDVAR(1, VAR_DNSCRYPT_PORT) } -dnscrypt-provider{COLON} { YDVAR(1, VAR_DNSCRYPT_PROVIDER) } -dnscrypt-secret-key{COLON} { YDVAR(1, VAR_DNSCRYPT_SECRET_KEY) } -dnscrypt-provider-cert{COLON} { YDVAR(1, VAR_DNSCRYPT_PROVIDER_CERT) } -dnscrypt-provider-cert-rotated{COLON} { YDVAR(1, VAR_DNSCRYPT_PROVIDER_CERT_ROTATED) } -dnscrypt-shared-secret-cache-size{COLON} { - YDVAR(1, VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE) } -dnscrypt-shared-secret-cache-slabs{COLON} { - YDVAR(1, VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS) } -dnscrypt-nonce-cache-size{COLON} { YDVAR(1, VAR_DNSCRYPT_NONCE_CACHE_SIZE) } -dnscrypt-nonce-cache-slabs{COLON} { YDVAR(1, VAR_DNSCRYPT_NONCE_CACHE_SLABS) } -pad-responses{COLON} { YDVAR(1, VAR_PAD_RESPONSES) } -pad-responses-block-size{COLON} { YDVAR(1, VAR_PAD_RESPONSES_BLOCK_SIZE) } -pad-queries{COLON} { YDVAR(1, VAR_PAD_QUERIES) } -pad-queries-block-size{COLON} { YDVAR(1, VAR_PAD_QUERIES_BLOCK_SIZE) } -ipsecmod-enabled{COLON} { YDVAR(1, VAR_IPSECMOD_ENABLED) } -ipsecmod-ignore-bogus{COLON} { YDVAR(1, VAR_IPSECMOD_IGNORE_BOGUS) } -ipsecmod-hook{COLON} { YDVAR(1, VAR_IPSECMOD_HOOK) } -ipsecmod-max-ttl{COLON} { YDVAR(1, VAR_IPSECMOD_MAX_TTL) } -ipsecmod-whitelist{COLON} { YDVAR(1, VAR_IPSECMOD_WHITELIST) } -ipsecmod-allow{COLON} { YDVAR(1, VAR_IPSECMOD_WHITELIST) } -ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) } -cachedb{COLON} { YDVAR(0, VAR_CACHEDB) } -backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) } -secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) } -redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) } -redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) } -redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) } -redis-server-password{COLON} { YDVAR(1, VAR_CACHEDB_REDISPASSWORD) } -redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) } -redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) } -ipset{COLON} { YDVAR(0, VAR_IPSET) } -name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) } -name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) } -udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) } -tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) } -answer-cookie{COLON} { YDVAR(1, VAR_ANSWER_COOKIE ) } -cookie-secret{COLON} { YDVAR(1, VAR_COOKIE_SECRET) } -edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) } -edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) } -nsid{COLON} { YDVAR(1, VAR_NSID ) } -ede{COLON} { YDVAR(1, VAR_EDE ) } -proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) } -{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } - - /* Quoted strings. Strip leading and ending quotes */ -\" { BEGIN(quotedstring); LEXOUT(("QS ")); } -<> { - yyerror("EOF inside quoted string"); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } -} -{DQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); } -{NEWLINE} { yyerror("newline inside quoted string, no end \""); - cfg_parser->line++; BEGIN(INITIAL); } -\" { - LEXOUT(("QE ")); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } - yytext[yyleng - 1] = '\0'; - yylval.str = strdup(yytext); - if(!yylval.str) - yyerror("out of memory"); - return STRING_ARG; -} - - /* Single Quoted strings. Strip leading and ending quotes */ -\' { BEGIN(singlequotedstr); LEXOUT(("SQS ")); } -<> { - yyerror("EOF inside quoted string"); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } -} -{SQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); } -{NEWLINE} { yyerror("newline inside quoted string, no end '"); - cfg_parser->line++; BEGIN(INITIAL); } -\' { - LEXOUT(("SQE ")); - if(--num_args == 0) { BEGIN(INITIAL); } - else { BEGIN(val); } - yytext[yyleng - 1] = '\0'; - yylval.str = strdup(yytext); - if(!yylval.str) - yyerror("out of memory"); - return STRING_ARG; -} - - /* include: directive */ -include{COLON} { - LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); } -<> { - yyerror("EOF inside include directive"); - BEGIN(inc_prev); -} -{SPACE}* { LEXOUT(("ISP ")); /* ignore */ } -{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} -\" { LEXOUT(("IQS ")); BEGIN(include_quoted); } -{UNQUOTEDLETTER}* { - LEXOUT(("Iunquotedstr(%s) ", yytext)); - config_start_include_glob(yytext, 0); - BEGIN(inc_prev); -} -<> { - yyerror("EOF inside quoted string"); - BEGIN(inc_prev); -} -{DQANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); } -{NEWLINE} { yyerror("newline before \" in include name"); - cfg_parser->line++; BEGIN(inc_prev); } -\" { - LEXOUT(("IQE ")); - yytext[yyleng - 1] = '\0'; - config_start_include_glob(yytext, 0); - BEGIN(inc_prev); -} -<> { - LEXOUT(("LEXEOF ")); - yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ - if (!config_include_stack) { - yyterminate(); - } else { - int prev_toplevel = inc_toplevel; - fclose(yyin); - config_end_include(); - if(prev_toplevel) return (VAR_FORCE_TOPLEVEL); - } -} - - /* include-toplevel: directive */ -include-toplevel{COLON} { - LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include_toplevel); -} -<> { - yyerror("EOF inside include_toplevel directive"); - BEGIN(inc_prev); -} -{SPACE}* { LEXOUT(("ITSP ")); /* ignore */ } -{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } -\" { LEXOUT(("ITQS ")); BEGIN(include_toplevel_quoted); } -{UNQUOTEDLETTER}* { - LEXOUT(("ITunquotedstr(%s) ", yytext)); - config_start_include_glob(yytext, 1); - BEGIN(inc_prev); - return (VAR_FORCE_TOPLEVEL); -} -<> { - yyerror("EOF inside quoted string"); - BEGIN(inc_prev); -} -{DQANY}* { LEXOUT(("ITSTR(%s) ", yytext)); yymore(); } -{NEWLINE} { - yyerror("newline before \" in include name"); - cfg_parser->line++; BEGIN(inc_prev); -} -\" { - LEXOUT(("ITQE ")); - yytext[yyleng - 1] = '\0'; - config_start_include_glob(yytext, 1); - BEGIN(inc_prev); - return (VAR_FORCE_TOPLEVEL); -} - -{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext)); - if(--num_args == 0) { BEGIN(INITIAL); } - yylval.str = strdup(yytext); return STRING_ARG; } - -{UNQUOTEDLETTER_NOCOLON}* { - ub_c_error_msg("unknown keyword '%s'", yytext); - } - -<*>. { - ub_c_error_msg("stray '%s'", yytext); - } - -%% diff --git a/crates/libunbound-sys/unbound/util/configparser.c b/crates/libunbound-sys/unbound/util/configparser.c deleted file mode 100644 index b6271f12..00000000 --- a/crates/libunbound-sys/unbound/util/configparser.c +++ /dev/null @@ -1,7635 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.7.6. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output, and Bison version. */ -#define YYBISON 30706 - -/* Bison version string. */ -#define YYBISON_VERSION "3.7.6" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* First part of user prologue. */ -#line 38 "util/configparser.y" - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "util/configyyrename.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "sldns/str2wire.h" - -int ub_c_lex(void); -void ub_c_error(const char *message); - -static void validate_respip_action(const char* action); -static void validate_acl_action(const char* action); - -/* these need to be global, otherwise they cannot be used inside yacc */ -extern struct config_parser_state* cfg_parser; - -#if 0 -#define OUTYY(s) printf s /* used ONLY when debugging */ -#else -#define OUTYY(s) -#endif - - -#line 102 "util/configparser.c" - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - -#include "configparser.h" -/* Symbol kind. */ -enum yysymbol_kind_t -{ - YYSYMBOL_YYEMPTY = -2, - YYSYMBOL_YYEOF = 0, /* "end of file" */ - YYSYMBOL_YYerror = 1, /* error */ - YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ - YYSYMBOL_SPACE = 3, /* SPACE */ - YYSYMBOL_LETTER = 4, /* LETTER */ - YYSYMBOL_NEWLINE = 5, /* NEWLINE */ - YYSYMBOL_COMMENT = 6, /* COMMENT */ - YYSYMBOL_COLON = 7, /* COLON */ - YYSYMBOL_ANY = 8, /* ANY */ - YYSYMBOL_ZONESTR = 9, /* ZONESTR */ - YYSYMBOL_STRING_ARG = 10, /* STRING_ARG */ - YYSYMBOL_VAR_FORCE_TOPLEVEL = 11, /* VAR_FORCE_TOPLEVEL */ - YYSYMBOL_VAR_SERVER = 12, /* VAR_SERVER */ - YYSYMBOL_VAR_VERBOSITY = 13, /* VAR_VERBOSITY */ - YYSYMBOL_VAR_NUM_THREADS = 14, /* VAR_NUM_THREADS */ - YYSYMBOL_VAR_PORT = 15, /* VAR_PORT */ - YYSYMBOL_VAR_OUTGOING_RANGE = 16, /* VAR_OUTGOING_RANGE */ - YYSYMBOL_VAR_INTERFACE = 17, /* VAR_INTERFACE */ - YYSYMBOL_VAR_PREFER_IP4 = 18, /* VAR_PREFER_IP4 */ - YYSYMBOL_VAR_DO_IP4 = 19, /* VAR_DO_IP4 */ - YYSYMBOL_VAR_DO_IP6 = 20, /* VAR_DO_IP6 */ - YYSYMBOL_VAR_DO_NAT64 = 21, /* VAR_DO_NAT64 */ - YYSYMBOL_VAR_PREFER_IP6 = 22, /* VAR_PREFER_IP6 */ - YYSYMBOL_VAR_DO_UDP = 23, /* VAR_DO_UDP */ - YYSYMBOL_VAR_DO_TCP = 24, /* VAR_DO_TCP */ - YYSYMBOL_VAR_TCP_MSS = 25, /* VAR_TCP_MSS */ - YYSYMBOL_VAR_OUTGOING_TCP_MSS = 26, /* VAR_OUTGOING_TCP_MSS */ - YYSYMBOL_VAR_TCP_IDLE_TIMEOUT = 27, /* VAR_TCP_IDLE_TIMEOUT */ - YYSYMBOL_VAR_EDNS_TCP_KEEPALIVE = 28, /* VAR_EDNS_TCP_KEEPALIVE */ - YYSYMBOL_VAR_EDNS_TCP_KEEPALIVE_TIMEOUT = 29, /* VAR_EDNS_TCP_KEEPALIVE_TIMEOUT */ - YYSYMBOL_VAR_SOCK_QUEUE_TIMEOUT = 30, /* VAR_SOCK_QUEUE_TIMEOUT */ - YYSYMBOL_VAR_CHROOT = 31, /* VAR_CHROOT */ - YYSYMBOL_VAR_USERNAME = 32, /* VAR_USERNAME */ - YYSYMBOL_VAR_DIRECTORY = 33, /* VAR_DIRECTORY */ - YYSYMBOL_VAR_LOGFILE = 34, /* VAR_LOGFILE */ - YYSYMBOL_VAR_PIDFILE = 35, /* VAR_PIDFILE */ - YYSYMBOL_VAR_MSG_CACHE_SIZE = 36, /* VAR_MSG_CACHE_SIZE */ - YYSYMBOL_VAR_MSG_CACHE_SLABS = 37, /* VAR_MSG_CACHE_SLABS */ - YYSYMBOL_VAR_NUM_QUERIES_PER_THREAD = 38, /* VAR_NUM_QUERIES_PER_THREAD */ - YYSYMBOL_VAR_RRSET_CACHE_SIZE = 39, /* VAR_RRSET_CACHE_SIZE */ - YYSYMBOL_VAR_RRSET_CACHE_SLABS = 40, /* VAR_RRSET_CACHE_SLABS */ - YYSYMBOL_VAR_OUTGOING_NUM_TCP = 41, /* VAR_OUTGOING_NUM_TCP */ - YYSYMBOL_VAR_INFRA_HOST_TTL = 42, /* VAR_INFRA_HOST_TTL */ - YYSYMBOL_VAR_INFRA_LAME_TTL = 43, /* VAR_INFRA_LAME_TTL */ - YYSYMBOL_VAR_INFRA_CACHE_SLABS = 44, /* VAR_INFRA_CACHE_SLABS */ - YYSYMBOL_VAR_INFRA_CACHE_NUMHOSTS = 45, /* VAR_INFRA_CACHE_NUMHOSTS */ - YYSYMBOL_VAR_INFRA_CACHE_LAME_SIZE = 46, /* VAR_INFRA_CACHE_LAME_SIZE */ - YYSYMBOL_VAR_NAME = 47, /* VAR_NAME */ - YYSYMBOL_VAR_STUB_ZONE = 48, /* VAR_STUB_ZONE */ - YYSYMBOL_VAR_STUB_HOST = 49, /* VAR_STUB_HOST */ - YYSYMBOL_VAR_STUB_ADDR = 50, /* VAR_STUB_ADDR */ - YYSYMBOL_VAR_TARGET_FETCH_POLICY = 51, /* VAR_TARGET_FETCH_POLICY */ - YYSYMBOL_VAR_HARDEN_SHORT_BUFSIZE = 52, /* VAR_HARDEN_SHORT_BUFSIZE */ - YYSYMBOL_VAR_HARDEN_LARGE_QUERIES = 53, /* VAR_HARDEN_LARGE_QUERIES */ - YYSYMBOL_VAR_FORWARD_ZONE = 54, /* VAR_FORWARD_ZONE */ - YYSYMBOL_VAR_FORWARD_HOST = 55, /* VAR_FORWARD_HOST */ - YYSYMBOL_VAR_FORWARD_ADDR = 56, /* VAR_FORWARD_ADDR */ - YYSYMBOL_VAR_DO_NOT_QUERY_ADDRESS = 57, /* VAR_DO_NOT_QUERY_ADDRESS */ - YYSYMBOL_VAR_HIDE_IDENTITY = 58, /* VAR_HIDE_IDENTITY */ - YYSYMBOL_VAR_HIDE_VERSION = 59, /* VAR_HIDE_VERSION */ - YYSYMBOL_VAR_IDENTITY = 60, /* VAR_IDENTITY */ - YYSYMBOL_VAR_VERSION = 61, /* VAR_VERSION */ - YYSYMBOL_VAR_HARDEN_GLUE = 62, /* VAR_HARDEN_GLUE */ - YYSYMBOL_VAR_MODULE_CONF = 63, /* VAR_MODULE_CONF */ - YYSYMBOL_VAR_TRUST_ANCHOR_FILE = 64, /* VAR_TRUST_ANCHOR_FILE */ - YYSYMBOL_VAR_TRUST_ANCHOR = 65, /* VAR_TRUST_ANCHOR */ - YYSYMBOL_VAR_VAL_OVERRIDE_DATE = 66, /* VAR_VAL_OVERRIDE_DATE */ - YYSYMBOL_VAR_BOGUS_TTL = 67, /* VAR_BOGUS_TTL */ - YYSYMBOL_VAR_VAL_CLEAN_ADDITIONAL = 68, /* VAR_VAL_CLEAN_ADDITIONAL */ - YYSYMBOL_VAR_VAL_PERMISSIVE_MODE = 69, /* VAR_VAL_PERMISSIVE_MODE */ - YYSYMBOL_VAR_INCOMING_NUM_TCP = 70, /* VAR_INCOMING_NUM_TCP */ - YYSYMBOL_VAR_MSG_BUFFER_SIZE = 71, /* VAR_MSG_BUFFER_SIZE */ - YYSYMBOL_VAR_KEY_CACHE_SIZE = 72, /* VAR_KEY_CACHE_SIZE */ - YYSYMBOL_VAR_KEY_CACHE_SLABS = 73, /* VAR_KEY_CACHE_SLABS */ - YYSYMBOL_VAR_TRUSTED_KEYS_FILE = 74, /* VAR_TRUSTED_KEYS_FILE */ - YYSYMBOL_VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 75, /* VAR_VAL_NSEC3_KEYSIZE_ITERATIONS */ - YYSYMBOL_VAR_USE_SYSLOG = 76, /* VAR_USE_SYSLOG */ - YYSYMBOL_VAR_OUTGOING_INTERFACE = 77, /* VAR_OUTGOING_INTERFACE */ - YYSYMBOL_VAR_ROOT_HINTS = 78, /* VAR_ROOT_HINTS */ - YYSYMBOL_VAR_DO_NOT_QUERY_LOCALHOST = 79, /* VAR_DO_NOT_QUERY_LOCALHOST */ - YYSYMBOL_VAR_CACHE_MAX_TTL = 80, /* VAR_CACHE_MAX_TTL */ - YYSYMBOL_VAR_HARDEN_DNSSEC_STRIPPED = 81, /* VAR_HARDEN_DNSSEC_STRIPPED */ - YYSYMBOL_VAR_ACCESS_CONTROL = 82, /* VAR_ACCESS_CONTROL */ - YYSYMBOL_VAR_LOCAL_ZONE = 83, /* VAR_LOCAL_ZONE */ - YYSYMBOL_VAR_LOCAL_DATA = 84, /* VAR_LOCAL_DATA */ - YYSYMBOL_VAR_INTERFACE_AUTOMATIC = 85, /* VAR_INTERFACE_AUTOMATIC */ - YYSYMBOL_VAR_STATISTICS_INTERVAL = 86, /* VAR_STATISTICS_INTERVAL */ - YYSYMBOL_VAR_DO_DAEMONIZE = 87, /* VAR_DO_DAEMONIZE */ - YYSYMBOL_VAR_USE_CAPS_FOR_ID = 88, /* VAR_USE_CAPS_FOR_ID */ - YYSYMBOL_VAR_STATISTICS_CUMULATIVE = 89, /* VAR_STATISTICS_CUMULATIVE */ - YYSYMBOL_VAR_OUTGOING_PORT_PERMIT = 90, /* VAR_OUTGOING_PORT_PERMIT */ - YYSYMBOL_VAR_OUTGOING_PORT_AVOID = 91, /* VAR_OUTGOING_PORT_AVOID */ - YYSYMBOL_VAR_DLV_ANCHOR_FILE = 92, /* VAR_DLV_ANCHOR_FILE */ - YYSYMBOL_VAR_DLV_ANCHOR = 93, /* VAR_DLV_ANCHOR */ - YYSYMBOL_VAR_NEG_CACHE_SIZE = 94, /* VAR_NEG_CACHE_SIZE */ - YYSYMBOL_VAR_HARDEN_REFERRAL_PATH = 95, /* VAR_HARDEN_REFERRAL_PATH */ - YYSYMBOL_VAR_PRIVATE_ADDRESS = 96, /* VAR_PRIVATE_ADDRESS */ - YYSYMBOL_VAR_PRIVATE_DOMAIN = 97, /* VAR_PRIVATE_DOMAIN */ - YYSYMBOL_VAR_REMOTE_CONTROL = 98, /* VAR_REMOTE_CONTROL */ - YYSYMBOL_VAR_CONTROL_ENABLE = 99, /* VAR_CONTROL_ENABLE */ - YYSYMBOL_VAR_CONTROL_INTERFACE = 100, /* VAR_CONTROL_INTERFACE */ - YYSYMBOL_VAR_CONTROL_PORT = 101, /* VAR_CONTROL_PORT */ - YYSYMBOL_VAR_SERVER_KEY_FILE = 102, /* VAR_SERVER_KEY_FILE */ - YYSYMBOL_VAR_SERVER_CERT_FILE = 103, /* VAR_SERVER_CERT_FILE */ - YYSYMBOL_VAR_CONTROL_KEY_FILE = 104, /* VAR_CONTROL_KEY_FILE */ - YYSYMBOL_VAR_CONTROL_CERT_FILE = 105, /* VAR_CONTROL_CERT_FILE */ - YYSYMBOL_VAR_CONTROL_USE_CERT = 106, /* VAR_CONTROL_USE_CERT */ - YYSYMBOL_VAR_TCP_REUSE_TIMEOUT = 107, /* VAR_TCP_REUSE_TIMEOUT */ - YYSYMBOL_VAR_MAX_REUSE_TCP_QUERIES = 108, /* VAR_MAX_REUSE_TCP_QUERIES */ - YYSYMBOL_VAR_EXTENDED_STATISTICS = 109, /* VAR_EXTENDED_STATISTICS */ - YYSYMBOL_VAR_LOCAL_DATA_PTR = 110, /* VAR_LOCAL_DATA_PTR */ - YYSYMBOL_VAR_JOSTLE_TIMEOUT = 111, /* VAR_JOSTLE_TIMEOUT */ - YYSYMBOL_VAR_STUB_PRIME = 112, /* VAR_STUB_PRIME */ - YYSYMBOL_VAR_UNWANTED_REPLY_THRESHOLD = 113, /* VAR_UNWANTED_REPLY_THRESHOLD */ - YYSYMBOL_VAR_LOG_TIME_ASCII = 114, /* VAR_LOG_TIME_ASCII */ - YYSYMBOL_VAR_DOMAIN_INSECURE = 115, /* VAR_DOMAIN_INSECURE */ - YYSYMBOL_VAR_PYTHON = 116, /* VAR_PYTHON */ - YYSYMBOL_VAR_PYTHON_SCRIPT = 117, /* VAR_PYTHON_SCRIPT */ - YYSYMBOL_VAR_VAL_SIG_SKEW_MIN = 118, /* VAR_VAL_SIG_SKEW_MIN */ - YYSYMBOL_VAR_VAL_SIG_SKEW_MAX = 119, /* VAR_VAL_SIG_SKEW_MAX */ - YYSYMBOL_VAR_VAL_MAX_RESTART = 120, /* VAR_VAL_MAX_RESTART */ - YYSYMBOL_VAR_CACHE_MIN_TTL = 121, /* VAR_CACHE_MIN_TTL */ - YYSYMBOL_VAR_VAL_LOG_LEVEL = 122, /* VAR_VAL_LOG_LEVEL */ - YYSYMBOL_VAR_AUTO_TRUST_ANCHOR_FILE = 123, /* VAR_AUTO_TRUST_ANCHOR_FILE */ - YYSYMBOL_VAR_KEEP_MISSING = 124, /* VAR_KEEP_MISSING */ - YYSYMBOL_VAR_ADD_HOLDDOWN = 125, /* VAR_ADD_HOLDDOWN */ - YYSYMBOL_VAR_DEL_HOLDDOWN = 126, /* VAR_DEL_HOLDDOWN */ - YYSYMBOL_VAR_SO_RCVBUF = 127, /* VAR_SO_RCVBUF */ - YYSYMBOL_VAR_EDNS_BUFFER_SIZE = 128, /* VAR_EDNS_BUFFER_SIZE */ - YYSYMBOL_VAR_PREFETCH = 129, /* VAR_PREFETCH */ - YYSYMBOL_VAR_PREFETCH_KEY = 130, /* VAR_PREFETCH_KEY */ - YYSYMBOL_VAR_SO_SNDBUF = 131, /* VAR_SO_SNDBUF */ - YYSYMBOL_VAR_SO_REUSEPORT = 132, /* VAR_SO_REUSEPORT */ - YYSYMBOL_VAR_HARDEN_BELOW_NXDOMAIN = 133, /* VAR_HARDEN_BELOW_NXDOMAIN */ - YYSYMBOL_VAR_IGNORE_CD_FLAG = 134, /* VAR_IGNORE_CD_FLAG */ - YYSYMBOL_VAR_LOG_QUERIES = 135, /* VAR_LOG_QUERIES */ - YYSYMBOL_VAR_LOG_REPLIES = 136, /* VAR_LOG_REPLIES */ - YYSYMBOL_VAR_LOG_LOCAL_ACTIONS = 137, /* VAR_LOG_LOCAL_ACTIONS */ - YYSYMBOL_VAR_TCP_UPSTREAM = 138, /* VAR_TCP_UPSTREAM */ - YYSYMBOL_VAR_SSL_UPSTREAM = 139, /* VAR_SSL_UPSTREAM */ - YYSYMBOL_VAR_TCP_AUTH_QUERY_TIMEOUT = 140, /* VAR_TCP_AUTH_QUERY_TIMEOUT */ - YYSYMBOL_VAR_SSL_SERVICE_KEY = 141, /* VAR_SSL_SERVICE_KEY */ - YYSYMBOL_VAR_SSL_SERVICE_PEM = 142, /* VAR_SSL_SERVICE_PEM */ - YYSYMBOL_VAR_SSL_PORT = 143, /* VAR_SSL_PORT */ - YYSYMBOL_VAR_FORWARD_FIRST = 144, /* VAR_FORWARD_FIRST */ - YYSYMBOL_VAR_STUB_SSL_UPSTREAM = 145, /* VAR_STUB_SSL_UPSTREAM */ - YYSYMBOL_VAR_FORWARD_SSL_UPSTREAM = 146, /* VAR_FORWARD_SSL_UPSTREAM */ - YYSYMBOL_VAR_TLS_CERT_BUNDLE = 147, /* VAR_TLS_CERT_BUNDLE */ - YYSYMBOL_VAR_STUB_TCP_UPSTREAM = 148, /* VAR_STUB_TCP_UPSTREAM */ - YYSYMBOL_VAR_FORWARD_TCP_UPSTREAM = 149, /* VAR_FORWARD_TCP_UPSTREAM */ - YYSYMBOL_VAR_HTTPS_PORT = 150, /* VAR_HTTPS_PORT */ - YYSYMBOL_VAR_HTTP_ENDPOINT = 151, /* VAR_HTTP_ENDPOINT */ - YYSYMBOL_VAR_HTTP_MAX_STREAMS = 152, /* VAR_HTTP_MAX_STREAMS */ - YYSYMBOL_VAR_HTTP_QUERY_BUFFER_SIZE = 153, /* VAR_HTTP_QUERY_BUFFER_SIZE */ - YYSYMBOL_VAR_HTTP_RESPONSE_BUFFER_SIZE = 154, /* VAR_HTTP_RESPONSE_BUFFER_SIZE */ - YYSYMBOL_VAR_HTTP_NODELAY = 155, /* VAR_HTTP_NODELAY */ - YYSYMBOL_VAR_HTTP_NOTLS_DOWNSTREAM = 156, /* VAR_HTTP_NOTLS_DOWNSTREAM */ - YYSYMBOL_VAR_STUB_FIRST = 157, /* VAR_STUB_FIRST */ - YYSYMBOL_VAR_MINIMAL_RESPONSES = 158, /* VAR_MINIMAL_RESPONSES */ - YYSYMBOL_VAR_RRSET_ROUNDROBIN = 159, /* VAR_RRSET_ROUNDROBIN */ - YYSYMBOL_VAR_MAX_UDP_SIZE = 160, /* VAR_MAX_UDP_SIZE */ - YYSYMBOL_VAR_DELAY_CLOSE = 161, /* VAR_DELAY_CLOSE */ - YYSYMBOL_VAR_UDP_CONNECT = 162, /* VAR_UDP_CONNECT */ - YYSYMBOL_VAR_UNBLOCK_LAN_ZONES = 163, /* VAR_UNBLOCK_LAN_ZONES */ - YYSYMBOL_VAR_INSECURE_LAN_ZONES = 164, /* VAR_INSECURE_LAN_ZONES */ - YYSYMBOL_VAR_INFRA_CACHE_MIN_RTT = 165, /* VAR_INFRA_CACHE_MIN_RTT */ - YYSYMBOL_VAR_INFRA_CACHE_MAX_RTT = 166, /* VAR_INFRA_CACHE_MAX_RTT */ - YYSYMBOL_VAR_INFRA_KEEP_PROBING = 167, /* VAR_INFRA_KEEP_PROBING */ - YYSYMBOL_VAR_DNS64_PREFIX = 168, /* VAR_DNS64_PREFIX */ - YYSYMBOL_VAR_DNS64_SYNTHALL = 169, /* VAR_DNS64_SYNTHALL */ - YYSYMBOL_VAR_DNS64_IGNORE_AAAA = 170, /* VAR_DNS64_IGNORE_AAAA */ - YYSYMBOL_VAR_NAT64_PREFIX = 171, /* VAR_NAT64_PREFIX */ - YYSYMBOL_VAR_DNSTAP = 172, /* VAR_DNSTAP */ - YYSYMBOL_VAR_DNSTAP_ENABLE = 173, /* VAR_DNSTAP_ENABLE */ - YYSYMBOL_VAR_DNSTAP_SOCKET_PATH = 174, /* VAR_DNSTAP_SOCKET_PATH */ - YYSYMBOL_VAR_DNSTAP_IP = 175, /* VAR_DNSTAP_IP */ - YYSYMBOL_VAR_DNSTAP_TLS = 176, /* VAR_DNSTAP_TLS */ - YYSYMBOL_VAR_DNSTAP_TLS_SERVER_NAME = 177, /* VAR_DNSTAP_TLS_SERVER_NAME */ - YYSYMBOL_VAR_DNSTAP_TLS_CERT_BUNDLE = 178, /* VAR_DNSTAP_TLS_CERT_BUNDLE */ - YYSYMBOL_VAR_DNSTAP_TLS_CLIENT_KEY_FILE = 179, /* VAR_DNSTAP_TLS_CLIENT_KEY_FILE */ - YYSYMBOL_VAR_DNSTAP_TLS_CLIENT_CERT_FILE = 180, /* VAR_DNSTAP_TLS_CLIENT_CERT_FILE */ - YYSYMBOL_VAR_DNSTAP_SEND_IDENTITY = 181, /* VAR_DNSTAP_SEND_IDENTITY */ - YYSYMBOL_VAR_DNSTAP_SEND_VERSION = 182, /* VAR_DNSTAP_SEND_VERSION */ - YYSYMBOL_VAR_DNSTAP_BIDIRECTIONAL = 183, /* VAR_DNSTAP_BIDIRECTIONAL */ - YYSYMBOL_VAR_DNSTAP_IDENTITY = 184, /* VAR_DNSTAP_IDENTITY */ - YYSYMBOL_VAR_DNSTAP_VERSION = 185, /* VAR_DNSTAP_VERSION */ - YYSYMBOL_VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 186, /* VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES */ - YYSYMBOL_VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 187, /* VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES */ - YYSYMBOL_VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 188, /* VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES */ - YYSYMBOL_VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 189, /* VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES */ - YYSYMBOL_VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 190, /* VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES */ - YYSYMBOL_VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 191, /* VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES */ - YYSYMBOL_VAR_RESPONSE_IP_TAG = 192, /* VAR_RESPONSE_IP_TAG */ - YYSYMBOL_VAR_RESPONSE_IP = 193, /* VAR_RESPONSE_IP */ - YYSYMBOL_VAR_RESPONSE_IP_DATA = 194, /* VAR_RESPONSE_IP_DATA */ - YYSYMBOL_VAR_HARDEN_ALGO_DOWNGRADE = 195, /* VAR_HARDEN_ALGO_DOWNGRADE */ - YYSYMBOL_VAR_IP_TRANSPARENT = 196, /* VAR_IP_TRANSPARENT */ - YYSYMBOL_VAR_IP_DSCP = 197, /* VAR_IP_DSCP */ - YYSYMBOL_VAR_DISABLE_DNSSEC_LAME_CHECK = 198, /* VAR_DISABLE_DNSSEC_LAME_CHECK */ - YYSYMBOL_VAR_IP_RATELIMIT = 199, /* VAR_IP_RATELIMIT */ - YYSYMBOL_VAR_IP_RATELIMIT_SLABS = 200, /* VAR_IP_RATELIMIT_SLABS */ - YYSYMBOL_VAR_IP_RATELIMIT_SIZE = 201, /* VAR_IP_RATELIMIT_SIZE */ - YYSYMBOL_VAR_RATELIMIT = 202, /* VAR_RATELIMIT */ - YYSYMBOL_VAR_RATELIMIT_SLABS = 203, /* VAR_RATELIMIT_SLABS */ - YYSYMBOL_VAR_RATELIMIT_SIZE = 204, /* VAR_RATELIMIT_SIZE */ - YYSYMBOL_VAR_OUTBOUND_MSG_RETRY = 205, /* VAR_OUTBOUND_MSG_RETRY */ - YYSYMBOL_VAR_MAX_SENT_COUNT = 206, /* VAR_MAX_SENT_COUNT */ - YYSYMBOL_VAR_MAX_QUERY_RESTARTS = 207, /* VAR_MAX_QUERY_RESTARTS */ - YYSYMBOL_VAR_RATELIMIT_FOR_DOMAIN = 208, /* VAR_RATELIMIT_FOR_DOMAIN */ - YYSYMBOL_VAR_RATELIMIT_BELOW_DOMAIN = 209, /* VAR_RATELIMIT_BELOW_DOMAIN */ - YYSYMBOL_VAR_IP_RATELIMIT_FACTOR = 210, /* VAR_IP_RATELIMIT_FACTOR */ - YYSYMBOL_VAR_RATELIMIT_FACTOR = 211, /* VAR_RATELIMIT_FACTOR */ - YYSYMBOL_VAR_IP_RATELIMIT_BACKOFF = 212, /* VAR_IP_RATELIMIT_BACKOFF */ - YYSYMBOL_VAR_RATELIMIT_BACKOFF = 213, /* VAR_RATELIMIT_BACKOFF */ - YYSYMBOL_VAR_SEND_CLIENT_SUBNET = 214, /* VAR_SEND_CLIENT_SUBNET */ - YYSYMBOL_VAR_CLIENT_SUBNET_ZONE = 215, /* VAR_CLIENT_SUBNET_ZONE */ - YYSYMBOL_VAR_CLIENT_SUBNET_ALWAYS_FORWARD = 216, /* VAR_CLIENT_SUBNET_ALWAYS_FORWARD */ - YYSYMBOL_VAR_CLIENT_SUBNET_OPCODE = 217, /* VAR_CLIENT_SUBNET_OPCODE */ - YYSYMBOL_VAR_MAX_CLIENT_SUBNET_IPV4 = 218, /* VAR_MAX_CLIENT_SUBNET_IPV4 */ - YYSYMBOL_VAR_MAX_CLIENT_SUBNET_IPV6 = 219, /* VAR_MAX_CLIENT_SUBNET_IPV6 */ - YYSYMBOL_VAR_MIN_CLIENT_SUBNET_IPV4 = 220, /* VAR_MIN_CLIENT_SUBNET_IPV4 */ - YYSYMBOL_VAR_MIN_CLIENT_SUBNET_IPV6 = 221, /* VAR_MIN_CLIENT_SUBNET_IPV6 */ - YYSYMBOL_VAR_MAX_ECS_TREE_SIZE_IPV4 = 222, /* VAR_MAX_ECS_TREE_SIZE_IPV4 */ - YYSYMBOL_VAR_MAX_ECS_TREE_SIZE_IPV6 = 223, /* VAR_MAX_ECS_TREE_SIZE_IPV6 */ - YYSYMBOL_VAR_CAPS_WHITELIST = 224, /* VAR_CAPS_WHITELIST */ - YYSYMBOL_VAR_CACHE_MAX_NEGATIVE_TTL = 225, /* VAR_CACHE_MAX_NEGATIVE_TTL */ - YYSYMBOL_VAR_PERMIT_SMALL_HOLDDOWN = 226, /* VAR_PERMIT_SMALL_HOLDDOWN */ - YYSYMBOL_VAR_QNAME_MINIMISATION = 227, /* VAR_QNAME_MINIMISATION */ - YYSYMBOL_VAR_QNAME_MINIMISATION_STRICT = 228, /* VAR_QNAME_MINIMISATION_STRICT */ - YYSYMBOL_VAR_IP_FREEBIND = 229, /* VAR_IP_FREEBIND */ - YYSYMBOL_VAR_DEFINE_TAG = 230, /* VAR_DEFINE_TAG */ - YYSYMBOL_VAR_LOCAL_ZONE_TAG = 231, /* VAR_LOCAL_ZONE_TAG */ - YYSYMBOL_VAR_ACCESS_CONTROL_TAG = 232, /* VAR_ACCESS_CONTROL_TAG */ - YYSYMBOL_VAR_LOCAL_ZONE_OVERRIDE = 233, /* VAR_LOCAL_ZONE_OVERRIDE */ - YYSYMBOL_VAR_ACCESS_CONTROL_TAG_ACTION = 234, /* VAR_ACCESS_CONTROL_TAG_ACTION */ - YYSYMBOL_VAR_ACCESS_CONTROL_TAG_DATA = 235, /* VAR_ACCESS_CONTROL_TAG_DATA */ - YYSYMBOL_VAR_VIEW = 236, /* VAR_VIEW */ - YYSYMBOL_VAR_ACCESS_CONTROL_VIEW = 237, /* VAR_ACCESS_CONTROL_VIEW */ - YYSYMBOL_VAR_VIEW_FIRST = 238, /* VAR_VIEW_FIRST */ - YYSYMBOL_VAR_SERVE_EXPIRED = 239, /* VAR_SERVE_EXPIRED */ - YYSYMBOL_VAR_SERVE_EXPIRED_TTL = 240, /* VAR_SERVE_EXPIRED_TTL */ - YYSYMBOL_VAR_SERVE_EXPIRED_TTL_RESET = 241, /* VAR_SERVE_EXPIRED_TTL_RESET */ - YYSYMBOL_VAR_SERVE_EXPIRED_REPLY_TTL = 242, /* VAR_SERVE_EXPIRED_REPLY_TTL */ - YYSYMBOL_VAR_SERVE_EXPIRED_CLIENT_TIMEOUT = 243, /* VAR_SERVE_EXPIRED_CLIENT_TIMEOUT */ - YYSYMBOL_VAR_EDE_SERVE_EXPIRED = 244, /* VAR_EDE_SERVE_EXPIRED */ - YYSYMBOL_VAR_SERVE_ORIGINAL_TTL = 245, /* VAR_SERVE_ORIGINAL_TTL */ - YYSYMBOL_VAR_FAKE_DSA = 246, /* VAR_FAKE_DSA */ - YYSYMBOL_VAR_FAKE_SHA1 = 247, /* VAR_FAKE_SHA1 */ - YYSYMBOL_VAR_LOG_IDENTITY = 248, /* VAR_LOG_IDENTITY */ - YYSYMBOL_VAR_HIDE_TRUSTANCHOR = 249, /* VAR_HIDE_TRUSTANCHOR */ - YYSYMBOL_VAR_HIDE_HTTP_USER_AGENT = 250, /* VAR_HIDE_HTTP_USER_AGENT */ - YYSYMBOL_VAR_HTTP_USER_AGENT = 251, /* VAR_HTTP_USER_AGENT */ - YYSYMBOL_VAR_TRUST_ANCHOR_SIGNALING = 252, /* VAR_TRUST_ANCHOR_SIGNALING */ - YYSYMBOL_VAR_AGGRESSIVE_NSEC = 253, /* VAR_AGGRESSIVE_NSEC */ - YYSYMBOL_VAR_USE_SYSTEMD = 254, /* VAR_USE_SYSTEMD */ - YYSYMBOL_VAR_SHM_ENABLE = 255, /* VAR_SHM_ENABLE */ - YYSYMBOL_VAR_SHM_KEY = 256, /* VAR_SHM_KEY */ - YYSYMBOL_VAR_ROOT_KEY_SENTINEL = 257, /* VAR_ROOT_KEY_SENTINEL */ - YYSYMBOL_VAR_DNSCRYPT = 258, /* VAR_DNSCRYPT */ - YYSYMBOL_VAR_DNSCRYPT_ENABLE = 259, /* VAR_DNSCRYPT_ENABLE */ - YYSYMBOL_VAR_DNSCRYPT_PORT = 260, /* VAR_DNSCRYPT_PORT */ - YYSYMBOL_VAR_DNSCRYPT_PROVIDER = 261, /* VAR_DNSCRYPT_PROVIDER */ - YYSYMBOL_VAR_DNSCRYPT_SECRET_KEY = 262, /* VAR_DNSCRYPT_SECRET_KEY */ - YYSYMBOL_VAR_DNSCRYPT_PROVIDER_CERT = 263, /* VAR_DNSCRYPT_PROVIDER_CERT */ - YYSYMBOL_VAR_DNSCRYPT_PROVIDER_CERT_ROTATED = 264, /* VAR_DNSCRYPT_PROVIDER_CERT_ROTATED */ - YYSYMBOL_VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE = 265, /* VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE */ - YYSYMBOL_VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS = 266, /* VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS */ - YYSYMBOL_VAR_DNSCRYPT_NONCE_CACHE_SIZE = 267, /* VAR_DNSCRYPT_NONCE_CACHE_SIZE */ - YYSYMBOL_VAR_DNSCRYPT_NONCE_CACHE_SLABS = 268, /* VAR_DNSCRYPT_NONCE_CACHE_SLABS */ - YYSYMBOL_VAR_PAD_RESPONSES = 269, /* VAR_PAD_RESPONSES */ - YYSYMBOL_VAR_PAD_RESPONSES_BLOCK_SIZE = 270, /* VAR_PAD_RESPONSES_BLOCK_SIZE */ - YYSYMBOL_VAR_PAD_QUERIES = 271, /* VAR_PAD_QUERIES */ - YYSYMBOL_VAR_PAD_QUERIES_BLOCK_SIZE = 272, /* VAR_PAD_QUERIES_BLOCK_SIZE */ - YYSYMBOL_VAR_IPSECMOD_ENABLED = 273, /* VAR_IPSECMOD_ENABLED */ - YYSYMBOL_VAR_IPSECMOD_HOOK = 274, /* VAR_IPSECMOD_HOOK */ - YYSYMBOL_VAR_IPSECMOD_IGNORE_BOGUS = 275, /* VAR_IPSECMOD_IGNORE_BOGUS */ - YYSYMBOL_VAR_IPSECMOD_MAX_TTL = 276, /* VAR_IPSECMOD_MAX_TTL */ - YYSYMBOL_VAR_IPSECMOD_WHITELIST = 277, /* VAR_IPSECMOD_WHITELIST */ - YYSYMBOL_VAR_IPSECMOD_STRICT = 278, /* VAR_IPSECMOD_STRICT */ - YYSYMBOL_VAR_CACHEDB = 279, /* VAR_CACHEDB */ - YYSYMBOL_VAR_CACHEDB_BACKEND = 280, /* VAR_CACHEDB_BACKEND */ - YYSYMBOL_VAR_CACHEDB_SECRETSEED = 281, /* VAR_CACHEDB_SECRETSEED */ - YYSYMBOL_VAR_CACHEDB_REDISHOST = 282, /* VAR_CACHEDB_REDISHOST */ - YYSYMBOL_VAR_CACHEDB_REDISPORT = 283, /* VAR_CACHEDB_REDISPORT */ - YYSYMBOL_VAR_CACHEDB_REDISTIMEOUT = 284, /* VAR_CACHEDB_REDISTIMEOUT */ - YYSYMBOL_VAR_CACHEDB_REDISEXPIRERECORDS = 285, /* VAR_CACHEDB_REDISEXPIRERECORDS */ - YYSYMBOL_VAR_CACHEDB_REDISPATH = 286, /* VAR_CACHEDB_REDISPATH */ - YYSYMBOL_VAR_CACHEDB_REDISPASSWORD = 287, /* VAR_CACHEDB_REDISPASSWORD */ - YYSYMBOL_VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 288, /* VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM */ - YYSYMBOL_VAR_FOR_UPSTREAM = 289, /* VAR_FOR_UPSTREAM */ - YYSYMBOL_VAR_AUTH_ZONE = 290, /* VAR_AUTH_ZONE */ - YYSYMBOL_VAR_ZONEFILE = 291, /* VAR_ZONEFILE */ - YYSYMBOL_VAR_MASTER = 292, /* VAR_MASTER */ - YYSYMBOL_VAR_URL = 293, /* VAR_URL */ - YYSYMBOL_VAR_FOR_DOWNSTREAM = 294, /* VAR_FOR_DOWNSTREAM */ - YYSYMBOL_VAR_FALLBACK_ENABLED = 295, /* VAR_FALLBACK_ENABLED */ - YYSYMBOL_VAR_TLS_ADDITIONAL_PORT = 296, /* VAR_TLS_ADDITIONAL_PORT */ - YYSYMBOL_VAR_LOW_RTT = 297, /* VAR_LOW_RTT */ - YYSYMBOL_VAR_LOW_RTT_PERMIL = 298, /* VAR_LOW_RTT_PERMIL */ - YYSYMBOL_VAR_FAST_SERVER_PERMIL = 299, /* VAR_FAST_SERVER_PERMIL */ - YYSYMBOL_VAR_FAST_SERVER_NUM = 300, /* VAR_FAST_SERVER_NUM */ - YYSYMBOL_VAR_ALLOW_NOTIFY = 301, /* VAR_ALLOW_NOTIFY */ - YYSYMBOL_VAR_TLS_WIN_CERT = 302, /* VAR_TLS_WIN_CERT */ - YYSYMBOL_VAR_TCP_CONNECTION_LIMIT = 303, /* VAR_TCP_CONNECTION_LIMIT */ - YYSYMBOL_VAR_ANSWER_COOKIE = 304, /* VAR_ANSWER_COOKIE */ - YYSYMBOL_VAR_COOKIE_SECRET = 305, /* VAR_COOKIE_SECRET */ - YYSYMBOL_VAR_IP_RATELIMIT_COOKIE = 306, /* VAR_IP_RATELIMIT_COOKIE */ - YYSYMBOL_VAR_FORWARD_NO_CACHE = 307, /* VAR_FORWARD_NO_CACHE */ - YYSYMBOL_VAR_STUB_NO_CACHE = 308, /* VAR_STUB_NO_CACHE */ - YYSYMBOL_VAR_LOG_SERVFAIL = 309, /* VAR_LOG_SERVFAIL */ - YYSYMBOL_VAR_DENY_ANY = 310, /* VAR_DENY_ANY */ - YYSYMBOL_VAR_UNKNOWN_SERVER_TIME_LIMIT = 311, /* VAR_UNKNOWN_SERVER_TIME_LIMIT */ - YYSYMBOL_VAR_LOG_TAG_QUERYREPLY = 312, /* VAR_LOG_TAG_QUERYREPLY */ - YYSYMBOL_VAR_STREAM_WAIT_SIZE = 313, /* VAR_STREAM_WAIT_SIZE */ - YYSYMBOL_VAR_TLS_CIPHERS = 314, /* VAR_TLS_CIPHERS */ - YYSYMBOL_VAR_TLS_CIPHERSUITES = 315, /* VAR_TLS_CIPHERSUITES */ - YYSYMBOL_VAR_TLS_USE_SNI = 316, /* VAR_TLS_USE_SNI */ - YYSYMBOL_VAR_IPSET = 317, /* VAR_IPSET */ - YYSYMBOL_VAR_IPSET_NAME_V4 = 318, /* VAR_IPSET_NAME_V4 */ - YYSYMBOL_VAR_IPSET_NAME_V6 = 319, /* VAR_IPSET_NAME_V6 */ - YYSYMBOL_VAR_TLS_SESSION_TICKET_KEYS = 320, /* VAR_TLS_SESSION_TICKET_KEYS */ - YYSYMBOL_VAR_RPZ = 321, /* VAR_RPZ */ - YYSYMBOL_VAR_TAGS = 322, /* VAR_TAGS */ - YYSYMBOL_VAR_RPZ_ACTION_OVERRIDE = 323, /* VAR_RPZ_ACTION_OVERRIDE */ - YYSYMBOL_VAR_RPZ_CNAME_OVERRIDE = 324, /* VAR_RPZ_CNAME_OVERRIDE */ - YYSYMBOL_VAR_RPZ_LOG = 325, /* VAR_RPZ_LOG */ - YYSYMBOL_VAR_RPZ_LOG_NAME = 326, /* VAR_RPZ_LOG_NAME */ - YYSYMBOL_VAR_DYNLIB = 327, /* VAR_DYNLIB */ - YYSYMBOL_VAR_DYNLIB_FILE = 328, /* VAR_DYNLIB_FILE */ - YYSYMBOL_VAR_EDNS_CLIENT_STRING = 329, /* VAR_EDNS_CLIENT_STRING */ - YYSYMBOL_VAR_EDNS_CLIENT_STRING_OPCODE = 330, /* VAR_EDNS_CLIENT_STRING_OPCODE */ - YYSYMBOL_VAR_NSID = 331, /* VAR_NSID */ - YYSYMBOL_VAR_ZONEMD_PERMISSIVE_MODE = 332, /* VAR_ZONEMD_PERMISSIVE_MODE */ - YYSYMBOL_VAR_ZONEMD_CHECK = 333, /* VAR_ZONEMD_CHECK */ - YYSYMBOL_VAR_ZONEMD_REJECT_ABSENCE = 334, /* VAR_ZONEMD_REJECT_ABSENCE */ - YYSYMBOL_VAR_RPZ_SIGNAL_NXDOMAIN_RA = 335, /* VAR_RPZ_SIGNAL_NXDOMAIN_RA */ - YYSYMBOL_VAR_INTERFACE_AUTOMATIC_PORTS = 336, /* VAR_INTERFACE_AUTOMATIC_PORTS */ - YYSYMBOL_VAR_EDE = 337, /* VAR_EDE */ - YYSYMBOL_VAR_INTERFACE_ACTION = 338, /* VAR_INTERFACE_ACTION */ - YYSYMBOL_VAR_INTERFACE_VIEW = 339, /* VAR_INTERFACE_VIEW */ - YYSYMBOL_VAR_INTERFACE_TAG = 340, /* VAR_INTERFACE_TAG */ - YYSYMBOL_VAR_INTERFACE_TAG_ACTION = 341, /* VAR_INTERFACE_TAG_ACTION */ - YYSYMBOL_VAR_INTERFACE_TAG_DATA = 342, /* VAR_INTERFACE_TAG_DATA */ - YYSYMBOL_VAR_PROXY_PROTOCOL_PORT = 343, /* VAR_PROXY_PROTOCOL_PORT */ - YYSYMBOL_VAR_STATISTICS_INHIBIT_ZERO = 344, /* VAR_STATISTICS_INHIBIT_ZERO */ - YYSYMBOL_VAR_HARDEN_UNKNOWN_ADDITIONAL = 345, /* VAR_HARDEN_UNKNOWN_ADDITIONAL */ - YYSYMBOL_YYACCEPT = 346, /* $accept */ - YYSYMBOL_toplevelvars = 347, /* toplevelvars */ - YYSYMBOL_toplevelvar = 348, /* toplevelvar */ - YYSYMBOL_force_toplevel = 349, /* force_toplevel */ - YYSYMBOL_serverstart = 350, /* serverstart */ - YYSYMBOL_contents_server = 351, /* contents_server */ - YYSYMBOL_content_server = 352, /* content_server */ - YYSYMBOL_stubstart = 353, /* stubstart */ - YYSYMBOL_contents_stub = 354, /* contents_stub */ - YYSYMBOL_content_stub = 355, /* content_stub */ - YYSYMBOL_forwardstart = 356, /* forwardstart */ - YYSYMBOL_contents_forward = 357, /* contents_forward */ - YYSYMBOL_content_forward = 358, /* content_forward */ - YYSYMBOL_viewstart = 359, /* viewstart */ - YYSYMBOL_contents_view = 360, /* contents_view */ - YYSYMBOL_content_view = 361, /* content_view */ - YYSYMBOL_authstart = 362, /* authstart */ - YYSYMBOL_contents_auth = 363, /* contents_auth */ - YYSYMBOL_content_auth = 364, /* content_auth */ - YYSYMBOL_rpz_tag = 365, /* rpz_tag */ - YYSYMBOL_rpz_action_override = 366, /* rpz_action_override */ - YYSYMBOL_rpz_cname_override = 367, /* rpz_cname_override */ - YYSYMBOL_rpz_log = 368, /* rpz_log */ - YYSYMBOL_rpz_log_name = 369, /* rpz_log_name */ - YYSYMBOL_rpz_signal_nxdomain_ra = 370, /* rpz_signal_nxdomain_ra */ - YYSYMBOL_rpzstart = 371, /* rpzstart */ - YYSYMBOL_contents_rpz = 372, /* contents_rpz */ - YYSYMBOL_content_rpz = 373, /* content_rpz */ - YYSYMBOL_server_num_threads = 374, /* server_num_threads */ - YYSYMBOL_server_verbosity = 375, /* server_verbosity */ - YYSYMBOL_server_statistics_interval = 376, /* server_statistics_interval */ - YYSYMBOL_server_statistics_cumulative = 377, /* server_statistics_cumulative */ - YYSYMBOL_server_extended_statistics = 378, /* server_extended_statistics */ - YYSYMBOL_server_statistics_inhibit_zero = 379, /* server_statistics_inhibit_zero */ - YYSYMBOL_server_shm_enable = 380, /* server_shm_enable */ - YYSYMBOL_server_shm_key = 381, /* server_shm_key */ - YYSYMBOL_server_port = 382, /* server_port */ - YYSYMBOL_server_send_client_subnet = 383, /* server_send_client_subnet */ - YYSYMBOL_server_client_subnet_zone = 384, /* server_client_subnet_zone */ - YYSYMBOL_server_client_subnet_always_forward = 385, /* server_client_subnet_always_forward */ - YYSYMBOL_server_client_subnet_opcode = 386, /* server_client_subnet_opcode */ - YYSYMBOL_server_max_client_subnet_ipv4 = 387, /* server_max_client_subnet_ipv4 */ - YYSYMBOL_server_max_client_subnet_ipv6 = 388, /* server_max_client_subnet_ipv6 */ - YYSYMBOL_server_min_client_subnet_ipv4 = 389, /* server_min_client_subnet_ipv4 */ - YYSYMBOL_server_min_client_subnet_ipv6 = 390, /* server_min_client_subnet_ipv6 */ - YYSYMBOL_server_max_ecs_tree_size_ipv4 = 391, /* server_max_ecs_tree_size_ipv4 */ - YYSYMBOL_server_max_ecs_tree_size_ipv6 = 392, /* server_max_ecs_tree_size_ipv6 */ - YYSYMBOL_server_interface = 393, /* server_interface */ - YYSYMBOL_server_outgoing_interface = 394, /* server_outgoing_interface */ - YYSYMBOL_server_outgoing_range = 395, /* server_outgoing_range */ - YYSYMBOL_server_outgoing_port_permit = 396, /* server_outgoing_port_permit */ - YYSYMBOL_server_outgoing_port_avoid = 397, /* server_outgoing_port_avoid */ - YYSYMBOL_server_outgoing_num_tcp = 398, /* server_outgoing_num_tcp */ - YYSYMBOL_server_incoming_num_tcp = 399, /* server_incoming_num_tcp */ - YYSYMBOL_server_interface_automatic = 400, /* server_interface_automatic */ - YYSYMBOL_server_interface_automatic_ports = 401, /* server_interface_automatic_ports */ - YYSYMBOL_server_do_ip4 = 402, /* server_do_ip4 */ - YYSYMBOL_server_do_ip6 = 403, /* server_do_ip6 */ - YYSYMBOL_server_do_nat64 = 404, /* server_do_nat64 */ - YYSYMBOL_server_do_udp = 405, /* server_do_udp */ - YYSYMBOL_server_do_tcp = 406, /* server_do_tcp */ - YYSYMBOL_server_prefer_ip4 = 407, /* server_prefer_ip4 */ - YYSYMBOL_server_prefer_ip6 = 408, /* server_prefer_ip6 */ - YYSYMBOL_server_tcp_mss = 409, /* server_tcp_mss */ - YYSYMBOL_server_outgoing_tcp_mss = 410, /* server_outgoing_tcp_mss */ - YYSYMBOL_server_tcp_idle_timeout = 411, /* server_tcp_idle_timeout */ - YYSYMBOL_server_max_reuse_tcp_queries = 412, /* server_max_reuse_tcp_queries */ - YYSYMBOL_server_tcp_reuse_timeout = 413, /* server_tcp_reuse_timeout */ - YYSYMBOL_server_tcp_auth_query_timeout = 414, /* server_tcp_auth_query_timeout */ - YYSYMBOL_server_tcp_keepalive = 415, /* server_tcp_keepalive */ - YYSYMBOL_server_tcp_keepalive_timeout = 416, /* server_tcp_keepalive_timeout */ - YYSYMBOL_server_sock_queue_timeout = 417, /* server_sock_queue_timeout */ - YYSYMBOL_server_tcp_upstream = 418, /* server_tcp_upstream */ - YYSYMBOL_server_udp_upstream_without_downstream = 419, /* server_udp_upstream_without_downstream */ - YYSYMBOL_server_ssl_upstream = 420, /* server_ssl_upstream */ - YYSYMBOL_server_ssl_service_key = 421, /* server_ssl_service_key */ - YYSYMBOL_server_ssl_service_pem = 422, /* server_ssl_service_pem */ - YYSYMBOL_server_ssl_port = 423, /* server_ssl_port */ - YYSYMBOL_server_tls_cert_bundle = 424, /* server_tls_cert_bundle */ - YYSYMBOL_server_tls_win_cert = 425, /* server_tls_win_cert */ - YYSYMBOL_server_tls_additional_port = 426, /* server_tls_additional_port */ - YYSYMBOL_server_tls_ciphers = 427, /* server_tls_ciphers */ - YYSYMBOL_server_tls_ciphersuites = 428, /* server_tls_ciphersuites */ - YYSYMBOL_server_tls_session_ticket_keys = 429, /* server_tls_session_ticket_keys */ - YYSYMBOL_server_tls_use_sni = 430, /* server_tls_use_sni */ - YYSYMBOL_server_https_port = 431, /* server_https_port */ - YYSYMBOL_server_http_endpoint = 432, /* server_http_endpoint */ - YYSYMBOL_server_http_max_streams = 433, /* server_http_max_streams */ - YYSYMBOL_server_http_query_buffer_size = 434, /* server_http_query_buffer_size */ - YYSYMBOL_server_http_response_buffer_size = 435, /* server_http_response_buffer_size */ - YYSYMBOL_server_http_nodelay = 436, /* server_http_nodelay */ - YYSYMBOL_server_http_notls_downstream = 437, /* server_http_notls_downstream */ - YYSYMBOL_server_use_systemd = 438, /* server_use_systemd */ - YYSYMBOL_server_do_daemonize = 439, /* server_do_daemonize */ - YYSYMBOL_server_use_syslog = 440, /* server_use_syslog */ - YYSYMBOL_server_log_time_ascii = 441, /* server_log_time_ascii */ - YYSYMBOL_server_log_queries = 442, /* server_log_queries */ - YYSYMBOL_server_log_replies = 443, /* server_log_replies */ - YYSYMBOL_server_log_tag_queryreply = 444, /* server_log_tag_queryreply */ - YYSYMBOL_server_log_servfail = 445, /* server_log_servfail */ - YYSYMBOL_server_log_local_actions = 446, /* server_log_local_actions */ - YYSYMBOL_server_chroot = 447, /* server_chroot */ - YYSYMBOL_server_username = 448, /* server_username */ - YYSYMBOL_server_directory = 449, /* server_directory */ - YYSYMBOL_server_logfile = 450, /* server_logfile */ - YYSYMBOL_server_pidfile = 451, /* server_pidfile */ - YYSYMBOL_server_root_hints = 452, /* server_root_hints */ - YYSYMBOL_server_dlv_anchor_file = 453, /* server_dlv_anchor_file */ - YYSYMBOL_server_dlv_anchor = 454, /* server_dlv_anchor */ - YYSYMBOL_server_auto_trust_anchor_file = 455, /* server_auto_trust_anchor_file */ - YYSYMBOL_server_trust_anchor_file = 456, /* server_trust_anchor_file */ - YYSYMBOL_server_trusted_keys_file = 457, /* server_trusted_keys_file */ - YYSYMBOL_server_trust_anchor = 458, /* server_trust_anchor */ - YYSYMBOL_server_trust_anchor_signaling = 459, /* server_trust_anchor_signaling */ - YYSYMBOL_server_root_key_sentinel = 460, /* server_root_key_sentinel */ - YYSYMBOL_server_domain_insecure = 461, /* server_domain_insecure */ - YYSYMBOL_server_hide_identity = 462, /* server_hide_identity */ - YYSYMBOL_server_hide_version = 463, /* server_hide_version */ - YYSYMBOL_server_hide_trustanchor = 464, /* server_hide_trustanchor */ - YYSYMBOL_server_hide_http_user_agent = 465, /* server_hide_http_user_agent */ - YYSYMBOL_server_identity = 466, /* server_identity */ - YYSYMBOL_server_version = 467, /* server_version */ - YYSYMBOL_server_http_user_agent = 468, /* server_http_user_agent */ - YYSYMBOL_server_nsid = 469, /* server_nsid */ - YYSYMBOL_server_so_rcvbuf = 470, /* server_so_rcvbuf */ - YYSYMBOL_server_so_sndbuf = 471, /* server_so_sndbuf */ - YYSYMBOL_server_so_reuseport = 472, /* server_so_reuseport */ - YYSYMBOL_server_ip_transparent = 473, /* server_ip_transparent */ - YYSYMBOL_server_ip_freebind = 474, /* server_ip_freebind */ - YYSYMBOL_server_ip_dscp = 475, /* server_ip_dscp */ - YYSYMBOL_server_stream_wait_size = 476, /* server_stream_wait_size */ - YYSYMBOL_server_edns_buffer_size = 477, /* server_edns_buffer_size */ - YYSYMBOL_server_msg_buffer_size = 478, /* server_msg_buffer_size */ - YYSYMBOL_server_msg_cache_size = 479, /* server_msg_cache_size */ - YYSYMBOL_server_msg_cache_slabs = 480, /* server_msg_cache_slabs */ - YYSYMBOL_server_num_queries_per_thread = 481, /* server_num_queries_per_thread */ - YYSYMBOL_server_jostle_timeout = 482, /* server_jostle_timeout */ - YYSYMBOL_server_delay_close = 483, /* server_delay_close */ - YYSYMBOL_server_udp_connect = 484, /* server_udp_connect */ - YYSYMBOL_server_unblock_lan_zones = 485, /* server_unblock_lan_zones */ - YYSYMBOL_server_insecure_lan_zones = 486, /* server_insecure_lan_zones */ - YYSYMBOL_server_rrset_cache_size = 487, /* server_rrset_cache_size */ - YYSYMBOL_server_rrset_cache_slabs = 488, /* server_rrset_cache_slabs */ - YYSYMBOL_server_infra_host_ttl = 489, /* server_infra_host_ttl */ - YYSYMBOL_server_infra_lame_ttl = 490, /* server_infra_lame_ttl */ - YYSYMBOL_server_infra_cache_numhosts = 491, /* server_infra_cache_numhosts */ - YYSYMBOL_server_infra_cache_lame_size = 492, /* server_infra_cache_lame_size */ - YYSYMBOL_server_infra_cache_slabs = 493, /* server_infra_cache_slabs */ - YYSYMBOL_server_infra_cache_min_rtt = 494, /* server_infra_cache_min_rtt */ - YYSYMBOL_server_infra_cache_max_rtt = 495, /* server_infra_cache_max_rtt */ - YYSYMBOL_server_infra_keep_probing = 496, /* server_infra_keep_probing */ - YYSYMBOL_server_target_fetch_policy = 497, /* server_target_fetch_policy */ - YYSYMBOL_server_harden_short_bufsize = 498, /* server_harden_short_bufsize */ - YYSYMBOL_server_harden_large_queries = 499, /* server_harden_large_queries */ - YYSYMBOL_server_harden_glue = 500, /* server_harden_glue */ - YYSYMBOL_server_harden_dnssec_stripped = 501, /* server_harden_dnssec_stripped */ - YYSYMBOL_server_harden_below_nxdomain = 502, /* server_harden_below_nxdomain */ - YYSYMBOL_server_harden_referral_path = 503, /* server_harden_referral_path */ - YYSYMBOL_server_harden_algo_downgrade = 504, /* server_harden_algo_downgrade */ - YYSYMBOL_server_harden_unknown_additional = 505, /* server_harden_unknown_additional */ - YYSYMBOL_server_use_caps_for_id = 506, /* server_use_caps_for_id */ - YYSYMBOL_server_caps_whitelist = 507, /* server_caps_whitelist */ - YYSYMBOL_server_private_address = 508, /* server_private_address */ - YYSYMBOL_server_private_domain = 509, /* server_private_domain */ - YYSYMBOL_server_prefetch = 510, /* server_prefetch */ - YYSYMBOL_server_prefetch_key = 511, /* server_prefetch_key */ - YYSYMBOL_server_deny_any = 512, /* server_deny_any */ - YYSYMBOL_server_unwanted_reply_threshold = 513, /* server_unwanted_reply_threshold */ - YYSYMBOL_server_do_not_query_address = 514, /* server_do_not_query_address */ - YYSYMBOL_server_do_not_query_localhost = 515, /* server_do_not_query_localhost */ - YYSYMBOL_server_access_control = 516, /* server_access_control */ - YYSYMBOL_server_interface_action = 517, /* server_interface_action */ - YYSYMBOL_server_module_conf = 518, /* server_module_conf */ - YYSYMBOL_server_val_override_date = 519, /* server_val_override_date */ - YYSYMBOL_server_val_sig_skew_min = 520, /* server_val_sig_skew_min */ - YYSYMBOL_server_val_sig_skew_max = 521, /* server_val_sig_skew_max */ - YYSYMBOL_server_val_max_restart = 522, /* server_val_max_restart */ - YYSYMBOL_server_cache_max_ttl = 523, /* server_cache_max_ttl */ - YYSYMBOL_server_cache_max_negative_ttl = 524, /* server_cache_max_negative_ttl */ - YYSYMBOL_server_cache_min_ttl = 525, /* server_cache_min_ttl */ - YYSYMBOL_server_bogus_ttl = 526, /* server_bogus_ttl */ - YYSYMBOL_server_val_clean_additional = 527, /* server_val_clean_additional */ - YYSYMBOL_server_val_permissive_mode = 528, /* server_val_permissive_mode */ - YYSYMBOL_server_aggressive_nsec = 529, /* server_aggressive_nsec */ - YYSYMBOL_server_ignore_cd_flag = 530, /* server_ignore_cd_flag */ - YYSYMBOL_server_serve_expired = 531, /* server_serve_expired */ - YYSYMBOL_server_serve_expired_ttl = 532, /* server_serve_expired_ttl */ - YYSYMBOL_server_serve_expired_ttl_reset = 533, /* server_serve_expired_ttl_reset */ - YYSYMBOL_server_serve_expired_reply_ttl = 534, /* server_serve_expired_reply_ttl */ - YYSYMBOL_server_serve_expired_client_timeout = 535, /* server_serve_expired_client_timeout */ - YYSYMBOL_server_ede_serve_expired = 536, /* server_ede_serve_expired */ - YYSYMBOL_server_serve_original_ttl = 537, /* server_serve_original_ttl */ - YYSYMBOL_server_fake_dsa = 538, /* server_fake_dsa */ - YYSYMBOL_server_fake_sha1 = 539, /* server_fake_sha1 */ - YYSYMBOL_server_val_log_level = 540, /* server_val_log_level */ - YYSYMBOL_server_val_nsec3_keysize_iterations = 541, /* server_val_nsec3_keysize_iterations */ - YYSYMBOL_server_zonemd_permissive_mode = 542, /* server_zonemd_permissive_mode */ - YYSYMBOL_server_add_holddown = 543, /* server_add_holddown */ - YYSYMBOL_server_del_holddown = 544, /* server_del_holddown */ - YYSYMBOL_server_keep_missing = 545, /* server_keep_missing */ - YYSYMBOL_server_permit_small_holddown = 546, /* server_permit_small_holddown */ - YYSYMBOL_server_key_cache_size = 547, /* server_key_cache_size */ - YYSYMBOL_server_key_cache_slabs = 548, /* server_key_cache_slabs */ - YYSYMBOL_server_neg_cache_size = 549, /* server_neg_cache_size */ - YYSYMBOL_server_local_zone = 550, /* server_local_zone */ - YYSYMBOL_server_local_data = 551, /* server_local_data */ - YYSYMBOL_server_local_data_ptr = 552, /* server_local_data_ptr */ - YYSYMBOL_server_minimal_responses = 553, /* server_minimal_responses */ - YYSYMBOL_server_rrset_roundrobin = 554, /* server_rrset_roundrobin */ - YYSYMBOL_server_unknown_server_time_limit = 555, /* server_unknown_server_time_limit */ - YYSYMBOL_server_max_udp_size = 556, /* server_max_udp_size */ - YYSYMBOL_server_dns64_prefix = 557, /* server_dns64_prefix */ - YYSYMBOL_server_dns64_synthall = 558, /* server_dns64_synthall */ - YYSYMBOL_server_dns64_ignore_aaaa = 559, /* server_dns64_ignore_aaaa */ - YYSYMBOL_server_nat64_prefix = 560, /* server_nat64_prefix */ - YYSYMBOL_server_define_tag = 561, /* server_define_tag */ - YYSYMBOL_server_local_zone_tag = 562, /* server_local_zone_tag */ - YYSYMBOL_server_access_control_tag = 563, /* server_access_control_tag */ - YYSYMBOL_server_access_control_tag_action = 564, /* server_access_control_tag_action */ - YYSYMBOL_server_access_control_tag_data = 565, /* server_access_control_tag_data */ - YYSYMBOL_server_local_zone_override = 566, /* server_local_zone_override */ - YYSYMBOL_server_access_control_view = 567, /* server_access_control_view */ - YYSYMBOL_server_interface_tag = 568, /* server_interface_tag */ - YYSYMBOL_server_interface_tag_action = 569, /* server_interface_tag_action */ - YYSYMBOL_server_interface_tag_data = 570, /* server_interface_tag_data */ - YYSYMBOL_server_interface_view = 571, /* server_interface_view */ - YYSYMBOL_server_response_ip_tag = 572, /* server_response_ip_tag */ - YYSYMBOL_server_ip_ratelimit = 573, /* server_ip_ratelimit */ - YYSYMBOL_server_ip_ratelimit_cookie = 574, /* server_ip_ratelimit_cookie */ - YYSYMBOL_server_ratelimit = 575, /* server_ratelimit */ - YYSYMBOL_server_ip_ratelimit_size = 576, /* server_ip_ratelimit_size */ - YYSYMBOL_server_ratelimit_size = 577, /* server_ratelimit_size */ - YYSYMBOL_server_ip_ratelimit_slabs = 578, /* server_ip_ratelimit_slabs */ - YYSYMBOL_server_ratelimit_slabs = 579, /* server_ratelimit_slabs */ - YYSYMBOL_server_ratelimit_for_domain = 580, /* server_ratelimit_for_domain */ - YYSYMBOL_server_ratelimit_below_domain = 581, /* server_ratelimit_below_domain */ - YYSYMBOL_server_ip_ratelimit_factor = 582, /* server_ip_ratelimit_factor */ - YYSYMBOL_server_ratelimit_factor = 583, /* server_ratelimit_factor */ - YYSYMBOL_server_ip_ratelimit_backoff = 584, /* server_ip_ratelimit_backoff */ - YYSYMBOL_server_ratelimit_backoff = 585, /* server_ratelimit_backoff */ - YYSYMBOL_server_outbound_msg_retry = 586, /* server_outbound_msg_retry */ - YYSYMBOL_server_max_sent_count = 587, /* server_max_sent_count */ - YYSYMBOL_server_max_query_restarts = 588, /* server_max_query_restarts */ - YYSYMBOL_server_low_rtt = 589, /* server_low_rtt */ - YYSYMBOL_server_fast_server_num = 590, /* server_fast_server_num */ - YYSYMBOL_server_fast_server_permil = 591, /* server_fast_server_permil */ - YYSYMBOL_server_qname_minimisation = 592, /* server_qname_minimisation */ - YYSYMBOL_server_qname_minimisation_strict = 593, /* server_qname_minimisation_strict */ - YYSYMBOL_server_pad_responses = 594, /* server_pad_responses */ - YYSYMBOL_server_pad_responses_block_size = 595, /* server_pad_responses_block_size */ - YYSYMBOL_server_pad_queries = 596, /* server_pad_queries */ - YYSYMBOL_server_pad_queries_block_size = 597, /* server_pad_queries_block_size */ - YYSYMBOL_server_ipsecmod_enabled = 598, /* server_ipsecmod_enabled */ - YYSYMBOL_server_ipsecmod_ignore_bogus = 599, /* server_ipsecmod_ignore_bogus */ - YYSYMBOL_server_ipsecmod_hook = 600, /* server_ipsecmod_hook */ - YYSYMBOL_server_ipsecmod_max_ttl = 601, /* server_ipsecmod_max_ttl */ - YYSYMBOL_server_ipsecmod_whitelist = 602, /* server_ipsecmod_whitelist */ - YYSYMBOL_server_ipsecmod_strict = 603, /* server_ipsecmod_strict */ - YYSYMBOL_server_edns_client_string = 604, /* server_edns_client_string */ - YYSYMBOL_server_edns_client_string_opcode = 605, /* server_edns_client_string_opcode */ - YYSYMBOL_server_ede = 606, /* server_ede */ - YYSYMBOL_server_proxy_protocol_port = 607, /* server_proxy_protocol_port */ - YYSYMBOL_stub_name = 608, /* stub_name */ - YYSYMBOL_stub_host = 609, /* stub_host */ - YYSYMBOL_stub_addr = 610, /* stub_addr */ - YYSYMBOL_stub_first = 611, /* stub_first */ - YYSYMBOL_stub_no_cache = 612, /* stub_no_cache */ - YYSYMBOL_stub_ssl_upstream = 613, /* stub_ssl_upstream */ - YYSYMBOL_stub_tcp_upstream = 614, /* stub_tcp_upstream */ - YYSYMBOL_stub_prime = 615, /* stub_prime */ - YYSYMBOL_forward_name = 616, /* forward_name */ - YYSYMBOL_forward_host = 617, /* forward_host */ - YYSYMBOL_forward_addr = 618, /* forward_addr */ - YYSYMBOL_forward_first = 619, /* forward_first */ - YYSYMBOL_forward_no_cache = 620, /* forward_no_cache */ - YYSYMBOL_forward_ssl_upstream = 621, /* forward_ssl_upstream */ - YYSYMBOL_forward_tcp_upstream = 622, /* forward_tcp_upstream */ - YYSYMBOL_auth_name = 623, /* auth_name */ - YYSYMBOL_auth_zonefile = 624, /* auth_zonefile */ - YYSYMBOL_auth_master = 625, /* auth_master */ - YYSYMBOL_auth_url = 626, /* auth_url */ - YYSYMBOL_auth_allow_notify = 627, /* auth_allow_notify */ - YYSYMBOL_auth_zonemd_check = 628, /* auth_zonemd_check */ - YYSYMBOL_auth_zonemd_reject_absence = 629, /* auth_zonemd_reject_absence */ - YYSYMBOL_auth_for_downstream = 630, /* auth_for_downstream */ - YYSYMBOL_auth_for_upstream = 631, /* auth_for_upstream */ - YYSYMBOL_auth_fallback_enabled = 632, /* auth_fallback_enabled */ - YYSYMBOL_view_name = 633, /* view_name */ - YYSYMBOL_view_local_zone = 634, /* view_local_zone */ - YYSYMBOL_view_response_ip = 635, /* view_response_ip */ - YYSYMBOL_view_response_ip_data = 636, /* view_response_ip_data */ - YYSYMBOL_view_local_data = 637, /* view_local_data */ - YYSYMBOL_view_local_data_ptr = 638, /* view_local_data_ptr */ - YYSYMBOL_view_first = 639, /* view_first */ - YYSYMBOL_rcstart = 640, /* rcstart */ - YYSYMBOL_contents_rc = 641, /* contents_rc */ - YYSYMBOL_content_rc = 642, /* content_rc */ - YYSYMBOL_rc_control_enable = 643, /* rc_control_enable */ - YYSYMBOL_rc_control_port = 644, /* rc_control_port */ - YYSYMBOL_rc_control_interface = 645, /* rc_control_interface */ - YYSYMBOL_rc_control_use_cert = 646, /* rc_control_use_cert */ - YYSYMBOL_rc_server_key_file = 647, /* rc_server_key_file */ - YYSYMBOL_rc_server_cert_file = 648, /* rc_server_cert_file */ - YYSYMBOL_rc_control_key_file = 649, /* rc_control_key_file */ - YYSYMBOL_rc_control_cert_file = 650, /* rc_control_cert_file */ - YYSYMBOL_dtstart = 651, /* dtstart */ - YYSYMBOL_contents_dt = 652, /* contents_dt */ - YYSYMBOL_content_dt = 653, /* content_dt */ - YYSYMBOL_dt_dnstap_enable = 654, /* dt_dnstap_enable */ - YYSYMBOL_dt_dnstap_bidirectional = 655, /* dt_dnstap_bidirectional */ - YYSYMBOL_dt_dnstap_socket_path = 656, /* dt_dnstap_socket_path */ - YYSYMBOL_dt_dnstap_ip = 657, /* dt_dnstap_ip */ - YYSYMBOL_dt_dnstap_tls = 658, /* dt_dnstap_tls */ - YYSYMBOL_dt_dnstap_tls_server_name = 659, /* dt_dnstap_tls_server_name */ - YYSYMBOL_dt_dnstap_tls_cert_bundle = 660, /* dt_dnstap_tls_cert_bundle */ - YYSYMBOL_dt_dnstap_tls_client_key_file = 661, /* dt_dnstap_tls_client_key_file */ - YYSYMBOL_dt_dnstap_tls_client_cert_file = 662, /* dt_dnstap_tls_client_cert_file */ - YYSYMBOL_dt_dnstap_send_identity = 663, /* dt_dnstap_send_identity */ - YYSYMBOL_dt_dnstap_send_version = 664, /* dt_dnstap_send_version */ - YYSYMBOL_dt_dnstap_identity = 665, /* dt_dnstap_identity */ - YYSYMBOL_dt_dnstap_version = 666, /* dt_dnstap_version */ - YYSYMBOL_dt_dnstap_log_resolver_query_messages = 667, /* dt_dnstap_log_resolver_query_messages */ - YYSYMBOL_dt_dnstap_log_resolver_response_messages = 668, /* dt_dnstap_log_resolver_response_messages */ - YYSYMBOL_dt_dnstap_log_client_query_messages = 669, /* dt_dnstap_log_client_query_messages */ - YYSYMBOL_dt_dnstap_log_client_response_messages = 670, /* dt_dnstap_log_client_response_messages */ - YYSYMBOL_dt_dnstap_log_forwarder_query_messages = 671, /* dt_dnstap_log_forwarder_query_messages */ - YYSYMBOL_dt_dnstap_log_forwarder_response_messages = 672, /* dt_dnstap_log_forwarder_response_messages */ - YYSYMBOL_pythonstart = 673, /* pythonstart */ - YYSYMBOL_contents_py = 674, /* contents_py */ - YYSYMBOL_content_py = 675, /* content_py */ - YYSYMBOL_py_script = 676, /* py_script */ - YYSYMBOL_dynlibstart = 677, /* dynlibstart */ - YYSYMBOL_contents_dl = 678, /* contents_dl */ - YYSYMBOL_content_dl = 679, /* content_dl */ - YYSYMBOL_dl_file = 680, /* dl_file */ - YYSYMBOL_server_disable_dnssec_lame_check = 681, /* server_disable_dnssec_lame_check */ - YYSYMBOL_server_log_identity = 682, /* server_log_identity */ - YYSYMBOL_server_response_ip = 683, /* server_response_ip */ - YYSYMBOL_server_response_ip_data = 684, /* server_response_ip_data */ - YYSYMBOL_dnscstart = 685, /* dnscstart */ - YYSYMBOL_contents_dnsc = 686, /* contents_dnsc */ - YYSYMBOL_content_dnsc = 687, /* content_dnsc */ - YYSYMBOL_dnsc_dnscrypt_enable = 688, /* dnsc_dnscrypt_enable */ - YYSYMBOL_dnsc_dnscrypt_port = 689, /* dnsc_dnscrypt_port */ - YYSYMBOL_dnsc_dnscrypt_provider = 690, /* dnsc_dnscrypt_provider */ - YYSYMBOL_dnsc_dnscrypt_provider_cert = 691, /* dnsc_dnscrypt_provider_cert */ - YYSYMBOL_dnsc_dnscrypt_provider_cert_rotated = 692, /* dnsc_dnscrypt_provider_cert_rotated */ - YYSYMBOL_dnsc_dnscrypt_secret_key = 693, /* dnsc_dnscrypt_secret_key */ - YYSYMBOL_dnsc_dnscrypt_shared_secret_cache_size = 694, /* dnsc_dnscrypt_shared_secret_cache_size */ - YYSYMBOL_dnsc_dnscrypt_shared_secret_cache_slabs = 695, /* dnsc_dnscrypt_shared_secret_cache_slabs */ - YYSYMBOL_dnsc_dnscrypt_nonce_cache_size = 696, /* dnsc_dnscrypt_nonce_cache_size */ - YYSYMBOL_dnsc_dnscrypt_nonce_cache_slabs = 697, /* dnsc_dnscrypt_nonce_cache_slabs */ - YYSYMBOL_cachedbstart = 698, /* cachedbstart */ - YYSYMBOL_contents_cachedb = 699, /* contents_cachedb */ - YYSYMBOL_content_cachedb = 700, /* content_cachedb */ - YYSYMBOL_cachedb_backend_name = 701, /* cachedb_backend_name */ - YYSYMBOL_cachedb_secret_seed = 702, /* cachedb_secret_seed */ - YYSYMBOL_redis_server_host = 703, /* redis_server_host */ - YYSYMBOL_redis_server_port = 704, /* redis_server_port */ - YYSYMBOL_redis_server_path = 705, /* redis_server_path */ - YYSYMBOL_redis_server_password = 706, /* redis_server_password */ - YYSYMBOL_redis_timeout = 707, /* redis_timeout */ - YYSYMBOL_redis_expire_records = 708, /* redis_expire_records */ - YYSYMBOL_server_tcp_connection_limit = 709, /* server_tcp_connection_limit */ - YYSYMBOL_server_answer_cookie = 710, /* server_answer_cookie */ - YYSYMBOL_server_cookie_secret = 711, /* server_cookie_secret */ - YYSYMBOL_ipsetstart = 712, /* ipsetstart */ - YYSYMBOL_contents_ipset = 713, /* contents_ipset */ - YYSYMBOL_content_ipset = 714, /* content_ipset */ - YYSYMBOL_ipset_name_v4 = 715, /* ipset_name_v4 */ - YYSYMBOL_ipset_name_v6 = 716 /* ipset_name_v6 */ -}; -typedef enum yysymbol_kind_t yysymbol_kind_t; - - - - -#ifdef short -# undef short -#endif - -/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_STDINT_H -# endif -#endif - -/* Narrow types that promote to a signed type and that can represent a - signed or unsigned integer of at least N bits. In tables they can - save space and decrease cache pressure. Promoting to a signed type - helps avoid bugs in integer arithmetic. */ - -#ifdef __INT_LEAST8_MAX__ -typedef __INT_LEAST8_TYPE__ yytype_int8; -#elif defined YY_STDINT_H -typedef int_least8_t yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef __INT_LEAST16_MAX__ -typedef __INT_LEAST16_TYPE__ yytype_int16; -#elif defined YY_STDINT_H -typedef int_least16_t yytype_int16; -#else -typedef short yytype_int16; -#endif - -/* Work around bug in HP-UX 11.23, which defines these macros - incorrectly for preprocessor constants. This workaround can likely - be removed in 2023, as HPE has promised support for HP-UX 11.23 - (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of - . */ -#ifdef __hpux -# undef UINT_LEAST8_MAX -# undef UINT_LEAST16_MAX -# define UINT_LEAST8_MAX 255 -# define UINT_LEAST16_MAX 65535 -#endif - -#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST8_TYPE__ yytype_uint8; -#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST8_MAX <= INT_MAX) -typedef uint_least8_t yytype_uint8; -#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX -typedef unsigned char yytype_uint8; -#else -typedef short yytype_uint8; -#endif - -#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST16_TYPE__ yytype_uint16; -#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST16_MAX <= INT_MAX) -typedef uint_least16_t yytype_uint16; -#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX -typedef unsigned short yytype_uint16; -#else -typedef int yytype_uint16; -#endif - -#ifndef YYPTRDIFF_T -# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ -# define YYPTRDIFF_T __PTRDIFF_TYPE__ -# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined PTRDIFF_MAX -# ifndef ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# endif -# define YYPTRDIFF_T ptrdiff_t -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# else -# define YYPTRDIFF_T long -# define YYPTRDIFF_MAXIMUM LONG_MAX -# endif -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM \ - YY_CAST (YYPTRDIFF_T, \ - (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ - ? YYPTRDIFF_MAXIMUM \ - : YY_CAST (YYSIZE_T, -1))) - -#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) - - -/* Stored state numbers (used for stacks). */ -typedef yytype_int16 yy_state_t; - -/* State numbers in computations. */ -typedef int yy_state_fast_t; - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - - -#ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YY_USE(E) ((void) (E)) -#else -# define YY_USE(E) /* empty */ -#endif - -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") -#endif -#ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if !defined yyoverflow - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* !defined yyoverflow */ - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yy_state_t yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYPTRDIFF_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / YYSIZEOF (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYPTRDIFF_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 2 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 737 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 346 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 371 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 719 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 1076 - -/* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 600 - - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - (0 <= (YYX) && (YYX) <= YYMAXUTOK \ - ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ - : YYSYMBOL_YYUNDEF) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_int16 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345 -}; - -#if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = -{ - 0, 204, 204, 204, 205, 205, 206, 206, 207, 207, - 207, 208, 208, 209, 209, 210, 210, 211, 213, 220, - 226, 227, 228, 228, 228, 229, 229, 230, 230, 230, - 231, 231, 231, 232, 232, 232, 233, 233, 234, 235, - 235, 235, 236, 236, 236, 237, 237, 238, 238, 239, - 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, - 244, 245, 245, 245, 246, 246, 247, 247, 247, 248, - 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, - 253, 253, 253, 254, 254, 255, 255, 256, 256, 256, - 257, 257, 258, 258, 259, 259, 260, 260, 260, 261, - 261, 262, 262, 263, 263, 264, 264, 265, 265, 266, - 266, 267, 267, 268, 268, 269, 269, 269, 270, 270, - 270, 271, 271, 271, 272, 272, 272, 272, 273, 274, - 274, 274, 275, 275, 275, 276, 276, 277, 277, 278, - 278, 278, 279, 279, 279, 280, 280, 281, 281, 281, - 282, 283, 283, 283, 284, 284, 284, 285, 285, 286, - 286, 287, 287, 288, 289, 289, 290, 290, 291, 291, - 292, 292, 293, 293, 294, 294, 295, 295, 296, 296, - 297, 297, 298, 298, 299, 299, 300, 300, 300, 301, - 301, 302, 302, 303, 303, 304, 304, 304, 305, 305, - 306, 307, 307, 308, 308, 309, 310, 310, 311, 311, - 312, 312, 312, 313, 313, 314, 314, 314, 315, 315, - 315, 316, 316, 317, 318, 318, 319, 319, 320, 320, - 321, 321, 322, 322, 322, 323, 323, 323, 324, 324, - 324, 325, 325, 326, 326, 327, 327, 328, 328, 328, - 329, 329, 330, 330, 331, 331, 332, 332, 333, 333, - 334, 334, 335, 337, 351, 352, 353, 353, 353, 353, - 353, 354, 354, 354, 356, 370, 371, 372, 372, 372, - 372, 373, 373, 373, 375, 391, 392, 393, 393, 393, - 393, 394, 394, 394, 396, 417, 418, 419, 419, 419, - 419, 420, 420, 420, 421, 421, 421, 424, 443, 460, - 468, 478, 485, 495, 514, 515, 516, 516, 516, 516, - 516, 517, 517, 517, 518, 518, 518, 518, 520, 529, - 538, 549, 558, 567, 576, 585, 596, 605, 617, 631, - 646, 657, 674, 691, 708, 725, 740, 755, 768, 783, - 792, 801, 810, 819, 828, 837, 844, 853, 862, 871, - 880, 889, 898, 907, 916, 925, 938, 949, 960, 971, - 980, 993, 1006, 1015, 1024, 1033, 1040, 1047, 1056, 1063, - 1072, 1080, 1087, 1094, 1102, 1111, 1119, 1135, 1143, 1151, - 1159, 1167, 1175, 1184, 1193, 1207, 1216, 1225, 1234, 1243, - 1252, 1261, 1268, 1275, 1301, 1309, 1316, 1323, 1330, 1337, - 1345, 1353, 1361, 1368, 1379, 1390, 1397, 1406, 1415, 1424, - 1433, 1440, 1447, 1454, 1470, 1478, 1486, 1496, 1506, 1516, - 1530, 1538, 1551, 1562, 1570, 1583, 1592, 1601, 1610, 1619, - 1629, 1639, 1647, 1660, 1669, 1677, 1686, 1694, 1707, 1716, - 1725, 1735, 1742, 1752, 1762, 1772, 1782, 1792, 1802, 1812, - 1822, 1832, 1839, 1846, 1853, 1862, 1871, 1880, 1889, 1896, - 1906, 1914, 1923, 1930, 1948, 1961, 1974, 1987, 1996, 2005, - 2014, 2023, 2033, 2043, 2054, 2063, 2072, 2081, 2090, 2099, - 2108, 2117, 2126, 2139, 2152, 2161, 2168, 2177, 2186, 2195, - 2204, 2214, 2222, 2235, 2243, 2299, 2306, 2321, 2331, 2341, - 2348, 2355, 2362, 2371, 2379, 2386, 2400, 2421, 2442, 2454, - 2466, 2478, 2487, 2508, 2520, 2532, 2541, 2562, 2571, 2580, - 2589, 2597, 2605, 2618, 2631, 2646, 2661, 2670, 2679, 2689, - 2699, 2708, 2717, 2726, 2732, 2741, 2750, 2760, 2770, 2780, - 2789, 2799, 2808, 2821, 2834, 2846, 2860, 2872, 2886, 2895, - 2906, 2915, 2922, 2932, 2939, 2946, 2955, 2964, 2974, 2984, - 2994, 3004, 3011, 3018, 3027, 3036, 3046, 3056, 3066, 3073, - 3080, 3087, 3095, 3105, 3115, 3125, 3135, 3145, 3155, 3211, - 3221, 3229, 3237, 3252, 3261, 3267, 3268, 3269, 3269, 3269, - 3270, 3270, 3270, 3271, 3271, 3273, 3283, 3292, 3299, 3306, - 3313, 3320, 3327, 3334, 3340, 3341, 3342, 3342, 3342, 3343, - 3343, 3343, 3344, 3345, 3345, 3346, 3346, 3347, 3347, 3348, - 3349, 3350, 3351, 3352, 3353, 3355, 3364, 3374, 3381, 3388, - 3397, 3404, 3411, 3418, 3425, 3434, 3443, 3450, 3457, 3467, - 3477, 3487, 3497, 3507, 3517, 3523, 3524, 3525, 3527, 3534, - 3540, 3541, 3542, 3544, 3551, 3561, 3568, 3577, 3585, 3591, - 3592, 3594, 3594, 3594, 3595, 3595, 3596, 3597, 3598, 3599, - 3600, 3602, 3611, 3620, 3627, 3636, 3643, 3652, 3660, 3673, - 3681, 3694, 3700, 3701, 3702, 3702, 3703, 3703, 3703, 3704, - 3704, 3704, 3706, 3718, 3730, 3742, 3757, 3769, 3781, 3794, - 3807, 3818, 3827, 3843, 3849, 3850, 3851, 3851, 3853, 3868 -}; -#endif - -/** Accessing symbol of state STATE. */ -#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) - -#if YYDEBUG || 0 -/* The user-facing name of the symbol whose (internal) number is - YYSYMBOL. No bounds checking. */ -static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; - -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "\"end of file\"", "error", "\"invalid token\"", "SPACE", "LETTER", - "NEWLINE", "COMMENT", "COLON", "ANY", "ZONESTR", "STRING_ARG", - "VAR_FORCE_TOPLEVEL", "VAR_SERVER", "VAR_VERBOSITY", "VAR_NUM_THREADS", - "VAR_PORT", "VAR_OUTGOING_RANGE", "VAR_INTERFACE", "VAR_PREFER_IP4", - "VAR_DO_IP4", "VAR_DO_IP6", "VAR_DO_NAT64", "VAR_PREFER_IP6", - "VAR_DO_UDP", "VAR_DO_TCP", "VAR_TCP_MSS", "VAR_OUTGOING_TCP_MSS", - "VAR_TCP_IDLE_TIMEOUT", "VAR_EDNS_TCP_KEEPALIVE", - "VAR_EDNS_TCP_KEEPALIVE_TIMEOUT", "VAR_SOCK_QUEUE_TIMEOUT", "VAR_CHROOT", - "VAR_USERNAME", "VAR_DIRECTORY", "VAR_LOGFILE", "VAR_PIDFILE", - "VAR_MSG_CACHE_SIZE", "VAR_MSG_CACHE_SLABS", - "VAR_NUM_QUERIES_PER_THREAD", "VAR_RRSET_CACHE_SIZE", - "VAR_RRSET_CACHE_SLABS", "VAR_OUTGOING_NUM_TCP", "VAR_INFRA_HOST_TTL", - "VAR_INFRA_LAME_TTL", "VAR_INFRA_CACHE_SLABS", - "VAR_INFRA_CACHE_NUMHOSTS", "VAR_INFRA_CACHE_LAME_SIZE", "VAR_NAME", - "VAR_STUB_ZONE", "VAR_STUB_HOST", "VAR_STUB_ADDR", - "VAR_TARGET_FETCH_POLICY", "VAR_HARDEN_SHORT_BUFSIZE", - "VAR_HARDEN_LARGE_QUERIES", "VAR_FORWARD_ZONE", "VAR_FORWARD_HOST", - "VAR_FORWARD_ADDR", "VAR_DO_NOT_QUERY_ADDRESS", "VAR_HIDE_IDENTITY", - "VAR_HIDE_VERSION", "VAR_IDENTITY", "VAR_VERSION", "VAR_HARDEN_GLUE", - "VAR_MODULE_CONF", "VAR_TRUST_ANCHOR_FILE", "VAR_TRUST_ANCHOR", - "VAR_VAL_OVERRIDE_DATE", "VAR_BOGUS_TTL", "VAR_VAL_CLEAN_ADDITIONAL", - "VAR_VAL_PERMISSIVE_MODE", "VAR_INCOMING_NUM_TCP", "VAR_MSG_BUFFER_SIZE", - "VAR_KEY_CACHE_SIZE", "VAR_KEY_CACHE_SLABS", "VAR_TRUSTED_KEYS_FILE", - "VAR_VAL_NSEC3_KEYSIZE_ITERATIONS", "VAR_USE_SYSLOG", - "VAR_OUTGOING_INTERFACE", "VAR_ROOT_HINTS", "VAR_DO_NOT_QUERY_LOCALHOST", - "VAR_CACHE_MAX_TTL", "VAR_HARDEN_DNSSEC_STRIPPED", "VAR_ACCESS_CONTROL", - "VAR_LOCAL_ZONE", "VAR_LOCAL_DATA", "VAR_INTERFACE_AUTOMATIC", - "VAR_STATISTICS_INTERVAL", "VAR_DO_DAEMONIZE", "VAR_USE_CAPS_FOR_ID", - "VAR_STATISTICS_CUMULATIVE", "VAR_OUTGOING_PORT_PERMIT", - "VAR_OUTGOING_PORT_AVOID", "VAR_DLV_ANCHOR_FILE", "VAR_DLV_ANCHOR", - "VAR_NEG_CACHE_SIZE", "VAR_HARDEN_REFERRAL_PATH", "VAR_PRIVATE_ADDRESS", - "VAR_PRIVATE_DOMAIN", "VAR_REMOTE_CONTROL", "VAR_CONTROL_ENABLE", - "VAR_CONTROL_INTERFACE", "VAR_CONTROL_PORT", "VAR_SERVER_KEY_FILE", - "VAR_SERVER_CERT_FILE", "VAR_CONTROL_KEY_FILE", "VAR_CONTROL_CERT_FILE", - "VAR_CONTROL_USE_CERT", "VAR_TCP_REUSE_TIMEOUT", - "VAR_MAX_REUSE_TCP_QUERIES", "VAR_EXTENDED_STATISTICS", - "VAR_LOCAL_DATA_PTR", "VAR_JOSTLE_TIMEOUT", "VAR_STUB_PRIME", - "VAR_UNWANTED_REPLY_THRESHOLD", "VAR_LOG_TIME_ASCII", - "VAR_DOMAIN_INSECURE", "VAR_PYTHON", "VAR_PYTHON_SCRIPT", - "VAR_VAL_SIG_SKEW_MIN", "VAR_VAL_SIG_SKEW_MAX", "VAR_VAL_MAX_RESTART", - "VAR_CACHE_MIN_TTL", "VAR_VAL_LOG_LEVEL", "VAR_AUTO_TRUST_ANCHOR_FILE", - "VAR_KEEP_MISSING", "VAR_ADD_HOLDDOWN", "VAR_DEL_HOLDDOWN", - "VAR_SO_RCVBUF", "VAR_EDNS_BUFFER_SIZE", "VAR_PREFETCH", - "VAR_PREFETCH_KEY", "VAR_SO_SNDBUF", "VAR_SO_REUSEPORT", - "VAR_HARDEN_BELOW_NXDOMAIN", "VAR_IGNORE_CD_FLAG", "VAR_LOG_QUERIES", - "VAR_LOG_REPLIES", "VAR_LOG_LOCAL_ACTIONS", "VAR_TCP_UPSTREAM", - "VAR_SSL_UPSTREAM", "VAR_TCP_AUTH_QUERY_TIMEOUT", "VAR_SSL_SERVICE_KEY", - "VAR_SSL_SERVICE_PEM", "VAR_SSL_PORT", "VAR_FORWARD_FIRST", - "VAR_STUB_SSL_UPSTREAM", "VAR_FORWARD_SSL_UPSTREAM", - "VAR_TLS_CERT_BUNDLE", "VAR_STUB_TCP_UPSTREAM", - "VAR_FORWARD_TCP_UPSTREAM", "VAR_HTTPS_PORT", "VAR_HTTP_ENDPOINT", - "VAR_HTTP_MAX_STREAMS", "VAR_HTTP_QUERY_BUFFER_SIZE", - "VAR_HTTP_RESPONSE_BUFFER_SIZE", "VAR_HTTP_NODELAY", - "VAR_HTTP_NOTLS_DOWNSTREAM", "VAR_STUB_FIRST", "VAR_MINIMAL_RESPONSES", - "VAR_RRSET_ROUNDROBIN", "VAR_MAX_UDP_SIZE", "VAR_DELAY_CLOSE", - "VAR_UDP_CONNECT", "VAR_UNBLOCK_LAN_ZONES", "VAR_INSECURE_LAN_ZONES", - "VAR_INFRA_CACHE_MIN_RTT", "VAR_INFRA_CACHE_MAX_RTT", - "VAR_INFRA_KEEP_PROBING", "VAR_DNS64_PREFIX", "VAR_DNS64_SYNTHALL", - "VAR_DNS64_IGNORE_AAAA", "VAR_NAT64_PREFIX", "VAR_DNSTAP", - "VAR_DNSTAP_ENABLE", "VAR_DNSTAP_SOCKET_PATH", "VAR_DNSTAP_IP", - "VAR_DNSTAP_TLS", "VAR_DNSTAP_TLS_SERVER_NAME", - "VAR_DNSTAP_TLS_CERT_BUNDLE", "VAR_DNSTAP_TLS_CLIENT_KEY_FILE", - "VAR_DNSTAP_TLS_CLIENT_CERT_FILE", "VAR_DNSTAP_SEND_IDENTITY", - "VAR_DNSTAP_SEND_VERSION", "VAR_DNSTAP_BIDIRECTIONAL", - "VAR_DNSTAP_IDENTITY", "VAR_DNSTAP_VERSION", - "VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES", - "VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES", - "VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES", - "VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES", - "VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES", - "VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES", "VAR_RESPONSE_IP_TAG", - "VAR_RESPONSE_IP", "VAR_RESPONSE_IP_DATA", "VAR_HARDEN_ALGO_DOWNGRADE", - "VAR_IP_TRANSPARENT", "VAR_IP_DSCP", "VAR_DISABLE_DNSSEC_LAME_CHECK", - "VAR_IP_RATELIMIT", "VAR_IP_RATELIMIT_SLABS", "VAR_IP_RATELIMIT_SIZE", - "VAR_RATELIMIT", "VAR_RATELIMIT_SLABS", "VAR_RATELIMIT_SIZE", - "VAR_OUTBOUND_MSG_RETRY", "VAR_MAX_SENT_COUNT", "VAR_MAX_QUERY_RESTARTS", - "VAR_RATELIMIT_FOR_DOMAIN", "VAR_RATELIMIT_BELOW_DOMAIN", - "VAR_IP_RATELIMIT_FACTOR", "VAR_RATELIMIT_FACTOR", - "VAR_IP_RATELIMIT_BACKOFF", "VAR_RATELIMIT_BACKOFF", - "VAR_SEND_CLIENT_SUBNET", "VAR_CLIENT_SUBNET_ZONE", - "VAR_CLIENT_SUBNET_ALWAYS_FORWARD", "VAR_CLIENT_SUBNET_OPCODE", - "VAR_MAX_CLIENT_SUBNET_IPV4", "VAR_MAX_CLIENT_SUBNET_IPV6", - "VAR_MIN_CLIENT_SUBNET_IPV4", "VAR_MIN_CLIENT_SUBNET_IPV6", - "VAR_MAX_ECS_TREE_SIZE_IPV4", "VAR_MAX_ECS_TREE_SIZE_IPV6", - "VAR_CAPS_WHITELIST", "VAR_CACHE_MAX_NEGATIVE_TTL", - "VAR_PERMIT_SMALL_HOLDDOWN", "VAR_QNAME_MINIMISATION", - "VAR_QNAME_MINIMISATION_STRICT", "VAR_IP_FREEBIND", "VAR_DEFINE_TAG", - "VAR_LOCAL_ZONE_TAG", "VAR_ACCESS_CONTROL_TAG", - "VAR_LOCAL_ZONE_OVERRIDE", "VAR_ACCESS_CONTROL_TAG_ACTION", - "VAR_ACCESS_CONTROL_TAG_DATA", "VAR_VIEW", "VAR_ACCESS_CONTROL_VIEW", - "VAR_VIEW_FIRST", "VAR_SERVE_EXPIRED", "VAR_SERVE_EXPIRED_TTL", - "VAR_SERVE_EXPIRED_TTL_RESET", "VAR_SERVE_EXPIRED_REPLY_TTL", - "VAR_SERVE_EXPIRED_CLIENT_TIMEOUT", "VAR_EDE_SERVE_EXPIRED", - "VAR_SERVE_ORIGINAL_TTL", "VAR_FAKE_DSA", "VAR_FAKE_SHA1", - "VAR_LOG_IDENTITY", "VAR_HIDE_TRUSTANCHOR", "VAR_HIDE_HTTP_USER_AGENT", - "VAR_HTTP_USER_AGENT", "VAR_TRUST_ANCHOR_SIGNALING", - "VAR_AGGRESSIVE_NSEC", "VAR_USE_SYSTEMD", "VAR_SHM_ENABLE", - "VAR_SHM_KEY", "VAR_ROOT_KEY_SENTINEL", "VAR_DNSCRYPT", - "VAR_DNSCRYPT_ENABLE", "VAR_DNSCRYPT_PORT", "VAR_DNSCRYPT_PROVIDER", - "VAR_DNSCRYPT_SECRET_KEY", "VAR_DNSCRYPT_PROVIDER_CERT", - "VAR_DNSCRYPT_PROVIDER_CERT_ROTATED", - "VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE", - "VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS", - "VAR_DNSCRYPT_NONCE_CACHE_SIZE", "VAR_DNSCRYPT_NONCE_CACHE_SLABS", - "VAR_PAD_RESPONSES", "VAR_PAD_RESPONSES_BLOCK_SIZE", "VAR_PAD_QUERIES", - "VAR_PAD_QUERIES_BLOCK_SIZE", "VAR_IPSECMOD_ENABLED", - "VAR_IPSECMOD_HOOK", "VAR_IPSECMOD_IGNORE_BOGUS", "VAR_IPSECMOD_MAX_TTL", - "VAR_IPSECMOD_WHITELIST", "VAR_IPSECMOD_STRICT", "VAR_CACHEDB", - "VAR_CACHEDB_BACKEND", "VAR_CACHEDB_SECRETSEED", "VAR_CACHEDB_REDISHOST", - "VAR_CACHEDB_REDISPORT", "VAR_CACHEDB_REDISTIMEOUT", - "VAR_CACHEDB_REDISEXPIRERECORDS", "VAR_CACHEDB_REDISPATH", - "VAR_CACHEDB_REDISPASSWORD", "VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM", - "VAR_FOR_UPSTREAM", "VAR_AUTH_ZONE", "VAR_ZONEFILE", "VAR_MASTER", - "VAR_URL", "VAR_FOR_DOWNSTREAM", "VAR_FALLBACK_ENABLED", - "VAR_TLS_ADDITIONAL_PORT", "VAR_LOW_RTT", "VAR_LOW_RTT_PERMIL", - "VAR_FAST_SERVER_PERMIL", "VAR_FAST_SERVER_NUM", "VAR_ALLOW_NOTIFY", - "VAR_TLS_WIN_CERT", "VAR_TCP_CONNECTION_LIMIT", "VAR_ANSWER_COOKIE", - "VAR_COOKIE_SECRET", "VAR_IP_RATELIMIT_COOKIE", "VAR_FORWARD_NO_CACHE", - "VAR_STUB_NO_CACHE", "VAR_LOG_SERVFAIL", "VAR_DENY_ANY", - "VAR_UNKNOWN_SERVER_TIME_LIMIT", "VAR_LOG_TAG_QUERYREPLY", - "VAR_STREAM_WAIT_SIZE", "VAR_TLS_CIPHERS", "VAR_TLS_CIPHERSUITES", - "VAR_TLS_USE_SNI", "VAR_IPSET", "VAR_IPSET_NAME_V4", "VAR_IPSET_NAME_V6", - "VAR_TLS_SESSION_TICKET_KEYS", "VAR_RPZ", "VAR_TAGS", - "VAR_RPZ_ACTION_OVERRIDE", "VAR_RPZ_CNAME_OVERRIDE", "VAR_RPZ_LOG", - "VAR_RPZ_LOG_NAME", "VAR_DYNLIB", "VAR_DYNLIB_FILE", - "VAR_EDNS_CLIENT_STRING", "VAR_EDNS_CLIENT_STRING_OPCODE", "VAR_NSID", - "VAR_ZONEMD_PERMISSIVE_MODE", "VAR_ZONEMD_CHECK", - "VAR_ZONEMD_REJECT_ABSENCE", "VAR_RPZ_SIGNAL_NXDOMAIN_RA", - "VAR_INTERFACE_AUTOMATIC_PORTS", "VAR_EDE", "VAR_INTERFACE_ACTION", - "VAR_INTERFACE_VIEW", "VAR_INTERFACE_TAG", "VAR_INTERFACE_TAG_ACTION", - "VAR_INTERFACE_TAG_DATA", "VAR_PROXY_PROTOCOL_PORT", - "VAR_STATISTICS_INHIBIT_ZERO", "VAR_HARDEN_UNKNOWN_ADDITIONAL", - "$accept", "toplevelvars", "toplevelvar", "force_toplevel", - "serverstart", "contents_server", "content_server", "stubstart", - "contents_stub", "content_stub", "forwardstart", "contents_forward", - "content_forward", "viewstart", "contents_view", "content_view", - "authstart", "contents_auth", "content_auth", "rpz_tag", - "rpz_action_override", "rpz_cname_override", "rpz_log", "rpz_log_name", - "rpz_signal_nxdomain_ra", "rpzstart", "contents_rpz", "content_rpz", - "server_num_threads", "server_verbosity", "server_statistics_interval", - "server_statistics_cumulative", "server_extended_statistics", - "server_statistics_inhibit_zero", "server_shm_enable", "server_shm_key", - "server_port", "server_send_client_subnet", "server_client_subnet_zone", - "server_client_subnet_always_forward", "server_client_subnet_opcode", - "server_max_client_subnet_ipv4", "server_max_client_subnet_ipv6", - "server_min_client_subnet_ipv4", "server_min_client_subnet_ipv6", - "server_max_ecs_tree_size_ipv4", "server_max_ecs_tree_size_ipv6", - "server_interface", "server_outgoing_interface", "server_outgoing_range", - "server_outgoing_port_permit", "server_outgoing_port_avoid", - "server_outgoing_num_tcp", "server_incoming_num_tcp", - "server_interface_automatic", "server_interface_automatic_ports", - "server_do_ip4", "server_do_ip6", "server_do_nat64", "server_do_udp", - "server_do_tcp", "server_prefer_ip4", "server_prefer_ip6", - "server_tcp_mss", "server_outgoing_tcp_mss", "server_tcp_idle_timeout", - "server_max_reuse_tcp_queries", "server_tcp_reuse_timeout", - "server_tcp_auth_query_timeout", "server_tcp_keepalive", - "server_tcp_keepalive_timeout", "server_sock_queue_timeout", - "server_tcp_upstream", "server_udp_upstream_without_downstream", - "server_ssl_upstream", "server_ssl_service_key", - "server_ssl_service_pem", "server_ssl_port", "server_tls_cert_bundle", - "server_tls_win_cert", "server_tls_additional_port", - "server_tls_ciphers", "server_tls_ciphersuites", - "server_tls_session_ticket_keys", "server_tls_use_sni", - "server_https_port", "server_http_endpoint", "server_http_max_streams", - "server_http_query_buffer_size", "server_http_response_buffer_size", - "server_http_nodelay", "server_http_notls_downstream", - "server_use_systemd", "server_do_daemonize", "server_use_syslog", - "server_log_time_ascii", "server_log_queries", "server_log_replies", - "server_log_tag_queryreply", "server_log_servfail", - "server_log_local_actions", "server_chroot", "server_username", - "server_directory", "server_logfile", "server_pidfile", - "server_root_hints", "server_dlv_anchor_file", "server_dlv_anchor", - "server_auto_trust_anchor_file", "server_trust_anchor_file", - "server_trusted_keys_file", "server_trust_anchor", - "server_trust_anchor_signaling", "server_root_key_sentinel", - "server_domain_insecure", "server_hide_identity", "server_hide_version", - "server_hide_trustanchor", "server_hide_http_user_agent", - "server_identity", "server_version", "server_http_user_agent", - "server_nsid", "server_so_rcvbuf", "server_so_sndbuf", - "server_so_reuseport", "server_ip_transparent", "server_ip_freebind", - "server_ip_dscp", "server_stream_wait_size", "server_edns_buffer_size", - "server_msg_buffer_size", "server_msg_cache_size", - "server_msg_cache_slabs", "server_num_queries_per_thread", - "server_jostle_timeout", "server_delay_close", "server_udp_connect", - "server_unblock_lan_zones", "server_insecure_lan_zones", - "server_rrset_cache_size", "server_rrset_cache_slabs", - "server_infra_host_ttl", "server_infra_lame_ttl", - "server_infra_cache_numhosts", "server_infra_cache_lame_size", - "server_infra_cache_slabs", "server_infra_cache_min_rtt", - "server_infra_cache_max_rtt", "server_infra_keep_probing", - "server_target_fetch_policy", "server_harden_short_bufsize", - "server_harden_large_queries", "server_harden_glue", - "server_harden_dnssec_stripped", "server_harden_below_nxdomain", - "server_harden_referral_path", "server_harden_algo_downgrade", - "server_harden_unknown_additional", "server_use_caps_for_id", - "server_caps_whitelist", "server_private_address", - "server_private_domain", "server_prefetch", "server_prefetch_key", - "server_deny_any", "server_unwanted_reply_threshold", - "server_do_not_query_address", "server_do_not_query_localhost", - "server_access_control", "server_interface_action", "server_module_conf", - "server_val_override_date", "server_val_sig_skew_min", - "server_val_sig_skew_max", "server_val_max_restart", - "server_cache_max_ttl", "server_cache_max_negative_ttl", - "server_cache_min_ttl", "server_bogus_ttl", - "server_val_clean_additional", "server_val_permissive_mode", - "server_aggressive_nsec", "server_ignore_cd_flag", - "server_serve_expired", "server_serve_expired_ttl", - "server_serve_expired_ttl_reset", "server_serve_expired_reply_ttl", - "server_serve_expired_client_timeout", "server_ede_serve_expired", - "server_serve_original_ttl", "server_fake_dsa", "server_fake_sha1", - "server_val_log_level", "server_val_nsec3_keysize_iterations", - "server_zonemd_permissive_mode", "server_add_holddown", - "server_del_holddown", "server_keep_missing", - "server_permit_small_holddown", "server_key_cache_size", - "server_key_cache_slabs", "server_neg_cache_size", "server_local_zone", - "server_local_data", "server_local_data_ptr", "server_minimal_responses", - "server_rrset_roundrobin", "server_unknown_server_time_limit", - "server_max_udp_size", "server_dns64_prefix", "server_dns64_synthall", - "server_dns64_ignore_aaaa", "server_nat64_prefix", "server_define_tag", - "server_local_zone_tag", "server_access_control_tag", - "server_access_control_tag_action", "server_access_control_tag_data", - "server_local_zone_override", "server_access_control_view", - "server_interface_tag", "server_interface_tag_action", - "server_interface_tag_data", "server_interface_view", - "server_response_ip_tag", "server_ip_ratelimit", - "server_ip_ratelimit_cookie", "server_ratelimit", - "server_ip_ratelimit_size", "server_ratelimit_size", - "server_ip_ratelimit_slabs", "server_ratelimit_slabs", - "server_ratelimit_for_domain", "server_ratelimit_below_domain", - "server_ip_ratelimit_factor", "server_ratelimit_factor", - "server_ip_ratelimit_backoff", "server_ratelimit_backoff", - "server_outbound_msg_retry", "server_max_sent_count", - "server_max_query_restarts", "server_low_rtt", "server_fast_server_num", - "server_fast_server_permil", "server_qname_minimisation", - "server_qname_minimisation_strict", "server_pad_responses", - "server_pad_responses_block_size", "server_pad_queries", - "server_pad_queries_block_size", "server_ipsecmod_enabled", - "server_ipsecmod_ignore_bogus", "server_ipsecmod_hook", - "server_ipsecmod_max_ttl", "server_ipsecmod_whitelist", - "server_ipsecmod_strict", "server_edns_client_string", - "server_edns_client_string_opcode", "server_ede", - "server_proxy_protocol_port", "stub_name", "stub_host", "stub_addr", - "stub_first", "stub_no_cache", "stub_ssl_upstream", "stub_tcp_upstream", - "stub_prime", "forward_name", "forward_host", "forward_addr", - "forward_first", "forward_no_cache", "forward_ssl_upstream", - "forward_tcp_upstream", "auth_name", "auth_zonefile", "auth_master", - "auth_url", "auth_allow_notify", "auth_zonemd_check", - "auth_zonemd_reject_absence", "auth_for_downstream", "auth_for_upstream", - "auth_fallback_enabled", "view_name", "view_local_zone", - "view_response_ip", "view_response_ip_data", "view_local_data", - "view_local_data_ptr", "view_first", "rcstart", "contents_rc", - "content_rc", "rc_control_enable", "rc_control_port", - "rc_control_interface", "rc_control_use_cert", "rc_server_key_file", - "rc_server_cert_file", "rc_control_key_file", "rc_control_cert_file", - "dtstart", "contents_dt", "content_dt", "dt_dnstap_enable", - "dt_dnstap_bidirectional", "dt_dnstap_socket_path", "dt_dnstap_ip", - "dt_dnstap_tls", "dt_dnstap_tls_server_name", - "dt_dnstap_tls_cert_bundle", "dt_dnstap_tls_client_key_file", - "dt_dnstap_tls_client_cert_file", "dt_dnstap_send_identity", - "dt_dnstap_send_version", "dt_dnstap_identity", "dt_dnstap_version", - "dt_dnstap_log_resolver_query_messages", - "dt_dnstap_log_resolver_response_messages", - "dt_dnstap_log_client_query_messages", - "dt_dnstap_log_client_response_messages", - "dt_dnstap_log_forwarder_query_messages", - "dt_dnstap_log_forwarder_response_messages", "pythonstart", - "contents_py", "content_py", "py_script", "dynlibstart", "contents_dl", - "content_dl", "dl_file", "server_disable_dnssec_lame_check", - "server_log_identity", "server_response_ip", "server_response_ip_data", - "dnscstart", "contents_dnsc", "content_dnsc", "dnsc_dnscrypt_enable", - "dnsc_dnscrypt_port", "dnsc_dnscrypt_provider", - "dnsc_dnscrypt_provider_cert", "dnsc_dnscrypt_provider_cert_rotated", - "dnsc_dnscrypt_secret_key", "dnsc_dnscrypt_shared_secret_cache_size", - "dnsc_dnscrypt_shared_secret_cache_slabs", - "dnsc_dnscrypt_nonce_cache_size", "dnsc_dnscrypt_nonce_cache_slabs", - "cachedbstart", "contents_cachedb", "content_cachedb", - "cachedb_backend_name", "cachedb_secret_seed", "redis_server_host", - "redis_server_port", "redis_server_path", "redis_server_password", - "redis_timeout", "redis_expire_records", "server_tcp_connection_limit", - "server_answer_cookie", "server_cookie_secret", "ipsetstart", - "contents_ipset", "content_ipset", "ipset_name_v4", "ipset_name_v6", YY_NULLPTR -}; - -static const char * -yysymbol_name (yysymbol_kind_t yysymbol) -{ - return yytname[yysymbol]; -} -#endif - -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, - 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, - 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, - 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, - 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, - 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, - 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, - 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, - 595, 596, 597, 598, 599, 600 -}; -#endif - -#define YYPACT_NINF (-292) - -#define yypact_value_is_default(Yyn) \ - ((Yyn) == YYPACT_NINF) - -#define YYTABLE_NINF (-1) - -#define yytable_value_is_error(Yyn) \ - 0 - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - -292, 266, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -13, 198, 226, 229, 56, 43, 302, -14, - -81, -291, 132, 129, -284, 31, 32, 33, 75, 76, - 77, 78, 79, 81, 82, 83, 89, 94, 121, 122, - 123, 125, 126, 134, 168, 213, 215, 236, 239, 240, - 241, 242, 243, 244, 245, 257, 258, 259, 260, 261, - 262, 264, 269, 270, 275, 278, 284, 285, 294, 295, - 296, 298, 299, 301, 305, 311, 312, 323, 328, 330, - 331, 332, 342, 343, 344, 346, 348, 349, 350, 351, - 352, 353, 361, 363, 364, 366, 367, 369, 370, 371, - 373, 374, 375, 376, 377, 378, 407, 408, 409, 410, - 411, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 426, 427, 429, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 493, 494, 495, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 515, 516, 517, - 518, 519, 520, 521, 522, 524, 525, 526, 527, 528, - 529, 530, 531, 532, 533, 534, 536, 537, 538, 539, - 540, 541, 542, 543, 544, 545, 547, 548, 549, 550, - 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, - 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, - 571, 572, 574, 575, 576, 578, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, 579, 580, - 581, 582, 584, 585, 586, 587, -292, -292, -292, -292, - -292, -292, -292, -292, -292, 588, 589, 590, 591, 592, - 593, 594, -292, -292, -292, -292, -292, -292, -292, -292, - 595, 596, 597, 598, 599, 600, 601, -292, -292, -292, - -292, -292, -292, -292, -292, 602, 603, 604, 605, 606, - 607, 608, 609, 610, 611, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, 612, 613, 614, 615, - 616, 617, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, 618, 619, 620, 621, 622, - 623, 624, 625, -292, -292, -292, -292, -292, -292, -292, - -292, -292, 626, 627, 628, 629, 630, 631, 632, 633, - 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, - 644, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, 645, -292, -292, 646, -292, -292, 647, 648, 649, - 650, 651, 652, 653, 654, 655, 656, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, 657, 658, - 659, 660, 661, 662, 663, 664, -292, -292, -292, -292, - -292, -292, -292, -292, -292, 665, 666, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, 667, 668, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, 669, 670, 671, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - 672, 673, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, 674, 675, 676, 677, 678, 679, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, 680, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, 681, -292, -292, - -292, -292, -292, 682, 683, 684, 685, 686, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, 687, -292, -292, - 688, 689, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, 690, 691, 692, - -292, -292, -292, -292, -292, -292, 693, 694, -292, -292, - -292, -292, -292, -292, -292, -292 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_int16 yydefact[] = -{ - 2, 0, 1, 18, 19, 263, 274, 594, 654, 613, - 284, 668, 691, 294, 713, 313, 659, 3, 17, 21, - 265, 276, 286, 296, 315, 596, 615, 656, 661, 670, - 693, 715, 4, 5, 6, 10, 14, 15, 8, 9, - 7, 16, 11, 12, 13, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 20, 22, 23, 90, - 93, 102, 261, 218, 219, 24, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 39, 81, 25, 94, - 95, 50, 74, 89, 258, 26, 27, 28, 31, 32, - 29, 30, 33, 34, 35, 255, 256, 257, 36, 37, - 38, 126, 230, 127, 129, 130, 131, 232, 237, 233, - 244, 245, 246, 250, 132, 133, 134, 135, 136, 137, - 138, 214, 91, 80, 106, 124, 125, 242, 239, 128, - 40, 41, 42, 43, 44, 82, 96, 97, 113, 68, - 78, 69, 222, 223, 107, 60, 61, 221, 64, 62, - 63, 65, 253, 117, 121, 142, 154, 186, 157, 243, - 118, 75, 45, 46, 47, 104, 143, 144, 145, 146, - 48, 49, 51, 52, 54, 55, 53, 151, 152, 158, - 56, 57, 58, 66, 85, 122, 99, 153, 262, 92, - 182, 100, 101, 119, 120, 240, 105, 59, 83, 86, - 195, 67, 70, 108, 109, 110, 84, 183, 111, 71, - 72, 73, 231, 123, 205, 206, 207, 208, 209, 210, - 211, 212, 220, 112, 79, 254, 114, 115, 116, 184, - 76, 77, 98, 87, 88, 103, 139, 140, 241, 141, - 147, 148, 149, 150, 187, 188, 190, 192, 193, 191, - 194, 197, 198, 199, 196, 215, 155, 249, 156, 161, - 162, 159, 160, 163, 164, 166, 165, 168, 167, 169, - 170, 171, 234, 236, 235, 185, 200, 201, 202, 203, - 204, 224, 226, 225, 227, 228, 229, 251, 252, 259, - 260, 189, 213, 216, 217, 238, 247, 248, 0, 0, - 0, 0, 0, 0, 0, 0, 264, 266, 267, 268, - 270, 271, 272, 273, 269, 0, 0, 0, 0, 0, - 0, 0, 275, 277, 278, 279, 280, 281, 282, 283, - 0, 0, 0, 0, 0, 0, 0, 285, 287, 288, - 291, 292, 289, 293, 290, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 295, 297, 298, 299, 300, - 304, 305, 306, 301, 302, 303, 0, 0, 0, 0, - 0, 0, 318, 322, 323, 324, 325, 326, 314, 316, - 317, 319, 320, 321, 327, 0, 0, 0, 0, 0, - 0, 0, 0, 595, 597, 599, 598, 604, 600, 601, - 602, 603, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 614, 616, 618, 617, 619, 620, 621, 622, 623, - 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, - 634, 0, 655, 657, 0, 660, 662, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 669, 671, 672, - 673, 675, 676, 674, 677, 678, 679, 680, 0, 0, - 0, 0, 0, 0, 0, 0, 692, 694, 695, 696, - 697, 700, 701, 698, 699, 0, 0, 714, 716, 717, - 329, 328, 336, 349, 347, 361, 356, 357, 358, 362, - 359, 360, 363, 364, 365, 369, 370, 371, 401, 402, - 403, 404, 405, 433, 434, 435, 441, 442, 352, 443, - 444, 447, 445, 446, 451, 452, 453, 468, 416, 417, - 420, 421, 454, 472, 410, 412, 473, 480, 481, 482, - 353, 432, 501, 502, 411, 495, 394, 348, 406, 469, - 477, 455, 0, 0, 505, 354, 330, 393, 460, 331, - 350, 351, 407, 408, 503, 457, 462, 463, 367, 366, - 332, 506, 436, 467, 395, 415, 474, 475, 476, 479, - 494, 409, 499, 497, 498, 424, 431, 464, 465, 425, - 426, 456, 484, 396, 397, 400, 372, 374, 368, 375, - 376, 377, 378, 385, 386, 387, 388, 389, 390, 391, - 507, 508, 510, 437, 438, 439, 440, 448, 449, 450, - 511, 512, 513, 514, 0, 0, 0, 458, 427, 429, - 664, 527, 532, 530, 529, 533, 531, 540, 541, 542, - 0, 0, 536, 537, 538, 539, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 461, 478, 500, 546, - 547, 428, 515, 0, 0, 0, 0, 0, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 665, 418, - 419, 422, 413, 483, 392, 334, 335, 414, 548, 549, - 550, 551, 552, 554, 553, 555, 556, 557, 373, 380, - 543, 545, 544, 379, 0, 711, 712, 528, 399, 466, - 509, 398, 430, 381, 382, 384, 383, 0, 559, 423, - 496, 355, 560, 0, 0, 0, 0, 0, 561, 333, - 459, 562, 563, 564, 569, 567, 568, 565, 566, 570, - 571, 572, 573, 575, 576, 574, 587, 0, 591, 592, - 0, 0, 593, 577, 585, 578, 579, 580, 584, 586, - 581, 582, 583, 307, 308, 309, 310, 311, 312, 605, - 607, 606, 609, 610, 611, 612, 608, 635, 637, 638, - 639, 640, 641, 642, 643, 644, 645, 636, 646, 647, - 648, 649, 650, 651, 652, 653, 658, 663, 681, 682, - 683, 686, 684, 685, 687, 688, 689, 690, 702, 703, - 704, 705, 708, 709, 706, 707, 718, 719, 470, 504, - 526, 666, 667, 534, 535, 516, 517, 0, 0, 0, - 521, 710, 558, 471, 525, 522, 0, 0, 588, 589, - 590, 520, 518, 519, 523, 524 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, 695, 696, 697, - 698, 699, -292, -292, 700, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292, -292, -292, -292, -292, -292, -292, -292, -292, -292, - -292 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - 0, 1, 17, 18, 19, 32, 286, 20, 33, 536, - 21, 34, 552, 22, 35, 567, 23, 36, 585, 602, - 603, 604, 605, 606, 607, 24, 37, 608, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, - 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, - 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, - 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, - 519, 520, 537, 538, 539, 540, 541, 542, 543, 544, - 553, 554, 555, 556, 557, 558, 559, 586, 587, 588, - 589, 590, 591, 592, 593, 594, 595, 568, 569, 570, - 571, 572, 573, 574, 25, 38, 623, 624, 625, 626, - 627, 628, 629, 630, 631, 26, 39, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 670, 27, 40, 672, - 673, 28, 41, 675, 676, 521, 522, 523, 524, 29, - 42, 687, 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 30, 43, 706, 707, 708, 709, 710, 711, - 712, 713, 714, 525, 526, 527, 31, 44, 717, 718, - 719 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 715, 716, 671, 674, 79, 80, - 81, 720, 721, 722, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 723, 724, 725, 726, 727, - 575, 728, 729, 730, 123, 124, 125, 126, 127, 731, - 128, 129, 130, 575, 732, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 733, 734, 735, 157, 736, 737, 158, 159, 160, - 161, 162, 163, 164, 738, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 632, - 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, - 643, 644, 645, 646, 647, 648, 649, 650, 739, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 740, 223, 741, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 528, 742, 529, 530, 743, - 744, 745, 746, 747, 748, 749, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 2, 750, 751, 752, - 753, 754, 755, 545, 756, 253, 560, 3, 4, 757, - 758, 546, 547, 254, 255, 759, 256, 257, 760, 258, - 259, 260, 261, 262, 761, 762, 263, 264, 265, 266, - 267, 268, 269, 270, 763, 764, 765, 271, 766, 767, - 531, 768, 561, 562, 5, 769, 272, 273, 274, 275, - 6, 770, 771, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 772, 577, 578, 579, 580, 773, 563, - 774, 775, 776, 532, 582, 576, 533, 577, 578, 579, - 580, 581, 777, 778, 779, 534, 780, 582, 781, 782, - 783, 784, 785, 786, 7, 596, 597, 598, 599, 600, - 548, 787, 549, 788, 789, 550, 790, 791, 601, 792, - 793, 794, 8, 795, 796, 797, 798, 799, 800, 583, - 584, 677, 678, 679, 680, 681, 682, 683, 684, 685, - 686, 615, 616, 617, 618, 619, 620, 621, 622, 698, - 699, 700, 701, 702, 703, 704, 705, 801, 802, 803, - 804, 805, 564, 565, 806, 807, 808, 809, 810, 811, - 812, 813, 814, 815, 816, 817, 818, 819, 9, 820, - 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, - 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, - 841, 842, 843, 844, 845, 846, 847, 566, 848, 849, - 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, - 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, - 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, - 880, 881, 10, 882, 883, 884, 535, 885, 886, 887, - 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, - 898, 899, 900, 901, 11, 902, 903, 904, 905, 906, - 907, 908, 909, 551, 910, 911, 912, 913, 914, 915, - 916, 917, 918, 919, 920, 12, 921, 922, 923, 924, - 925, 926, 927, 928, 929, 930, 13, 931, 932, 933, - 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, - 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, - 954, 955, 956, 14, 957, 958, 959, 15, 960, 961, - 962, 963, 964, 16, 965, 966, 967, 968, 969, 970, - 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, - 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, - 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, - 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, - 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, - 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, - 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, - 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, - 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, - 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, - 1071, 1072, 1073, 1074, 1075, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 609, 610, 611, 612, 613, 614 -}; - -static const yytype_int16 yycheck[] = -{ - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 318, 319, 117, 328, 51, 52, - 53, 10, 10, 10, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 10, 10, 10, 10, 10, - 47, 10, 10, 10, 107, 108, 109, 110, 111, 10, - 113, 114, 115, 47, 10, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 10, 10, 10, 147, 10, 10, 150, 151, 152, - 153, 154, 155, 156, 10, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 10, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 10, 237, 10, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 47, 10, 49, 50, 10, - 10, 10, 10, 10, 10, 10, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 0, 10, 10, 10, - 10, 10, 10, 47, 10, 288, 47, 11, 12, 10, - 10, 55, 56, 296, 297, 10, 299, 300, 10, 302, - 303, 304, 305, 306, 10, 10, 309, 310, 311, 312, - 313, 314, 315, 316, 10, 10, 10, 320, 10, 10, - 112, 10, 83, 84, 48, 10, 329, 330, 331, 332, - 54, 10, 10, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 10, 291, 292, 293, 294, 10, 110, - 10, 10, 10, 145, 301, 289, 148, 291, 292, 293, - 294, 295, 10, 10, 10, 157, 10, 301, 10, 10, - 10, 10, 10, 10, 98, 322, 323, 324, 325, 326, - 144, 10, 146, 10, 10, 149, 10, 10, 335, 10, - 10, 10, 116, 10, 10, 10, 10, 10, 10, 333, - 334, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 99, 100, 101, 102, 103, 104, 105, 106, 280, - 281, 282, 283, 284, 285, 286, 287, 10, 10, 10, - 10, 10, 193, 194, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 172, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 238, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 236, 10, 10, 10, 308, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 258, 10, 10, 10, 10, 10, - 10, 10, 10, 307, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 279, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 290, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 317, 10, 10, 10, 321, 10, 10, - 10, 10, 10, 327, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 37, 37, 37, 37, 37, 37 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_int16 yystos[] = -{ - 0, 347, 0, 11, 12, 48, 54, 98, 116, 172, - 236, 258, 279, 290, 317, 321, 327, 348, 349, 350, - 353, 356, 359, 362, 371, 640, 651, 673, 677, 685, - 698, 712, 351, 354, 357, 360, 363, 372, 641, 652, - 674, 678, 686, 699, 713, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 51, - 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 107, 108, 109, 110, 111, 113, 114, - 115, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 147, 150, 151, - 152, 153, 154, 155, 156, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 237, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 288, 296, 297, 299, 300, 302, 303, - 304, 305, 306, 309, 310, 311, 312, 313, 314, 315, - 316, 320, 329, 330, 331, 332, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 352, 374, 375, 376, - 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, - 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, - 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, - 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, - 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, - 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, - 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, - 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, - 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, - 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, - 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, - 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, - 607, 681, 682, 683, 684, 709, 710, 711, 47, 49, - 50, 112, 145, 148, 157, 308, 355, 608, 609, 610, - 611, 612, 613, 614, 615, 47, 55, 56, 144, 146, - 149, 307, 358, 616, 617, 618, 619, 620, 621, 622, - 47, 83, 84, 110, 193, 194, 238, 361, 633, 634, - 635, 636, 637, 638, 639, 47, 289, 291, 292, 293, - 294, 295, 301, 333, 334, 364, 623, 624, 625, 626, - 627, 628, 629, 630, 631, 632, 322, 323, 324, 325, - 326, 335, 365, 366, 367, 368, 369, 370, 373, 623, - 624, 625, 626, 627, 630, 99, 100, 101, 102, 103, - 104, 105, 106, 642, 643, 644, 645, 646, 647, 648, - 649, 650, 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 653, 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, - 672, 117, 675, 676, 328, 679, 680, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 687, 688, 689, - 690, 691, 692, 693, 694, 695, 696, 697, 280, 281, - 282, 283, 284, 285, 286, 287, 700, 701, 702, 703, - 704, 705, 706, 707, 708, 318, 319, 714, 715, 716, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_int16 yyr1[] = -{ - 0, 346, 347, 347, 348, 348, 348, 348, 348, 348, - 348, 348, 348, 348, 348, 348, 348, 348, 349, 350, - 351, 351, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 352, 352, 352, 352, 352, 352, 352, - 352, 352, 352, 353, 354, 354, 355, 355, 355, 355, - 355, 355, 355, 355, 356, 357, 357, 358, 358, 358, - 358, 358, 358, 358, 359, 360, 360, 361, 361, 361, - 361, 361, 361, 361, 362, 363, 363, 364, 364, 364, - 364, 364, 364, 364, 364, 364, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 372, 373, 373, 373, 373, - 373, 373, 373, 373, 373, 373, 373, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, - 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, - 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, - 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, - 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, - 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, - 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, - 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, - 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, - 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, - 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, - 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, - 636, 637, 638, 639, 640, 641, 641, 642, 642, 642, - 642, 642, 642, 642, 642, 643, 644, 645, 646, 647, - 648, 649, 650, 651, 652, 652, 653, 653, 653, 653, - 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, - 653, 653, 653, 653, 653, 654, 655, 656, 657, 658, - 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, - 669, 670, 671, 672, 673, 674, 674, 675, 676, 677, - 678, 678, 679, 680, 681, 682, 683, 684, 685, 686, - 686, 687, 687, 687, 687, 687, 687, 687, 687, 687, - 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, - 697, 698, 699, 699, 700, 700, 700, 700, 700, 700, - 700, 700, 701, 702, 703, 704, 705, 706, 707, 708, - 709, 710, 711, 712, 713, 713, 714, 714, 715, 716 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_int8 yyr2[] = -{ - 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 1, 2, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, - 4, 3, 3, 4, 4, 3, 3, 2, 2, 2, - 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, - 3, 2, 2, 2, 1, 2, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 2, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 1, 2, 0, 1, 2, 1, - 2, 0, 1, 2, 2, 2, 3, 3, 1, 2, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 1, 2, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 2, 2, 1, 2, 0, 1, 1, 2, 2 -}; - - -enum { YYENOMEM = -2 }; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Backward compatibility with an undocumented macro. - Use YYerror or YYUNDEF. */ -#define YYERRCODE YYUNDEF - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif - - -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Kind, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) -{ - FILE *yyoutput = yyo; - YY_USE (yyoutput); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) -{ - YYFPRINTF (yyo, "%s %s (", - yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - - yy_symbol_value_print (yyo, yykind, yyvaluep); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, - int yyrule) -{ - int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)]); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) ((void) 0) -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - - - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep) -{ - YY_USE (yyvaluep); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/* Lookahead token kind. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; -/* Number of syntax errors so far. */ -int yynerrs; - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (void) -{ - yy_state_fast_t yystate = 0; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus = 0; - - /* Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* Their size. */ - YYPTRDIFF_T yystacksize = YYINITDEPTH; - - /* The state stack: array, bottom, top. */ - yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss = yyssa; - yy_state_t *yyssp = yyss; - - /* The semantic value stack: array, bottom, top. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp = yyvs; - - int yyn; - /* The return value of yyparse. */ - int yyresult; - /* Lookahead symbol kind. */ - yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - - - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yysetstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - YY_IGNORE_USELESS_CAST_BEGIN - *yyssp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - YY_STACK_PRINT (yyss, yyssp); - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYPTRDIFF_T yysize = yyssp - yyss + 1; - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - yy_state_t *yyss1 = yyss; - YYSTYPE *yyvs1 = yyvs; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * YYSIZEOF (*yyssp), - &yyvs1, yysize * YYSIZEOF (*yyvsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yy_state_t *yyss1 = yyss; - union yyalloc *yyptr = - YY_CAST (union yyalloc *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YY_IGNORE_USELESS_CAST_BEGIN - YYDPRINTF ((stderr, "Stack size increased to %ld\n", - YY_CAST (long, yystacksize))); - YY_IGNORE_USELESS_CAST_END - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token\n")); - yychar = yylex (); - } - - if (yychar <= YYEOF) - { - yychar = YYEOF; - yytoken = YYSYMBOL_YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else if (yychar == YYerror) - { - /* The scanner already issued an error message, process directly - to error recovery. But do not keep the error token as - lookahead, it is too special and may lead us to an endless - loop in error recovery. */ - yychar = YYUNDEF; - yytoken = YYSYMBOL_YYerror; - goto yyerrlab1; - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - /* Discard the shifted token. */ - yychar = YYEMPTY; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 18: /* force_toplevel: VAR_FORCE_TOPLEVEL */ -#line 214 "util/configparser.y" - { - OUTYY(("\nP(force-toplevel)\n")); - cfg_parser->started_toplevel = 0; - } -#line 2903 "util/configparser.c" - break; - - case 19: /* serverstart: VAR_SERVER */ -#line 221 "util/configparser.y" - { - OUTYY(("\nP(server:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 2912 "util/configparser.c" - break; - - case 263: /* stubstart: VAR_STUB_ZONE */ -#line 338 "util/configparser.y" - { - struct config_stub* s; - OUTYY(("\nP(stub_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); - if(s) { - s->next = cfg_parser->cfg->stubs; - cfg_parser->cfg->stubs = s; - } else { - yyerror("out of memory"); - } - } -#line 2929 "util/configparser.c" - break; - - case 274: /* forwardstart: VAR_FORWARD_ZONE */ -#line 357 "util/configparser.y" - { - struct config_stub* s; - OUTYY(("\nP(forward_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); - if(s) { - s->next = cfg_parser->cfg->forwards; - cfg_parser->cfg->forwards = s; - } else { - yyerror("out of memory"); - } - } -#line 2946 "util/configparser.c" - break; - - case 284: /* viewstart: VAR_VIEW */ -#line 376 "util/configparser.y" - { - struct config_view* s; - OUTYY(("\nP(view:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_view*)calloc(1, sizeof(struct config_view)); - if(s) { - s->next = cfg_parser->cfg->views; - if(s->next && !s->next->name) - yyerror("view without name"); - cfg_parser->cfg->views = s; - } else { - yyerror("out of memory"); - } - } -#line 2965 "util/configparser.c" - break; - - case 294: /* authstart: VAR_AUTH_ZONE */ -#line 397 "util/configparser.y" - { - struct config_auth* s; - OUTYY(("\nP(auth_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_auth*)calloc(1, sizeof(struct config_auth)); - if(s) { - s->next = cfg_parser->cfg->auths; - cfg_parser->cfg->auths = s; - /* defaults for auth zone */ - s->for_downstream = 1; - s->for_upstream = 1; - s->fallback_enabled = 0; - s->zonemd_check = 0; - s->zonemd_reject_absence = 0; - s->isrpz = 0; - } else { - yyerror("out of memory"); - } - } -#line 2989 "util/configparser.c" - break; - - case 307: /* rpz_tag: VAR_TAGS STRING_ARG */ -#line 425 "util/configparser.y" - { - uint8_t* bitlist; - size_t len = 0; - OUTYY(("P(server_local_zone_tag:%s)\n", (yyvsp[0].str))); - bitlist = config_parse_taglist(cfg_parser->cfg, (yyvsp[0].str), - &len); - free((yyvsp[0].str)); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - } - if(bitlist) { - cfg_parser->cfg->auths->rpz_taglist = bitlist; - cfg_parser->cfg->auths->rpz_taglistlen = len; - - } - } -#line 3010 "util/configparser.c" - break; - - case 308: /* rpz_action_override: VAR_RPZ_ACTION_OVERRIDE STRING_ARG */ -#line 444 "util/configparser.y" - { - OUTYY(("P(rpz_action_override:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "nxdomain")!=0 && strcmp((yyvsp[0].str), "nodata")!=0 && - strcmp((yyvsp[0].str), "passthru")!=0 && strcmp((yyvsp[0].str), "drop")!=0 && - strcmp((yyvsp[0].str), "cname")!=0 && strcmp((yyvsp[0].str), "disabled")!=0) { - yyerror("rpz-action-override action: expected nxdomain, " - "nodata, passthru, drop, cname or disabled"); - free((yyvsp[0].str)); - cfg_parser->cfg->auths->rpz_action_override = NULL; - } - else { - cfg_parser->cfg->auths->rpz_action_override = (yyvsp[0].str); - } - } -#line 3029 "util/configparser.c" - break; - - case 309: /* rpz_cname_override: VAR_RPZ_CNAME_OVERRIDE STRING_ARG */ -#line 461 "util/configparser.y" - { - OUTYY(("P(rpz_cname_override:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->auths->rpz_cname); - cfg_parser->cfg->auths->rpz_cname = (yyvsp[0].str); - } -#line 3039 "util/configparser.c" - break; - - case 310: /* rpz_log: VAR_RPZ_LOG STRING_ARG */ -#line 469 "util/configparser.y" - { - OUTYY(("P(rpz_log:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->rpz_log = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3051 "util/configparser.c" - break; - - case 311: /* rpz_log_name: VAR_RPZ_LOG_NAME STRING_ARG */ -#line 479 "util/configparser.y" - { - OUTYY(("P(rpz_log_name:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->auths->rpz_log_name); - cfg_parser->cfg->auths->rpz_log_name = (yyvsp[0].str); - } -#line 3061 "util/configparser.c" - break; - - case 312: /* rpz_signal_nxdomain_ra: VAR_RPZ_SIGNAL_NXDOMAIN_RA STRING_ARG */ -#line 486 "util/configparser.y" - { - OUTYY(("P(rpz_signal_nxdomain_ra:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->rpz_signal_nxdomain_ra = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3073 "util/configparser.c" - break; - - case 313: /* rpzstart: VAR_RPZ */ -#line 496 "util/configparser.y" - { - struct config_auth* s; - OUTYY(("\nP(rpz:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_auth*)calloc(1, sizeof(struct config_auth)); - if(s) { - s->next = cfg_parser->cfg->auths; - cfg_parser->cfg->auths = s; - /* defaults for RPZ auth zone */ - s->for_downstream = 0; - s->for_upstream = 0; - s->fallback_enabled = 0; - s->isrpz = 1; - } else { - yyerror("out of memory"); - } - } -#line 3095 "util/configparser.c" - break; - - case 328: /* server_num_threads: VAR_NUM_THREADS STRING_ARG */ -#line 521 "util/configparser.y" - { - OUTYY(("P(server_num_threads:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->num_threads = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3107 "util/configparser.c" - break; - - case 329: /* server_verbosity: VAR_VERBOSITY STRING_ARG */ -#line 530 "util/configparser.y" - { - OUTYY(("P(server_verbosity:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->verbosity = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3119 "util/configparser.c" - break; - - case 330: /* server_statistics_interval: VAR_STATISTICS_INTERVAL STRING_ARG */ -#line 539 "util/configparser.y" - { - OUTYY(("P(server_statistics_interval:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "") == 0 || strcmp((yyvsp[0].str), "0") == 0) - cfg_parser->cfg->stat_interval = 0; - else if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->stat_interval = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3133 "util/configparser.c" - break; - - case 331: /* server_statistics_cumulative: VAR_STATISTICS_CUMULATIVE STRING_ARG */ -#line 550 "util/configparser.y" - { - OUTYY(("P(server_statistics_cumulative:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_cumulative = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3145 "util/configparser.c" - break; - - case 332: /* server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG */ -#line 559 "util/configparser.y" - { - OUTYY(("P(server_extended_statistics:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_extended = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3157 "util/configparser.c" - break; - - case 333: /* server_statistics_inhibit_zero: VAR_STATISTICS_INHIBIT_ZERO STRING_ARG */ -#line 568 "util/configparser.y" - { - OUTYY(("P(server_statistics_inhibit_zero:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_inhibit_zero = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3169 "util/configparser.c" - break; - - case 334: /* server_shm_enable: VAR_SHM_ENABLE STRING_ARG */ -#line 577 "util/configparser.y" - { - OUTYY(("P(server_shm_enable:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->shm_enable = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3181 "util/configparser.c" - break; - - case 335: /* server_shm_key: VAR_SHM_KEY STRING_ARG */ -#line 586 "util/configparser.y" - { - OUTYY(("P(server_shm_key:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "") == 0 || strcmp((yyvsp[0].str), "0") == 0) - cfg_parser->cfg->shm_key = 0; - else if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->shm_key = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3195 "util/configparser.c" - break; - - case 336: /* server_port: VAR_PORT STRING_ARG */ -#line 597 "util/configparser.y" - { - OUTYY(("P(server_port:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->port = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3207 "util/configparser.c" - break; - - case 337: /* server_send_client_subnet: VAR_SEND_CLIENT_SUBNET STRING_ARG */ -#line 606 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_send_client_subnet:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->client_subnet, (yyvsp[0].str))) - fatal_exit("out of memory adding client-subnet"); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 3222 "util/configparser.c" - break; - - case 338: /* server_client_subnet_zone: VAR_CLIENT_SUBNET_ZONE STRING_ARG */ -#line 618 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_client_subnet_zone:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->client_subnet_zone, - (yyvsp[0].str))) - fatal_exit("out of memory adding client-subnet-zone"); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 3238 "util/configparser.c" - break; - - case 339: /* server_client_subnet_always_forward: VAR_CLIENT_SUBNET_ALWAYS_FORWARD STRING_ARG */ -#line 632 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_client_subnet_always_forward:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->client_subnet_always_forward = - (strcmp((yyvsp[0].str), "yes")==0); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3256 "util/configparser.c" - break; - - case 340: /* server_client_subnet_opcode: VAR_CLIENT_SUBNET_OPCODE STRING_ARG */ -#line 647 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(client_subnet_opcode:%s)\n", (yyvsp[0].str))); - OUTYY(("P(Deprecated option, ignoring)\n")); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3270 "util/configparser.c" - break; - - case 341: /* server_max_client_subnet_ipv4: VAR_MAX_CLIENT_SUBNET_IPV4 STRING_ARG */ -#line 658 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_client_subnet_ipv4:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("IPv4 subnet length expected"); - else if (atoi((yyvsp[0].str)) > 32) - cfg_parser->cfg->max_client_subnet_ipv4 = 32; - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->max_client_subnet_ipv4 = 0; - else cfg_parser->cfg->max_client_subnet_ipv4 = (uint8_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3290 "util/configparser.c" - break; - - case 342: /* server_max_client_subnet_ipv6: VAR_MAX_CLIENT_SUBNET_IPV6 STRING_ARG */ -#line 675 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_client_subnet_ipv6:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("Ipv6 subnet length expected"); - else if (atoi((yyvsp[0].str)) > 128) - cfg_parser->cfg->max_client_subnet_ipv6 = 128; - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->max_client_subnet_ipv6 = 0; - else cfg_parser->cfg->max_client_subnet_ipv6 = (uint8_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3310 "util/configparser.c" - break; - - case 343: /* server_min_client_subnet_ipv4: VAR_MIN_CLIENT_SUBNET_IPV4 STRING_ARG */ -#line 692 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(min_client_subnet_ipv4:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("IPv4 subnet length expected"); - else if (atoi((yyvsp[0].str)) > 32) - cfg_parser->cfg->min_client_subnet_ipv4 = 32; - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->min_client_subnet_ipv4 = 0; - else cfg_parser->cfg->min_client_subnet_ipv4 = (uint8_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3330 "util/configparser.c" - break; - - case 344: /* server_min_client_subnet_ipv6: VAR_MIN_CLIENT_SUBNET_IPV6 STRING_ARG */ -#line 709 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(min_client_subnet_ipv6:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("Ipv6 subnet length expected"); - else if (atoi((yyvsp[0].str)) > 128) - cfg_parser->cfg->min_client_subnet_ipv6 = 128; - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->min_client_subnet_ipv6 = 0; - else cfg_parser->cfg->min_client_subnet_ipv6 = (uint8_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3350 "util/configparser.c" - break; - - case 345: /* server_max_ecs_tree_size_ipv4: VAR_MAX_ECS_TREE_SIZE_IPV4 STRING_ARG */ -#line 726 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_ecs_tree_size_ipv4:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("IPv4 ECS tree size expected"); - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->max_ecs_tree_size_ipv4 = 0; - else cfg_parser->cfg->max_ecs_tree_size_ipv4 = (uint32_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3368 "util/configparser.c" - break; - - case 346: /* server_max_ecs_tree_size_ipv6: VAR_MAX_ECS_TREE_SIZE_IPV6 STRING_ARG */ -#line 741 "util/configparser.y" - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_ecs_tree_size_ipv6:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("IPv6 ECS tree size expected"); - else if (atoi((yyvsp[0].str)) < 0) - cfg_parser->cfg->max_ecs_tree_size_ipv6 = 0; - else cfg_parser->cfg->max_ecs_tree_size_ipv6 = (uint32_t)atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 3386 "util/configparser.c" - break; - - case 347: /* server_interface: VAR_INTERFACE STRING_ARG */ -#line 756 "util/configparser.y" - { - OUTYY(("P(server_interface:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->num_ifs == 0) - cfg_parser->cfg->ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, - (cfg_parser->cfg->num_ifs+1)*sizeof(char*)); - if(!cfg_parser->cfg->ifs) - yyerror("out of memory"); - else - cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = (yyvsp[0].str); - } -#line 3402 "util/configparser.c" - break; - - case 348: /* server_outgoing_interface: VAR_OUTGOING_INTERFACE STRING_ARG */ -#line 769 "util/configparser.y" - { - OUTYY(("P(server_outgoing_interface:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->num_out_ifs == 0) - cfg_parser->cfg->out_ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->out_ifs = realloc( - cfg_parser->cfg->out_ifs, - (cfg_parser->cfg->num_out_ifs+1)*sizeof(char*)); - if(!cfg_parser->cfg->out_ifs) - yyerror("out of memory"); - else - cfg_parser->cfg->out_ifs[ - cfg_parser->cfg->num_out_ifs++] = (yyvsp[0].str); - } -#line 3420 "util/configparser.c" - break; - - case 349: /* server_outgoing_range: VAR_OUTGOING_RANGE STRING_ARG */ -#line 784 "util/configparser.y" - { - OUTYY(("P(server_outgoing_range:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_num_ports = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3432 "util/configparser.c" - break; - - case 350: /* server_outgoing_port_permit: VAR_OUTGOING_PORT_PERMIT STRING_ARG */ -#line 793 "util/configparser.y" - { - OUTYY(("P(server_outgoing_port_permit:%s)\n", (yyvsp[0].str))); - if(!cfg_mark_ports((yyvsp[0].str), 1, - cfg_parser->cfg->outgoing_avail_ports, 65536)) - yyerror("port number or range (\"low-high\") expected"); - free((yyvsp[0].str)); - } -#line 3444 "util/configparser.c" - break; - - case 351: /* server_outgoing_port_avoid: VAR_OUTGOING_PORT_AVOID STRING_ARG */ -#line 802 "util/configparser.y" - { - OUTYY(("P(server_outgoing_port_avoid:%s)\n", (yyvsp[0].str))); - if(!cfg_mark_ports((yyvsp[0].str), 0, - cfg_parser->cfg->outgoing_avail_ports, 65536)) - yyerror("port number or range (\"low-high\") expected"); - free((yyvsp[0].str)); - } -#line 3456 "util/configparser.c" - break; - - case 352: /* server_outgoing_num_tcp: VAR_OUTGOING_NUM_TCP STRING_ARG */ -#line 811 "util/configparser.y" - { - OUTYY(("P(server_outgoing_num_tcp:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_num_tcp = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3468 "util/configparser.c" - break; - - case 353: /* server_incoming_num_tcp: VAR_INCOMING_NUM_TCP STRING_ARG */ -#line 820 "util/configparser.y" - { - OUTYY(("P(server_incoming_num_tcp:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->incoming_num_tcp = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3480 "util/configparser.c" - break; - - case 354: /* server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG */ -#line 829 "util/configparser.y" - { - OUTYY(("P(server_interface_automatic:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->if_automatic = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3492 "util/configparser.c" - break; - - case 355: /* server_interface_automatic_ports: VAR_INTERFACE_AUTOMATIC_PORTS STRING_ARG */ -#line 838 "util/configparser.y" - { - OUTYY(("P(server_interface_automatic_ports:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->if_automatic_ports); - cfg_parser->cfg->if_automatic_ports = (yyvsp[0].str); - } -#line 3502 "util/configparser.c" - break; - - case 356: /* server_do_ip4: VAR_DO_IP4 STRING_ARG */ -#line 845 "util/configparser.y" - { - OUTYY(("P(server_do_ip4:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_ip4 = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3514 "util/configparser.c" - break; - - case 357: /* server_do_ip6: VAR_DO_IP6 STRING_ARG */ -#line 854 "util/configparser.y" - { - OUTYY(("P(server_do_ip6:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_ip6 = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3526 "util/configparser.c" - break; - - case 358: /* server_do_nat64: VAR_DO_NAT64 STRING_ARG */ -#line 863 "util/configparser.y" - { - OUTYY(("P(server_do_nat64:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_nat64 = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3538 "util/configparser.c" - break; - - case 359: /* server_do_udp: VAR_DO_UDP STRING_ARG */ -#line 872 "util/configparser.y" - { - OUTYY(("P(server_do_udp:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_udp = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3550 "util/configparser.c" - break; - - case 360: /* server_do_tcp: VAR_DO_TCP STRING_ARG */ -#line 881 "util/configparser.y" - { - OUTYY(("P(server_do_tcp:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_tcp = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3562 "util/configparser.c" - break; - - case 361: /* server_prefer_ip4: VAR_PREFER_IP4 STRING_ARG */ -#line 890 "util/configparser.y" - { - OUTYY(("P(server_prefer_ip4:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefer_ip4 = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3574 "util/configparser.c" - break; - - case 362: /* server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG */ -#line 899 "util/configparser.y" - { - OUTYY(("P(server_prefer_ip6:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefer_ip6 = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3586 "util/configparser.c" - break; - - case 363: /* server_tcp_mss: VAR_TCP_MSS STRING_ARG */ -#line 908 "util/configparser.y" - { - OUTYY(("P(server_tcp_mss:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->tcp_mss = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3598 "util/configparser.c" - break; - - case 364: /* server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING_ARG */ -#line 917 "util/configparser.y" - { - OUTYY(("P(server_outgoing_tcp_mss:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_tcp_mss = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3610 "util/configparser.c" - break; - - case 365: /* server_tcp_idle_timeout: VAR_TCP_IDLE_TIMEOUT STRING_ARG */ -#line 926 "util/configparser.y" - { - OUTYY(("P(server_tcp_idle_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) > 120000) - cfg_parser->cfg->tcp_idle_timeout = 120000; - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->tcp_idle_timeout = 1; - else cfg_parser->cfg->tcp_idle_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3626 "util/configparser.c" - break; - - case 366: /* server_max_reuse_tcp_queries: VAR_MAX_REUSE_TCP_QUERIES STRING_ARG */ -#line 939 "util/configparser.y" - { - OUTYY(("P(server_max_reuse_tcp_queries:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->max_reuse_tcp_queries = 0; - else cfg_parser->cfg->max_reuse_tcp_queries = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3640 "util/configparser.c" - break; - - case 367: /* server_tcp_reuse_timeout: VAR_TCP_REUSE_TIMEOUT STRING_ARG */ -#line 950 "util/configparser.y" - { - OUTYY(("P(server_tcp_reuse_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->tcp_reuse_timeout = 0; - else cfg_parser->cfg->tcp_reuse_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3654 "util/configparser.c" - break; - - case 368: /* server_tcp_auth_query_timeout: VAR_TCP_AUTH_QUERY_TIMEOUT STRING_ARG */ -#line 961 "util/configparser.y" - { - OUTYY(("P(server_tcp_auth_query_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->tcp_auth_query_timeout = 0; - else cfg_parser->cfg->tcp_auth_query_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3668 "util/configparser.c" - break; - - case 369: /* server_tcp_keepalive: VAR_EDNS_TCP_KEEPALIVE STRING_ARG */ -#line 972 "util/configparser.y" - { - OUTYY(("P(server_tcp_keepalive:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_tcp_keepalive = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3680 "util/configparser.c" - break; - - case 370: /* server_tcp_keepalive_timeout: VAR_EDNS_TCP_KEEPALIVE_TIMEOUT STRING_ARG */ -#line 981 "util/configparser.y" - { - OUTYY(("P(server_tcp_keepalive_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) > 6553500) - cfg_parser->cfg->tcp_keepalive_timeout = 6553500; - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->tcp_keepalive_timeout = 0; - else cfg_parser->cfg->tcp_keepalive_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3696 "util/configparser.c" - break; - - case 371: /* server_sock_queue_timeout: VAR_SOCK_QUEUE_TIMEOUT STRING_ARG */ -#line 994 "util/configparser.y" - { - OUTYY(("P(server_sock_queue_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) > 6553500) - cfg_parser->cfg->sock_queue_timeout = 6553500; - else if (atoi((yyvsp[0].str)) < 1) - cfg_parser->cfg->sock_queue_timeout = 0; - else cfg_parser->cfg->sock_queue_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3712 "util/configparser.c" - break; - - case 372: /* server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG */ -#line 1007 "util/configparser.y" - { - OUTYY(("P(server_tcp_upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tcp_upstream = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3724 "util/configparser.c" - break; - - case 373: /* server_udp_upstream_without_downstream: VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM STRING_ARG */ -#line 1016 "util/configparser.y" - { - OUTYY(("P(server_udp_upstream_without_downstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->udp_upstream_without_downstream = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3736 "util/configparser.c" - break; - - case 374: /* server_ssl_upstream: VAR_SSL_UPSTREAM STRING_ARG */ -#line 1025 "util/configparser.y" - { - OUTYY(("P(server_ssl_upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ssl_upstream = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3748 "util/configparser.c" - break; - - case 375: /* server_ssl_service_key: VAR_SSL_SERVICE_KEY STRING_ARG */ -#line 1034 "util/configparser.y" - { - OUTYY(("P(server_ssl_service_key:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->ssl_service_key); - cfg_parser->cfg->ssl_service_key = (yyvsp[0].str); - } -#line 3758 "util/configparser.c" - break; - - case 376: /* server_ssl_service_pem: VAR_SSL_SERVICE_PEM STRING_ARG */ -#line 1041 "util/configparser.y" - { - OUTYY(("P(server_ssl_service_pem:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->ssl_service_pem); - cfg_parser->cfg->ssl_service_pem = (yyvsp[0].str); - } -#line 3768 "util/configparser.c" - break; - - case 377: /* server_ssl_port: VAR_SSL_PORT STRING_ARG */ -#line 1048 "util/configparser.y" - { - OUTYY(("P(server_ssl_port:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->ssl_port = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3780 "util/configparser.c" - break; - - case 378: /* server_tls_cert_bundle: VAR_TLS_CERT_BUNDLE STRING_ARG */ -#line 1057 "util/configparser.y" - { - OUTYY(("P(server_tls_cert_bundle:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->tls_cert_bundle); - cfg_parser->cfg->tls_cert_bundle = (yyvsp[0].str); - } -#line 3790 "util/configparser.c" - break; - - case 379: /* server_tls_win_cert: VAR_TLS_WIN_CERT STRING_ARG */ -#line 1064 "util/configparser.y" - { - OUTYY(("P(server_tls_win_cert:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tls_win_cert = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3802 "util/configparser.c" - break; - - case 380: /* server_tls_additional_port: VAR_TLS_ADDITIONAL_PORT STRING_ARG */ -#line 1073 "util/configparser.y" - { - OUTYY(("P(server_tls_additional_port:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->tls_additional_port, - (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 3813 "util/configparser.c" - break; - - case 381: /* server_tls_ciphers: VAR_TLS_CIPHERS STRING_ARG */ -#line 1081 "util/configparser.y" - { - OUTYY(("P(server_tls_ciphers:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->tls_ciphers); - cfg_parser->cfg->tls_ciphers = (yyvsp[0].str); - } -#line 3823 "util/configparser.c" - break; - - case 382: /* server_tls_ciphersuites: VAR_TLS_CIPHERSUITES STRING_ARG */ -#line 1088 "util/configparser.y" - { - OUTYY(("P(server_tls_ciphersuites:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->tls_ciphersuites); - cfg_parser->cfg->tls_ciphersuites = (yyvsp[0].str); - } -#line 3833 "util/configparser.c" - break; - - case 383: /* server_tls_session_ticket_keys: VAR_TLS_SESSION_TICKET_KEYS STRING_ARG */ -#line 1095 "util/configparser.y" - { - OUTYY(("P(server_tls_session_ticket_keys:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_append(&cfg_parser->cfg->tls_session_ticket_keys, - (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 3844 "util/configparser.c" - break; - - case 384: /* server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG */ -#line 1103 "util/configparser.y" - { - OUTYY(("P(server_tls_use_sni:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tls_use_sni = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3856 "util/configparser.c" - break; - - case 385: /* server_https_port: VAR_HTTPS_PORT STRING_ARG */ -#line 1112 "util/configparser.y" - { - OUTYY(("P(server_https_port:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->https_port = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3868 "util/configparser.c" - break; - - case 386: /* server_http_endpoint: VAR_HTTP_ENDPOINT STRING_ARG */ -#line 1120 "util/configparser.y" - { - OUTYY(("P(server_http_endpoint:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->http_endpoint); - if((yyvsp[0].str) && (yyvsp[0].str)[0] != '/') { - cfg_parser->cfg->http_endpoint = malloc(strlen((yyvsp[0].str))+2); - if(!cfg_parser->cfg->http_endpoint) - yyerror("out of memory"); - cfg_parser->cfg->http_endpoint[0] = '/'; - memmove(cfg_parser->cfg->http_endpoint+1, (yyvsp[0].str), - strlen((yyvsp[0].str))+1); - free((yyvsp[0].str)); - } else { - cfg_parser->cfg->http_endpoint = (yyvsp[0].str); - } - } -#line 3888 "util/configparser.c" - break; - - case 387: /* server_http_max_streams: VAR_HTTP_MAX_STREAMS STRING_ARG */ -#line 1136 "util/configparser.y" - { - OUTYY(("P(server_http_max_streams:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->http_max_streams = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 3900 "util/configparser.c" - break; - - case 388: /* server_http_query_buffer_size: VAR_HTTP_QUERY_BUFFER_SIZE STRING_ARG */ -#line 1144 "util/configparser.y" - { - OUTYY(("P(server_http_query_buffer_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), - &cfg_parser->cfg->http_query_buffer_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 3912 "util/configparser.c" - break; - - case 389: /* server_http_response_buffer_size: VAR_HTTP_RESPONSE_BUFFER_SIZE STRING_ARG */ -#line 1152 "util/configparser.y" - { - OUTYY(("P(server_http_response_buffer_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), - &cfg_parser->cfg->http_response_buffer_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 3924 "util/configparser.c" - break; - - case 390: /* server_http_nodelay: VAR_HTTP_NODELAY STRING_ARG */ -#line 1160 "util/configparser.y" - { - OUTYY(("P(server_http_nodelay:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->http_nodelay = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3936 "util/configparser.c" - break; - - case 391: /* server_http_notls_downstream: VAR_HTTP_NOTLS_DOWNSTREAM STRING_ARG */ -#line 1168 "util/configparser.y" - { - OUTYY(("P(server_http_notls_downstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->http_notls_downstream = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3948 "util/configparser.c" - break; - - case 392: /* server_use_systemd: VAR_USE_SYSTEMD STRING_ARG */ -#line 1176 "util/configparser.y" - { - OUTYY(("P(server_use_systemd:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_systemd = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3960 "util/configparser.c" - break; - - case 393: /* server_do_daemonize: VAR_DO_DAEMONIZE STRING_ARG */ -#line 1185 "util/configparser.y" - { - OUTYY(("P(server_do_daemonize:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_daemonize = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 3972 "util/configparser.c" - break; - - case 394: /* server_use_syslog: VAR_USE_SYSLOG STRING_ARG */ -#line 1194 "util/configparser.y" - { - OUTYY(("P(server_use_syslog:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_syslog = (strcmp((yyvsp[0].str), "yes")==0); -#if !defined(HAVE_SYSLOG_H) && !defined(UB_ON_WINDOWS) - if(strcmp((yyvsp[0].str), "yes") == 0) - yyerror("no syslog services are available. " - "(reconfigure and compile to add)"); -#endif - free((yyvsp[0].str)); - } -#line 3989 "util/configparser.c" - break; - - case 395: /* server_log_time_ascii: VAR_LOG_TIME_ASCII STRING_ARG */ -#line 1208 "util/configparser.y" - { - OUTYY(("P(server_log_time_ascii:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_time_ascii = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4001 "util/configparser.c" - break; - - case 396: /* server_log_queries: VAR_LOG_QUERIES STRING_ARG */ -#line 1217 "util/configparser.y" - { - OUTYY(("P(server_log_queries:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_queries = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4013 "util/configparser.c" - break; - - case 397: /* server_log_replies: VAR_LOG_REPLIES STRING_ARG */ -#line 1226 "util/configparser.y" - { - OUTYY(("P(server_log_replies:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_replies = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4025 "util/configparser.c" - break; - - case 398: /* server_log_tag_queryreply: VAR_LOG_TAG_QUERYREPLY STRING_ARG */ -#line 1235 "util/configparser.y" - { - OUTYY(("P(server_log_tag_queryreply:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_tag_queryreply = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4037 "util/configparser.c" - break; - - case 399: /* server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG */ -#line 1244 "util/configparser.y" - { - OUTYY(("P(server_log_servfail:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_servfail = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4049 "util/configparser.c" - break; - - case 400: /* server_log_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG */ -#line 1253 "util/configparser.y" - { - OUTYY(("P(server_log_local_actions:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_local_actions = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4061 "util/configparser.c" - break; - - case 401: /* server_chroot: VAR_CHROOT STRING_ARG */ -#line 1262 "util/configparser.y" - { - OUTYY(("P(server_chroot:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->chrootdir); - cfg_parser->cfg->chrootdir = (yyvsp[0].str); - } -#line 4071 "util/configparser.c" - break; - - case 402: /* server_username: VAR_USERNAME STRING_ARG */ -#line 1269 "util/configparser.y" - { - OUTYY(("P(server_username:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->username); - cfg_parser->cfg->username = (yyvsp[0].str); - } -#line 4081 "util/configparser.c" - break; - - case 403: /* server_directory: VAR_DIRECTORY STRING_ARG */ -#line 1276 "util/configparser.y" - { - OUTYY(("P(server_directory:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->directory); - cfg_parser->cfg->directory = (yyvsp[0].str); - /* change there right away for includes relative to this */ - if((yyvsp[0].str)[0]) { - char* d; -#ifdef UB_ON_WINDOWS - w_config_adjust_directory(cfg_parser->cfg); -#endif - d = cfg_parser->cfg->directory; - /* adjust directory if we have already chroot, - * like, we reread after sighup */ - if(cfg_parser->chroot && cfg_parser->chroot[0] && - strncmp(d, cfg_parser->chroot, strlen( - cfg_parser->chroot)) == 0) - d += strlen(cfg_parser->chroot); - if(d[0]) { - if(chdir(d)) - log_err("cannot chdir to directory: %s (%s)", - d, strerror(errno)); - } - } - } -#line 4110 "util/configparser.c" - break; - - case 404: /* server_logfile: VAR_LOGFILE STRING_ARG */ -#line 1302 "util/configparser.y" - { - OUTYY(("P(server_logfile:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->logfile); - cfg_parser->cfg->logfile = (yyvsp[0].str); - cfg_parser->cfg->use_syslog = 0; - } -#line 4121 "util/configparser.c" - break; - - case 405: /* server_pidfile: VAR_PIDFILE STRING_ARG */ -#line 1310 "util/configparser.y" - { - OUTYY(("P(server_pidfile:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->pidfile); - cfg_parser->cfg->pidfile = (yyvsp[0].str); - } -#line 4131 "util/configparser.c" - break; - - case 406: /* server_root_hints: VAR_ROOT_HINTS STRING_ARG */ -#line 1317 "util/configparser.y" - { - OUTYY(("P(server_root_hints:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->root_hints, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4141 "util/configparser.c" - break; - - case 407: /* server_dlv_anchor_file: VAR_DLV_ANCHOR_FILE STRING_ARG */ -#line 1324 "util/configparser.y" - { - OUTYY(("P(server_dlv_anchor_file:%s)\n", (yyvsp[0].str))); - log_warn("option dlv-anchor-file ignored: DLV is decommissioned"); - free((yyvsp[0].str)); - } -#line 4151 "util/configparser.c" - break; - - case 408: /* server_dlv_anchor: VAR_DLV_ANCHOR STRING_ARG */ -#line 1331 "util/configparser.y" - { - OUTYY(("P(server_dlv_anchor:%s)\n", (yyvsp[0].str))); - log_warn("option dlv-anchor ignored: DLV is decommissioned"); - free((yyvsp[0].str)); - } -#line 4161 "util/configparser.c" - break; - - case 409: /* server_auto_trust_anchor_file: VAR_AUTO_TRUST_ANCHOR_FILE STRING_ARG */ -#line 1338 "util/configparser.y" - { - OUTYY(("P(server_auto_trust_anchor_file:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - auto_trust_anchor_file_list, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4172 "util/configparser.c" - break; - - case 410: /* server_trust_anchor_file: VAR_TRUST_ANCHOR_FILE STRING_ARG */ -#line 1346 "util/configparser.y" - { - OUTYY(("P(server_trust_anchor_file:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - trust_anchor_file_list, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4183 "util/configparser.c" - break; - - case 411: /* server_trusted_keys_file: VAR_TRUSTED_KEYS_FILE STRING_ARG */ -#line 1354 "util/configparser.y" - { - OUTYY(("P(server_trusted_keys_file:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - trusted_keys_file_list, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4194 "util/configparser.c" - break; - - case 412: /* server_trust_anchor: VAR_TRUST_ANCHOR STRING_ARG */ -#line 1362 "util/configparser.y" - { - OUTYY(("P(server_trust_anchor:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->trust_anchor_list, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4204 "util/configparser.c" - break; - - case 413: /* server_trust_anchor_signaling: VAR_TRUST_ANCHOR_SIGNALING STRING_ARG */ -#line 1369 "util/configparser.y" - { - OUTYY(("P(server_trust_anchor_signaling:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->trust_anchor_signaling = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4218 "util/configparser.c" - break; - - case 414: /* server_root_key_sentinel: VAR_ROOT_KEY_SENTINEL STRING_ARG */ -#line 1380 "util/configparser.y" - { - OUTYY(("P(server_root_key_sentinel:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->root_key_sentinel = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4232 "util/configparser.c" - break; - - case 415: /* server_domain_insecure: VAR_DOMAIN_INSECURE STRING_ARG */ -#line 1391 "util/configparser.y" - { - OUTYY(("P(server_domain_insecure:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->domain_insecure, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4242 "util/configparser.c" - break; - - case 416: /* server_hide_identity: VAR_HIDE_IDENTITY STRING_ARG */ -#line 1398 "util/configparser.y" - { - OUTYY(("P(server_hide_identity:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_identity = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4254 "util/configparser.c" - break; - - case 417: /* server_hide_version: VAR_HIDE_VERSION STRING_ARG */ -#line 1407 "util/configparser.y" - { - OUTYY(("P(server_hide_version:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_version = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4266 "util/configparser.c" - break; - - case 418: /* server_hide_trustanchor: VAR_HIDE_TRUSTANCHOR STRING_ARG */ -#line 1416 "util/configparser.y" - { - OUTYY(("P(server_hide_trustanchor:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_trustanchor = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4278 "util/configparser.c" - break; - - case 419: /* server_hide_http_user_agent: VAR_HIDE_HTTP_USER_AGENT STRING_ARG */ -#line 1425 "util/configparser.y" - { - OUTYY(("P(server_hide_user_agent:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_http_user_agent = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4290 "util/configparser.c" - break; - - case 420: /* server_identity: VAR_IDENTITY STRING_ARG */ -#line 1434 "util/configparser.y" - { - OUTYY(("P(server_identity:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->identity); - cfg_parser->cfg->identity = (yyvsp[0].str); - } -#line 4300 "util/configparser.c" - break; - - case 421: /* server_version: VAR_VERSION STRING_ARG */ -#line 1441 "util/configparser.y" - { - OUTYY(("P(server_version:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->version); - cfg_parser->cfg->version = (yyvsp[0].str); - } -#line 4310 "util/configparser.c" - break; - - case 422: /* server_http_user_agent: VAR_HTTP_USER_AGENT STRING_ARG */ -#line 1448 "util/configparser.y" - { - OUTYY(("P(server_http_user_agent:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->http_user_agent); - cfg_parser->cfg->http_user_agent = (yyvsp[0].str); - } -#line 4320 "util/configparser.c" - break; - - case 423: /* server_nsid: VAR_NSID STRING_ARG */ -#line 1455 "util/configparser.y" - { - OUTYY(("P(server_nsid:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->nsid_cfg_str); - cfg_parser->cfg->nsid_cfg_str = (yyvsp[0].str); - free(cfg_parser->cfg->nsid); - cfg_parser->cfg->nsid = NULL; - cfg_parser->cfg->nsid_len = 0; - if (*(yyvsp[0].str) == 0) - ; /* pass; empty string is not setting nsid */ - else if (!(cfg_parser->cfg->nsid = cfg_parse_nsid( - (yyvsp[0].str), &cfg_parser->cfg->nsid_len))) - yyerror("the NSID must be either a hex string or an " - "ascii character string prepended with ascii_."); - } -#line 4339 "util/configparser.c" - break; - - case 424: /* server_so_rcvbuf: VAR_SO_RCVBUF STRING_ARG */ -#line 1471 "util/configparser.y" - { - OUTYY(("P(server_so_rcvbuf:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->so_rcvbuf)) - yyerror("buffer size expected"); - free((yyvsp[0].str)); - } -#line 4350 "util/configparser.c" - break; - - case 425: /* server_so_sndbuf: VAR_SO_SNDBUF STRING_ARG */ -#line 1479 "util/configparser.y" - { - OUTYY(("P(server_so_sndbuf:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->so_sndbuf)) - yyerror("buffer size expected"); - free((yyvsp[0].str)); - } -#line 4361 "util/configparser.c" - break; - - case 426: /* server_so_reuseport: VAR_SO_REUSEPORT STRING_ARG */ -#line 1487 "util/configparser.y" - { - OUTYY(("P(server_so_reuseport:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->so_reuseport = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4374 "util/configparser.c" - break; - - case 427: /* server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG */ -#line 1497 "util/configparser.y" - { - OUTYY(("P(server_ip_transparent:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_transparent = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4387 "util/configparser.c" - break; - - case 428: /* server_ip_freebind: VAR_IP_FREEBIND STRING_ARG */ -#line 1507 "util/configparser.y" - { - OUTYY(("P(server_ip_freebind:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_freebind = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4400 "util/configparser.c" - break; - - case 429: /* server_ip_dscp: VAR_IP_DSCP STRING_ARG */ -#line 1517 "util/configparser.y" - { - OUTYY(("P(server_ip_dscp:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) > 63) - yyerror("value too large (max 63)"); - else if (atoi((yyvsp[0].str)) < 0) - yyerror("value too small (min 0)"); - else - cfg_parser->cfg->ip_dscp = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4417 "util/configparser.c" - break; - - case 430: /* server_stream_wait_size: VAR_STREAM_WAIT_SIZE STRING_ARG */ -#line 1531 "util/configparser.y" - { - OUTYY(("P(server_stream_wait_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->stream_wait_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 4428 "util/configparser.c" - break; - - case 431: /* server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG */ -#line 1539 "util/configparser.y" - { - OUTYY(("P(server_edns_buffer_size:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) < 12) - yyerror("edns buffer size too small"); - else if (atoi((yyvsp[0].str)) > 65535) - cfg_parser->cfg->edns_buffer_size = 65535; - else cfg_parser->cfg->edns_buffer_size = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4444 "util/configparser.c" - break; - - case 432: /* server_msg_buffer_size: VAR_MSG_BUFFER_SIZE STRING_ARG */ -#line 1552 "util/configparser.y" - { - OUTYY(("P(server_msg_buffer_size:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else if (atoi((yyvsp[0].str)) < 4096) - yyerror("message buffer size too small (use 4096)"); - else cfg_parser->cfg->msg_buffer_size = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4458 "util/configparser.c" - break; - - case 433: /* server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING_ARG */ -#line 1563 "util/configparser.y" - { - OUTYY(("P(server_msg_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->msg_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 4469 "util/configparser.c" - break; - - case 434: /* server_msg_cache_slabs: VAR_MSG_CACHE_SLABS STRING_ARG */ -#line 1571 "util/configparser.y" - { - OUTYY(("P(server_msg_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->msg_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->msg_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 4485 "util/configparser.c" - break; - - case 435: /* server_num_queries_per_thread: VAR_NUM_QUERIES_PER_THREAD STRING_ARG */ -#line 1584 "util/configparser.y" - { - OUTYY(("P(server_num_queries_per_thread:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->num_queries_per_thread = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4497 "util/configparser.c" - break; - - case 436: /* server_jostle_timeout: VAR_JOSTLE_TIMEOUT STRING_ARG */ -#line 1593 "util/configparser.y" - { - OUTYY(("P(server_jostle_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->jostle_time = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4509 "util/configparser.c" - break; - - case 437: /* server_delay_close: VAR_DELAY_CLOSE STRING_ARG */ -#line 1602 "util/configparser.y" - { - OUTYY(("P(server_delay_close:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->delay_close = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4521 "util/configparser.c" - break; - - case 438: /* server_udp_connect: VAR_UDP_CONNECT STRING_ARG */ -#line 1611 "util/configparser.y" - { - OUTYY(("P(server_udp_connect:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->udp_connect = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4533 "util/configparser.c" - break; - - case 439: /* server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG */ -#line 1620 "util/configparser.y" - { - OUTYY(("P(server_unblock_lan_zones:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->unblock_lan_zones = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4546 "util/configparser.c" - break; - - case 440: /* server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG */ -#line 1630 "util/configparser.y" - { - OUTYY(("P(server_insecure_lan_zones:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->insecure_lan_zones = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4559 "util/configparser.c" - break; - - case 441: /* server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG */ -#line 1640 "util/configparser.y" - { - OUTYY(("P(server_rrset_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->rrset_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 4570 "util/configparser.c" - break; - - case 442: /* server_rrset_cache_slabs: VAR_RRSET_CACHE_SLABS STRING_ARG */ -#line 1648 "util/configparser.y" - { - OUTYY(("P(server_rrset_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->rrset_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->rrset_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 4586 "util/configparser.c" - break; - - case 443: /* server_infra_host_ttl: VAR_INFRA_HOST_TTL STRING_ARG */ -#line 1661 "util/configparser.y" - { - OUTYY(("P(server_infra_host_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->host_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4598 "util/configparser.c" - break; - - case 444: /* server_infra_lame_ttl: VAR_INFRA_LAME_TTL STRING_ARG */ -#line 1670 "util/configparser.y" - { - OUTYY(("P(server_infra_lame_ttl:%s)\n", (yyvsp[0].str))); - verbose(VERB_DETAIL, "ignored infra-lame-ttl: %s (option " - "removed, use infra-host-ttl)", (yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4609 "util/configparser.c" - break; - - case 445: /* server_infra_cache_numhosts: VAR_INFRA_CACHE_NUMHOSTS STRING_ARG */ -#line 1678 "util/configparser.y" - { - OUTYY(("P(server_infra_cache_numhosts:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_numhosts = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4621 "util/configparser.c" - break; - - case 446: /* server_infra_cache_lame_size: VAR_INFRA_CACHE_LAME_SIZE STRING_ARG */ -#line 1687 "util/configparser.y" - { - OUTYY(("P(server_infra_cache_lame_size:%s)\n", (yyvsp[0].str))); - verbose(VERB_DETAIL, "ignored infra-cache-lame-size: %s " - "(option removed, use infra-cache-numhosts)", (yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4632 "util/configparser.c" - break; - - case 447: /* server_infra_cache_slabs: VAR_INFRA_CACHE_SLABS STRING_ARG */ -#line 1695 "util/configparser.y" - { - OUTYY(("P(server_infra_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->infra_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->infra_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 4648 "util/configparser.c" - break; - - case 448: /* server_infra_cache_min_rtt: VAR_INFRA_CACHE_MIN_RTT STRING_ARG */ -#line 1708 "util/configparser.y" - { - OUTYY(("P(server_infra_cache_min_rtt:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_min_rtt = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4660 "util/configparser.c" - break; - - case 449: /* server_infra_cache_max_rtt: VAR_INFRA_CACHE_MAX_RTT STRING_ARG */ -#line 1717 "util/configparser.y" - { - OUTYY(("P(server_infra_cache_max_rtt:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_max_rtt = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4672 "util/configparser.c" - break; - - case 450: /* server_infra_keep_probing: VAR_INFRA_KEEP_PROBING STRING_ARG */ -#line 1726 "util/configparser.y" - { - OUTYY(("P(server_infra_keep_probing:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->infra_keep_probing = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4685 "util/configparser.c" - break; - - case 451: /* server_target_fetch_policy: VAR_TARGET_FETCH_POLICY STRING_ARG */ -#line 1736 "util/configparser.y" - { - OUTYY(("P(server_target_fetch_policy:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->target_fetch_policy); - cfg_parser->cfg->target_fetch_policy = (yyvsp[0].str); - } -#line 4695 "util/configparser.c" - break; - - case 452: /* server_harden_short_bufsize: VAR_HARDEN_SHORT_BUFSIZE STRING_ARG */ -#line 1743 "util/configparser.y" - { - OUTYY(("P(server_harden_short_bufsize:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_short_bufsize = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4708 "util/configparser.c" - break; - - case 453: /* server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING_ARG */ -#line 1753 "util/configparser.y" - { - OUTYY(("P(server_harden_large_queries:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_large_queries = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4721 "util/configparser.c" - break; - - case 454: /* server_harden_glue: VAR_HARDEN_GLUE STRING_ARG */ -#line 1763 "util/configparser.y" - { - OUTYY(("P(server_harden_glue:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_glue = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4734 "util/configparser.c" - break; - - case 455: /* server_harden_dnssec_stripped: VAR_HARDEN_DNSSEC_STRIPPED STRING_ARG */ -#line 1773 "util/configparser.y" - { - OUTYY(("P(server_harden_dnssec_stripped:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_dnssec_stripped = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4747 "util/configparser.c" - break; - - case 456: /* server_harden_below_nxdomain: VAR_HARDEN_BELOW_NXDOMAIN STRING_ARG */ -#line 1783 "util/configparser.y" - { - OUTYY(("P(server_harden_below_nxdomain:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_below_nxdomain = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4760 "util/configparser.c" - break; - - case 457: /* server_harden_referral_path: VAR_HARDEN_REFERRAL_PATH STRING_ARG */ -#line 1793 "util/configparser.y" - { - OUTYY(("P(server_harden_referral_path:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_referral_path = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4773 "util/configparser.c" - break; - - case 458: /* server_harden_algo_downgrade: VAR_HARDEN_ALGO_DOWNGRADE STRING_ARG */ -#line 1803 "util/configparser.y" - { - OUTYY(("P(server_harden_algo_downgrade:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_algo_downgrade = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4786 "util/configparser.c" - break; - - case 459: /* server_harden_unknown_additional: VAR_HARDEN_UNKNOWN_ADDITIONAL STRING_ARG */ -#line 1813 "util/configparser.y" - { - OUTYY(("P(server_harden_unknown_additional:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_unknown_additional = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4799 "util/configparser.c" - break; - - case 460: /* server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG */ -#line 1823 "util/configparser.y" - { - OUTYY(("P(server_use_caps_for_id:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_caps_bits_for_id = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4812 "util/configparser.c" - break; - - case 461: /* server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG */ -#line 1833 "util/configparser.y" - { - OUTYY(("P(server_caps_whitelist:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4822 "util/configparser.c" - break; - - case 462: /* server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG */ -#line 1840 "util/configparser.y" - { - OUTYY(("P(server_private_address:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->private_address, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4832 "util/configparser.c" - break; - - case 463: /* server_private_domain: VAR_PRIVATE_DOMAIN STRING_ARG */ -#line 1847 "util/configparser.y" - { - OUTYY(("P(server_private_domain:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->private_domain, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4842 "util/configparser.c" - break; - - case 464: /* server_prefetch: VAR_PREFETCH STRING_ARG */ -#line 1854 "util/configparser.y" - { - OUTYY(("P(server_prefetch:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefetch = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4854 "util/configparser.c" - break; - - case 465: /* server_prefetch_key: VAR_PREFETCH_KEY STRING_ARG */ -#line 1863 "util/configparser.y" - { - OUTYY(("P(server_prefetch_key:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefetch_key = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4866 "util/configparser.c" - break; - - case 466: /* server_deny_any: VAR_DENY_ANY STRING_ARG */ -#line 1872 "util/configparser.y" - { - OUTYY(("P(server_deny_any:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->deny_any = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4878 "util/configparser.c" - break; - - case 467: /* server_unwanted_reply_threshold: VAR_UNWANTED_REPLY_THRESHOLD STRING_ARG */ -#line 1881 "util/configparser.y" - { - OUTYY(("P(server_unwanted_reply_threshold:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->unwanted_threshold = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 4890 "util/configparser.c" - break; - - case 468: /* server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING_ARG */ -#line 1890 "util/configparser.y" - { - OUTYY(("P(server_do_not_query_address:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 4900 "util/configparser.c" - break; - - case 469: /* server_do_not_query_localhost: VAR_DO_NOT_QUERY_LOCALHOST STRING_ARG */ -#line 1897 "util/configparser.y" - { - OUTYY(("P(server_do_not_query_localhost:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->donotquery_localhost = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 4913 "util/configparser.c" - break; - - case 470: /* server_access_control: VAR_ACCESS_CONTROL STRING_ARG STRING_ARG */ -#line 1907 "util/configparser.y" - { - OUTYY(("P(server_access_control:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - validate_acl_action((yyvsp[0].str)); - if(!cfg_str2list_insert(&cfg_parser->cfg->acls, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding acl"); - } -#line 4924 "util/configparser.c" - break; - - case 471: /* server_interface_action: VAR_INTERFACE_ACTION STRING_ARG STRING_ARG */ -#line 1915 "util/configparser.y" - { - OUTYY(("P(server_interface_action:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - validate_acl_action((yyvsp[0].str)); - if(!cfg_str2list_insert( - &cfg_parser->cfg->interface_actions, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding acl"); - } -#line 4936 "util/configparser.c" - break; - - case 472: /* server_module_conf: VAR_MODULE_CONF STRING_ARG */ -#line 1924 "util/configparser.y" - { - OUTYY(("P(server_module_conf:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->module_conf); - cfg_parser->cfg->module_conf = (yyvsp[0].str); - } -#line 4946 "util/configparser.c" - break; - - case 473: /* server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG */ -#line 1931 "util/configparser.y" - { - OUTYY(("P(server_val_override_date:%s)\n", (yyvsp[0].str))); - if(*(yyvsp[0].str) == '\0' || strcmp((yyvsp[0].str), "0") == 0) { - cfg_parser->cfg->val_date_override = 0; - } else if(strlen((yyvsp[0].str)) == 14) { - cfg_parser->cfg->val_date_override = - cfg_convert_timeval((yyvsp[0].str)); - if(!cfg_parser->cfg->val_date_override) - yyerror("bad date/time specification"); - } else { - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - cfg_parser->cfg->val_date_override = atoi((yyvsp[0].str)); - } - free((yyvsp[0].str)); - } -#line 4967 "util/configparser.c" - break; - - case 474: /* server_val_sig_skew_min: VAR_VAL_SIG_SKEW_MIN STRING_ARG */ -#line 1949 "util/configparser.y" - { - OUTYY(("P(server_val_sig_skew_min:%s)\n", (yyvsp[0].str))); - if(*(yyvsp[0].str) == '\0' || strcmp((yyvsp[0].str), "0") == 0) { - cfg_parser->cfg->val_sig_skew_min = 0; - } else { - cfg_parser->cfg->val_sig_skew_min = atoi((yyvsp[0].str)); - if(!cfg_parser->cfg->val_sig_skew_min) - yyerror("number expected"); - } - free((yyvsp[0].str)); - } -#line 4983 "util/configparser.c" - break; - - case 475: /* server_val_sig_skew_max: VAR_VAL_SIG_SKEW_MAX STRING_ARG */ -#line 1962 "util/configparser.y" - { - OUTYY(("P(server_val_sig_skew_max:%s)\n", (yyvsp[0].str))); - if(*(yyvsp[0].str) == '\0' || strcmp((yyvsp[0].str), "0") == 0) { - cfg_parser->cfg->val_sig_skew_max = 0; - } else { - cfg_parser->cfg->val_sig_skew_max = atoi((yyvsp[0].str)); - if(!cfg_parser->cfg->val_sig_skew_max) - yyerror("number expected"); - } - free((yyvsp[0].str)); - } -#line 4999 "util/configparser.c" - break; - - case 476: /* server_val_max_restart: VAR_VAL_MAX_RESTART STRING_ARG */ -#line 1975 "util/configparser.y" - { - OUTYY(("P(server_val_max_restart:%s)\n", (yyvsp[0].str))); - if(*(yyvsp[0].str) == '\0' || strcmp((yyvsp[0].str), "0") == 0) { - cfg_parser->cfg->val_max_restart = 0; - } else { - cfg_parser->cfg->val_max_restart = atoi((yyvsp[0].str)); - if(!cfg_parser->cfg->val_max_restart) - yyerror("number expected"); - } - free((yyvsp[0].str)); - } -#line 5015 "util/configparser.c" - break; - - case 477: /* server_cache_max_ttl: VAR_CACHE_MAX_TTL STRING_ARG */ -#line 1988 "util/configparser.y" - { - OUTYY(("P(server_cache_max_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5027 "util/configparser.c" - break; - - case 478: /* server_cache_max_negative_ttl: VAR_CACHE_MAX_NEGATIVE_TTL STRING_ARG */ -#line 1997 "util/configparser.y" - { - OUTYY(("P(server_cache_max_negative_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_negative_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5039 "util/configparser.c" - break; - - case 479: /* server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG */ -#line 2006 "util/configparser.y" - { - OUTYY(("P(server_cache_min_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->min_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5051 "util/configparser.c" - break; - - case 480: /* server_bogus_ttl: VAR_BOGUS_TTL STRING_ARG */ -#line 2015 "util/configparser.y" - { - OUTYY(("P(server_bogus_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->bogus_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5063 "util/configparser.c" - break; - - case 481: /* server_val_clean_additional: VAR_VAL_CLEAN_ADDITIONAL STRING_ARG */ -#line 2024 "util/configparser.y" - { - OUTYY(("P(server_val_clean_additional:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->val_clean_additional = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5076 "util/configparser.c" - break; - - case 482: /* server_val_permissive_mode: VAR_VAL_PERMISSIVE_MODE STRING_ARG */ -#line 2034 "util/configparser.y" - { - OUTYY(("P(server_val_permissive_mode:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->val_permissive_mode = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5089 "util/configparser.c" - break; - - case 483: /* server_aggressive_nsec: VAR_AGGRESSIVE_NSEC STRING_ARG */ -#line 2044 "util/configparser.y" - { - OUTYY(("P(server_aggressive_nsec:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->aggressive_nsec = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5103 "util/configparser.c" - break; - - case 484: /* server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG */ -#line 2055 "util/configparser.y" - { - OUTYY(("P(server_ignore_cd_flag:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ignore_cd = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5115 "util/configparser.c" - break; - - case 485: /* server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG */ -#line 2064 "util/configparser.y" - { - OUTYY(("P(server_serve_expired:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_expired = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5127 "util/configparser.c" - break; - - case 486: /* server_serve_expired_ttl: VAR_SERVE_EXPIRED_TTL STRING_ARG */ -#line 2073 "util/configparser.y" - { - OUTYY(("P(server_serve_expired_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5139 "util/configparser.c" - break; - - case 487: /* server_serve_expired_ttl_reset: VAR_SERVE_EXPIRED_TTL_RESET STRING_ARG */ -#line 2082 "util/configparser.y" - { - OUTYY(("P(server_serve_expired_ttl_reset:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_expired_ttl_reset = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5151 "util/configparser.c" - break; - - case 488: /* server_serve_expired_reply_ttl: VAR_SERVE_EXPIRED_REPLY_TTL STRING_ARG */ -#line 2091 "util/configparser.y" - { - OUTYY(("P(server_serve_expired_reply_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_reply_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5163 "util/configparser.c" - break; - - case 489: /* server_serve_expired_client_timeout: VAR_SERVE_EXPIRED_CLIENT_TIMEOUT STRING_ARG */ -#line 2100 "util/configparser.y" - { - OUTYY(("P(server_serve_expired_client_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_client_timeout = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5175 "util/configparser.c" - break; - - case 490: /* server_ede_serve_expired: VAR_EDE_SERVE_EXPIRED STRING_ARG */ -#line 2109 "util/configparser.y" - { - OUTYY(("P(server_ede_serve_expired:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ede_serve_expired = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5187 "util/configparser.c" - break; - - case 491: /* server_serve_original_ttl: VAR_SERVE_ORIGINAL_TTL STRING_ARG */ -#line 2118 "util/configparser.y" - { - OUTYY(("P(server_serve_original_ttl:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_original_ttl = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5199 "util/configparser.c" - break; - - case 492: /* server_fake_dsa: VAR_FAKE_DSA STRING_ARG */ -#line 2127 "util/configparser.y" - { - OUTYY(("P(server_fake_dsa:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); -#if defined(HAVE_SSL) || defined(HAVE_NETTLE) - else fake_dsa = (strcmp((yyvsp[0].str), "yes")==0); - if(fake_dsa) - log_warn("test option fake_dsa is enabled"); -#endif - free((yyvsp[0].str)); - } -#line 5215 "util/configparser.c" - break; - - case 493: /* server_fake_sha1: VAR_FAKE_SHA1 STRING_ARG */ -#line 2140 "util/configparser.y" - { - OUTYY(("P(server_fake_sha1:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); -#if defined(HAVE_SSL) || defined(HAVE_NETTLE) - else fake_sha1 = (strcmp((yyvsp[0].str), "yes")==0); - if(fake_sha1) - log_warn("test option fake_sha1 is enabled"); -#endif - free((yyvsp[0].str)); - } -#line 5231 "util/configparser.c" - break; - - case 494: /* server_val_log_level: VAR_VAL_LOG_LEVEL STRING_ARG */ -#line 2153 "util/configparser.y" - { - OUTYY(("P(server_val_log_level:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->val_log_level = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5243 "util/configparser.c" - break; - - case 495: /* server_val_nsec3_keysize_iterations: VAR_VAL_NSEC3_KEYSIZE_ITERATIONS STRING_ARG */ -#line 2162 "util/configparser.y" - { - OUTYY(("P(server_val_nsec3_keysize_iterations:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->val_nsec3_key_iterations); - cfg_parser->cfg->val_nsec3_key_iterations = (yyvsp[0].str); - } -#line 5253 "util/configparser.c" - break; - - case 496: /* server_zonemd_permissive_mode: VAR_ZONEMD_PERMISSIVE_MODE STRING_ARG */ -#line 2169 "util/configparser.y" - { - OUTYY(("P(server_zonemd_permissive_mode:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->zonemd_permissive_mode = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5265 "util/configparser.c" - break; - - case 497: /* server_add_holddown: VAR_ADD_HOLDDOWN STRING_ARG */ -#line 2178 "util/configparser.y" - { - OUTYY(("P(server_add_holddown:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->add_holddown = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5277 "util/configparser.c" - break; - - case 498: /* server_del_holddown: VAR_DEL_HOLDDOWN STRING_ARG */ -#line 2187 "util/configparser.y" - { - OUTYY(("P(server_del_holddown:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->del_holddown = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5289 "util/configparser.c" - break; - - case 499: /* server_keep_missing: VAR_KEEP_MISSING STRING_ARG */ -#line 2196 "util/configparser.y" - { - OUTYY(("P(server_keep_missing:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->keep_missing = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5301 "util/configparser.c" - break; - - case 500: /* server_permit_small_holddown: VAR_PERMIT_SMALL_HOLDDOWN STRING_ARG */ -#line 2205 "util/configparser.y" - { - OUTYY(("P(server_permit_small_holddown:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->permit_small_holddown = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5314 "util/configparser.c" - break; - - case 501: /* server_key_cache_size: VAR_KEY_CACHE_SIZE STRING_ARG */ -#line 2215 "util/configparser.y" - { - OUTYY(("P(server_key_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->key_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 5325 "util/configparser.c" - break; - - case 502: /* server_key_cache_slabs: VAR_KEY_CACHE_SLABS STRING_ARG */ -#line 2223 "util/configparser.y" - { - OUTYY(("P(server_key_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->key_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->key_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 5341 "util/configparser.c" - break; - - case 503: /* server_neg_cache_size: VAR_NEG_CACHE_SIZE STRING_ARG */ -#line 2236 "util/configparser.y" - { - OUTYY(("P(server_neg_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->neg_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 5352 "util/configparser.c" - break; - - case 504: /* server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG */ -#line 2244 "util/configparser.y" - { - OUTYY(("P(server_local_zone:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "static")!=0 && strcmp((yyvsp[0].str), "deny")!=0 && - strcmp((yyvsp[0].str), "refuse")!=0 && strcmp((yyvsp[0].str), "redirect")!=0 && - strcmp((yyvsp[0].str), "transparent")!=0 && strcmp((yyvsp[0].str), "nodefault")!=0 - && strcmp((yyvsp[0].str), "typetransparent")!=0 - && strcmp((yyvsp[0].str), "always_transparent")!=0 - && strcmp((yyvsp[0].str), "block_a")!=0 - && strcmp((yyvsp[0].str), "always_refuse")!=0 - && strcmp((yyvsp[0].str), "always_nxdomain")!=0 - && strcmp((yyvsp[0].str), "always_nodata")!=0 - && strcmp((yyvsp[0].str), "always_deny")!=0 - && strcmp((yyvsp[0].str), "always_null")!=0 - && strcmp((yyvsp[0].str), "noview")!=0 - && strcmp((yyvsp[0].str), "inform")!=0 && strcmp((yyvsp[0].str), "inform_deny")!=0 - && strcmp((yyvsp[0].str), "inform_redirect") != 0 - && strcmp((yyvsp[0].str), "ipset") != 0) { - yyerror("local-zone type: expected static, deny, " - "refuse, redirect, transparent, " - "typetransparent, inform, inform_deny, " - "inform_redirect, always_transparent, block_a," - "always_refuse, always_nxdomain, " - "always_nodata, always_deny, always_null, " - "noview, nodefault or ipset"); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } else if(strcmp((yyvsp[0].str), "nodefault")==0) { - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_zones_nodefault, (yyvsp[-1].str))) - fatal_exit("out of memory adding local-zone"); - free((yyvsp[0].str)); -#ifdef USE_IPSET - } else if(strcmp((yyvsp[0].str), "ipset")==0) { - size_t len = strlen((yyvsp[-1].str)); - /* Make sure to add the trailing dot. - * These are str compared to domain names. */ - if((yyvsp[-1].str)[len-1] != '.') { - if(!((yyvsp[-1].str) = realloc((yyvsp[-1].str), len+2))) { - fatal_exit("out of memory adding local-zone"); - } - (yyvsp[-1].str)[len] = '.'; - (yyvsp[-1].str)[len+1] = 0; - } - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_zones_ipset, (yyvsp[-1].str))) - fatal_exit("out of memory adding local-zone"); - free((yyvsp[0].str)); -#endif - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, - (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding local-zone"); - } - } -#line 5411 "util/configparser.c" - break; - - case 505: /* server_local_data: VAR_LOCAL_DATA STRING_ARG */ -#line 2300 "util/configparser.y" - { - OUTYY(("P(server_local_data:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, (yyvsp[0].str))) - fatal_exit("out of memory adding local-data"); - } -#line 5421 "util/configparser.c" - break; - - case 506: /* server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG */ -#line 2307 "util/configparser.y" - { - char* ptr; - OUTYY(("P(server_local_data_ptr:%s)\n", (yyvsp[0].str))); - ptr = cfg_ptr_reverse((yyvsp[0].str)); - free((yyvsp[0].str)); - if(ptr) { - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_data, ptr)) - fatal_exit("out of memory adding local-data"); - } else { - yyerror("local-data-ptr could not be reversed"); - } - } -#line 5439 "util/configparser.c" - break; - - case 507: /* server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG */ -#line 2322 "util/configparser.y" - { - OUTYY(("P(server_minimal_responses:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->minimal_responses = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5452 "util/configparser.c" - break; - - case 508: /* server_rrset_roundrobin: VAR_RRSET_ROUNDROBIN STRING_ARG */ -#line 2332 "util/configparser.y" - { - OUTYY(("P(server_rrset_roundrobin:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->rrset_roundrobin = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5465 "util/configparser.c" - break; - - case 509: /* server_unknown_server_time_limit: VAR_UNKNOWN_SERVER_TIME_LIMIT STRING_ARG */ -#line 2342 "util/configparser.y" - { - OUTYY(("P(server_unknown_server_time_limit:%s)\n", (yyvsp[0].str))); - cfg_parser->cfg->unknown_server_time_limit = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5475 "util/configparser.c" - break; - - case 510: /* server_max_udp_size: VAR_MAX_UDP_SIZE STRING_ARG */ -#line 2349 "util/configparser.y" - { - OUTYY(("P(server_max_udp_size:%s)\n", (yyvsp[0].str))); - cfg_parser->cfg->max_udp_size = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5485 "util/configparser.c" - break; - - case 511: /* server_dns64_prefix: VAR_DNS64_PREFIX STRING_ARG */ -#line 2356 "util/configparser.y" - { - OUTYY(("P(dns64_prefix:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dns64_prefix); - cfg_parser->cfg->dns64_prefix = (yyvsp[0].str); - } -#line 5495 "util/configparser.c" - break; - - case 512: /* server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG */ -#line 2363 "util/configparser.y" - { - OUTYY(("P(server_dns64_synthall:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dns64_synthall = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5507 "util/configparser.c" - break; - - case 513: /* server_dns64_ignore_aaaa: VAR_DNS64_IGNORE_AAAA STRING_ARG */ -#line 2372 "util/configparser.y" - { - OUTYY(("P(dns64_ignore_aaaa:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->dns64_ignore_aaaa, - (yyvsp[0].str))) - fatal_exit("out of memory adding dns64-ignore-aaaa"); - } -#line 5518 "util/configparser.c" - break; - - case 514: /* server_nat64_prefix: VAR_NAT64_PREFIX STRING_ARG */ -#line 2380 "util/configparser.y" - { - OUTYY(("P(nat64_prefix:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->nat64_prefix); - cfg_parser->cfg->nat64_prefix = (yyvsp[0].str); - } -#line 5528 "util/configparser.c" - break; - - case 515: /* server_define_tag: VAR_DEFINE_TAG STRING_ARG */ -#line 2387 "util/configparser.y" - { - char* p, *s = (yyvsp[0].str); - OUTYY(("P(server_define_tag:%s)\n", (yyvsp[0].str))); - while((p=strsep(&s, " \t\n")) != NULL) { - if(*p) { - if(!config_add_tag(cfg_parser->cfg, p)) - yyerror("could not define-tag, " - "out of memory"); - } - } - free((yyvsp[0].str)); - } -#line 5545 "util/configparser.c" - break; - - case 516: /* server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG */ -#line 2401 "util/configparser.y" - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, (yyvsp[0].str), - &len); - free((yyvsp[0].str)); - OUTYY(("P(server_local_zone_tag:%s)\n", (yyvsp[-1].str))); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free((yyvsp[-1].str)); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->local_zone_tags, - (yyvsp[-1].str), bitlist, len)) { - yyerror("out of memory"); - free((yyvsp[-1].str)); - } - } - } -#line 5569 "util/configparser.c" - break; - - case 517: /* server_access_control_tag: VAR_ACCESS_CONTROL_TAG STRING_ARG STRING_ARG */ -#line 2422 "util/configparser.y" - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, (yyvsp[0].str), - &len); - free((yyvsp[0].str)); - OUTYY(("P(server_access_control_tag:%s)\n", (yyvsp[-1].str))); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free((yyvsp[-1].str)); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->acl_tags, - (yyvsp[-1].str), bitlist, len)) { - yyerror("out of memory"); - free((yyvsp[-1].str)); - } - } - } -#line 5593 "util/configparser.c" - break; - - case 518: /* server_access_control_tag_action: VAR_ACCESS_CONTROL_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG */ -#line 2443 "util/configparser.y" - { - OUTYY(("P(server_access_control_tag_action:%s %s %s)\n", (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_actions, - (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - free((yyvsp[-2].str)); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } - } -#line 5608 "util/configparser.c" - break; - - case 519: /* server_access_control_tag_data: VAR_ACCESS_CONTROL_TAG_DATA STRING_ARG STRING_ARG STRING_ARG */ -#line 2455 "util/configparser.y" - { - OUTYY(("P(server_access_control_tag_data:%s %s %s)\n", (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_datas, - (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - free((yyvsp[-2].str)); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } - } -#line 5623 "util/configparser.c" - break; - - case 520: /* server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING_ARG */ -#line 2467 "util/configparser.y" - { - OUTYY(("P(server_local_zone_override:%s %s %s)\n", (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str3list_insert(&cfg_parser->cfg->local_zone_overrides, - (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - free((yyvsp[-2].str)); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } - } -#line 5638 "util/configparser.c" - break; - - case 521: /* server_access_control_view: VAR_ACCESS_CONTROL_VIEW STRING_ARG STRING_ARG */ -#line 2479 "util/configparser.y" - { - OUTYY(("P(server_access_control_view:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str2list_insert(&cfg_parser->cfg->acl_view, - (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - } - } -#line 5650 "util/configparser.c" - break; - - case 522: /* server_interface_tag: VAR_INTERFACE_TAG STRING_ARG STRING_ARG */ -#line 2488 "util/configparser.y" - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, (yyvsp[0].str), - &len); - free((yyvsp[0].str)); - OUTYY(("P(server_interface_tag:%s)\n", (yyvsp[-1].str))); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free((yyvsp[-1].str)); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->interface_tags, - (yyvsp[-1].str), bitlist, len)) { - yyerror("out of memory"); - free((yyvsp[-1].str)); - } - } - } -#line 5674 "util/configparser.c" - break; - - case 523: /* server_interface_tag_action: VAR_INTERFACE_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG */ -#line 2509 "util/configparser.y" - { - OUTYY(("P(server_interface_tag_action:%s %s %s)\n", (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str3list_insert(&cfg_parser->cfg->interface_tag_actions, - (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - free((yyvsp[-2].str)); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } - } -#line 5689 "util/configparser.c" - break; - - case 524: /* server_interface_tag_data: VAR_INTERFACE_TAG_DATA STRING_ARG STRING_ARG STRING_ARG */ -#line 2521 "util/configparser.y" - { - OUTYY(("P(server_interface_tag_data:%s %s %s)\n", (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str3list_insert(&cfg_parser->cfg->interface_tag_datas, - (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - free((yyvsp[-2].str)); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } - } -#line 5704 "util/configparser.c" - break; - - case 525: /* server_interface_view: VAR_INTERFACE_VIEW STRING_ARG STRING_ARG */ -#line 2533 "util/configparser.y" - { - OUTYY(("P(server_interface_view:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str2list_insert(&cfg_parser->cfg->interface_view, - (yyvsp[-1].str), (yyvsp[0].str))) { - yyerror("out of memory"); - } - } -#line 5716 "util/configparser.c" - break; - - case 526: /* server_response_ip_tag: VAR_RESPONSE_IP_TAG STRING_ARG STRING_ARG */ -#line 2542 "util/configparser.y" - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, (yyvsp[0].str), - &len); - free((yyvsp[0].str)); - OUTYY(("P(response_ip_tag:%s)\n", (yyvsp[-1].str))); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free((yyvsp[-1].str)); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->respip_tags, - (yyvsp[-1].str), bitlist, len)) { - yyerror("out of memory"); - free((yyvsp[-1].str)); - } - } - } -#line 5740 "util/configparser.c" - break; - - case 527: /* server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG */ -#line 2563 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5752 "util/configparser.c" - break; - - case 528: /* server_ip_ratelimit_cookie: VAR_IP_RATELIMIT_COOKIE STRING_ARG */ -#line 2572 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit_cookie:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit_cookie = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5764 "util/configparser.c" - break; - - case 529: /* server_ratelimit: VAR_RATELIMIT STRING_ARG */ -#line 2581 "util/configparser.y" - { - OUTYY(("P(server_ratelimit:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ratelimit = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5776 "util/configparser.c" - break; - - case 530: /* server_ip_ratelimit_size: VAR_IP_RATELIMIT_SIZE STRING_ARG */ -#line 2590 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->ip_ratelimit_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 5787 "util/configparser.c" - break; - - case 531: /* server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG */ -#line 2598 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->ratelimit_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 5798 "util/configparser.c" - break; - - case 532: /* server_ip_ratelimit_slabs: VAR_IP_RATELIMIT_SLABS STRING_ARG */ -#line 2606 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->ip_ratelimit_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 5814 "util/configparser.c" - break; - - case 533: /* server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG */ -#line 2619 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->ratelimit_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->ratelimit_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 5830 "util/configparser.c" - break; - - case 534: /* server_ratelimit_for_domain: VAR_RATELIMIT_FOR_DOMAIN STRING_ARG STRING_ARG */ -#line 2632 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_for_domain:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) { - yyerror("number expected"); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg-> - ratelimit_for_domain, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding " - "ratelimit-for-domain"); - } - } -#line 5848 "util/configparser.c" - break; - - case 535: /* server_ratelimit_below_domain: VAR_RATELIMIT_BELOW_DOMAIN STRING_ARG STRING_ARG */ -#line 2647 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_below_domain:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) { - yyerror("number expected"); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg-> - ratelimit_below_domain, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding " - "ratelimit-below-domain"); - } - } -#line 5866 "util/configparser.c" - break; - - case 536: /* server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG */ -#line 2662 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit_factor:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit_factor = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5878 "util/configparser.c" - break; - - case 537: /* server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG */ -#line 2671 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_factor:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ratelimit_factor = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5890 "util/configparser.c" - break; - - case 538: /* server_ip_ratelimit_backoff: VAR_IP_RATELIMIT_BACKOFF STRING_ARG */ -#line 2680 "util/configparser.y" - { - OUTYY(("P(server_ip_ratelimit_backoff:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_ratelimit_backoff = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5903 "util/configparser.c" - break; - - case 539: /* server_ratelimit_backoff: VAR_RATELIMIT_BACKOFF STRING_ARG */ -#line 2690 "util/configparser.y" - { - OUTYY(("P(server_ratelimit_backoff:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ratelimit_backoff = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5916 "util/configparser.c" - break; - - case 540: /* server_outbound_msg_retry: VAR_OUTBOUND_MSG_RETRY STRING_ARG */ -#line 2700 "util/configparser.y" - { - OUTYY(("P(server_outbound_msg_retry:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outbound_msg_retry = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5928 "util/configparser.c" - break; - - case 541: /* server_max_sent_count: VAR_MAX_SENT_COUNT STRING_ARG */ -#line 2709 "util/configparser.y" - { - OUTYY(("P(server_max_sent_count:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_sent_count = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5940 "util/configparser.c" - break; - - case 542: /* server_max_query_restarts: VAR_MAX_QUERY_RESTARTS STRING_ARG */ -#line 2718 "util/configparser.y" - { - OUTYY(("P(server_max_query_restarts:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_query_restarts = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5952 "util/configparser.c" - break; - - case 543: /* server_low_rtt: VAR_LOW_RTT STRING_ARG */ -#line 2727 "util/configparser.y" - { - OUTYY(("P(low-rtt option is deprecated, use fast-server-num instead)\n")); - free((yyvsp[0].str)); - } -#line 5961 "util/configparser.c" - break; - - case 544: /* server_fast_server_num: VAR_FAST_SERVER_NUM STRING_ARG */ -#line 2733 "util/configparser.y" - { - OUTYY(("P(server_fast_server_num:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) <= 0) - yyerror("number expected"); - else cfg_parser->cfg->fast_server_num = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5973 "util/configparser.c" - break; - - case 545: /* server_fast_server_permil: VAR_FAST_SERVER_PERMIL STRING_ARG */ -#line 2742 "util/configparser.y" - { - OUTYY(("P(server_fast_server_permil:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->fast_server_permil = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 5985 "util/configparser.c" - break; - - case 546: /* server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG */ -#line 2751 "util/configparser.y" - { - OUTYY(("P(server_qname_minimisation:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 5998 "util/configparser.c" - break; - - case 547: /* server_qname_minimisation_strict: VAR_QNAME_MINIMISATION_STRICT STRING_ARG */ -#line 2761 "util/configparser.y" - { - OUTYY(("P(server_qname_minimisation_strict:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation_strict = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6011 "util/configparser.c" - break; - - case 548: /* server_pad_responses: VAR_PAD_RESPONSES STRING_ARG */ -#line 2771 "util/configparser.y" - { - OUTYY(("P(server_pad_responses:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->pad_responses = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6024 "util/configparser.c" - break; - - case 549: /* server_pad_responses_block_size: VAR_PAD_RESPONSES_BLOCK_SIZE STRING_ARG */ -#line 2781 "util/configparser.y" - { - OUTYY(("P(server_pad_responses_block_size:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->pad_responses_block_size = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 6036 "util/configparser.c" - break; - - case 550: /* server_pad_queries: VAR_PAD_QUERIES STRING_ARG */ -#line 2790 "util/configparser.y" - { - OUTYY(("P(server_pad_queries:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->pad_queries = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6049 "util/configparser.c" - break; - - case 551: /* server_pad_queries_block_size: VAR_PAD_QUERIES_BLOCK_SIZE STRING_ARG */ -#line 2800 "util/configparser.y" - { - OUTYY(("P(server_pad_queries_block_size:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("number expected"); - else cfg_parser->cfg->pad_queries_block_size = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 6061 "util/configparser.c" - break; - - case 552: /* server_ipsecmod_enabled: VAR_IPSECMOD_ENABLED STRING_ARG */ -#line 2809 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_enabled:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_enabled = (strcmp((yyvsp[0].str), "yes")==0); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 6077 "util/configparser.c" - break; - - case 553: /* server_ipsecmod_ignore_bogus: VAR_IPSECMOD_IGNORE_BOGUS STRING_ARG */ -#line 2822 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_ignore_bogus:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_ignore_bogus = (strcmp((yyvsp[0].str), "yes")==0); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 6093 "util/configparser.c" - break; - - case 554: /* server_ipsecmod_hook: VAR_IPSECMOD_HOOK STRING_ARG */ -#line 2835 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_hook:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->ipsecmod_hook); - cfg_parser->cfg->ipsecmod_hook = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 6108 "util/configparser.c" - break; - - case 555: /* server_ipsecmod_max_ttl: VAR_IPSECMOD_MAX_TTL STRING_ARG */ -#line 2847 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_max_ttl:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ipsecmod_max_ttl = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 6125 "util/configparser.c" - break; - - case 556: /* server_ipsecmod_whitelist: VAR_IPSECMOD_WHITELIST STRING_ARG */ -#line 2861 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_whitelist:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->ipsecmod_whitelist, (yyvsp[0].str))) - yyerror("out of memory"); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 6140 "util/configparser.c" - break; - - case 557: /* server_ipsecmod_strict: VAR_IPSECMOD_STRICT STRING_ARG */ -#line 2873 "util/configparser.y" - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_strict:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_strict = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 6157 "util/configparser.c" - break; - - case 558: /* server_edns_client_string: VAR_EDNS_CLIENT_STRING STRING_ARG STRING_ARG */ -#line 2887 "util/configparser.y" - { - OUTYY(("P(server_edns_client_string:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(!cfg_str2list_insert( - &cfg_parser->cfg->edns_client_strings, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding " - "edns-client-string"); - } -#line 6169 "util/configparser.c" - break; - - case 559: /* server_edns_client_string_opcode: VAR_EDNS_CLIENT_STRING_OPCODE STRING_ARG */ -#line 2896 "util/configparser.y" - { - OUTYY(("P(edns_client_string_opcode:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0 && strcmp((yyvsp[0].str), "0") != 0) - yyerror("option code expected"); - else if(atoi((yyvsp[0].str)) > 65535 || atoi((yyvsp[0].str)) < 0) - yyerror("option code must be in interval [0, 65535]"); - else cfg_parser->cfg->edns_client_string_opcode = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 6183 "util/configparser.c" - break; - - case 560: /* server_ede: VAR_EDE STRING_ARG */ -#line 2907 "util/configparser.y" - { - OUTYY(("P(server_ede:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ede = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6195 "util/configparser.c" - break; - - case 561: /* server_proxy_protocol_port: VAR_PROXY_PROTOCOL_PORT STRING_ARG */ -#line 2916 "util/configparser.y" - { - OUTYY(("P(server_proxy_protocol_port:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->proxy_protocol_port, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6205 "util/configparser.c" - break; - - case 562: /* stub_name: VAR_NAME STRING_ARG */ -#line 2923 "util/configparser.y" - { - OUTYY(("P(name:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->stubs->name) - yyerror("stub name override, there must be one name " - "for one stub-zone"); - free(cfg_parser->cfg->stubs->name); - cfg_parser->cfg->stubs->name = (yyvsp[0].str); - } -#line 6218 "util/configparser.c" - break; - - case 563: /* stub_host: VAR_STUB_HOST STRING_ARG */ -#line 2933 "util/configparser.y" - { - OUTYY(("P(stub-host:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6228 "util/configparser.c" - break; - - case 564: /* stub_addr: VAR_STUB_ADDR STRING_ARG */ -#line 2940 "util/configparser.y" - { - OUTYY(("P(stub-addr:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6238 "util/configparser.c" - break; - - case 565: /* stub_first: VAR_STUB_FIRST STRING_ARG */ -#line 2947 "util/configparser.y" - { - OUTYY(("P(stub-first:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->isfirst=(strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6250 "util/configparser.c" - break; - - case 566: /* stub_no_cache: VAR_STUB_NO_CACHE STRING_ARG */ -#line 2956 "util/configparser.y" - { - OUTYY(("P(stub-no-cache:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->no_cache=(strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6262 "util/configparser.c" - break; - - case 567: /* stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG */ -#line 2965 "util/configparser.y" - { - OUTYY(("P(stub-ssl-upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->ssl_upstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6275 "util/configparser.c" - break; - - case 568: /* stub_tcp_upstream: VAR_STUB_TCP_UPSTREAM STRING_ARG */ -#line 2975 "util/configparser.y" - { - OUTYY(("P(stub-tcp-upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->tcp_upstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6288 "util/configparser.c" - break; - - case 569: /* stub_prime: VAR_STUB_PRIME STRING_ARG */ -#line 2985 "util/configparser.y" - { - OUTYY(("P(stub-prime:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->isprime = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6301 "util/configparser.c" - break; - - case 570: /* forward_name: VAR_NAME STRING_ARG */ -#line 2995 "util/configparser.y" - { - OUTYY(("P(name:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->forwards->name) - yyerror("forward name override, there must be one " - "name for one forward-zone"); - free(cfg_parser->cfg->forwards->name); - cfg_parser->cfg->forwards->name = (yyvsp[0].str); - } -#line 6314 "util/configparser.c" - break; - - case 571: /* forward_host: VAR_FORWARD_HOST STRING_ARG */ -#line 3005 "util/configparser.y" - { - OUTYY(("P(forward-host:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6324 "util/configparser.c" - break; - - case 572: /* forward_addr: VAR_FORWARD_ADDR STRING_ARG */ -#line 3012 "util/configparser.y" - { - OUTYY(("P(forward-addr:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6334 "util/configparser.c" - break; - - case 573: /* forward_first: VAR_FORWARD_FIRST STRING_ARG */ -#line 3019 "util/configparser.y" - { - OUTYY(("P(forward-first:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->isfirst=(strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6346 "util/configparser.c" - break; - - case 574: /* forward_no_cache: VAR_FORWARD_NO_CACHE STRING_ARG */ -#line 3028 "util/configparser.y" - { - OUTYY(("P(forward-no-cache:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->no_cache=(strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6358 "util/configparser.c" - break; - - case 575: /* forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG */ -#line 3037 "util/configparser.y" - { - OUTYY(("P(forward-ssl-upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->ssl_upstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6371 "util/configparser.c" - break; - - case 576: /* forward_tcp_upstream: VAR_FORWARD_TCP_UPSTREAM STRING_ARG */ -#line 3047 "util/configparser.y" - { - OUTYY(("P(forward-tcp-upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->tcp_upstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6384 "util/configparser.c" - break; - - case 577: /* auth_name: VAR_NAME STRING_ARG */ -#line 3057 "util/configparser.y" - { - OUTYY(("P(name:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->auths->name) - yyerror("auth name override, there must be one name " - "for one auth-zone"); - free(cfg_parser->cfg->auths->name); - cfg_parser->cfg->auths->name = (yyvsp[0].str); - } -#line 6397 "util/configparser.c" - break; - - case 578: /* auth_zonefile: VAR_ZONEFILE STRING_ARG */ -#line 3067 "util/configparser.y" - { - OUTYY(("P(zonefile:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->auths->zonefile); - cfg_parser->cfg->auths->zonefile = (yyvsp[0].str); - } -#line 6407 "util/configparser.c" - break; - - case 579: /* auth_master: VAR_MASTER STRING_ARG */ -#line 3074 "util/configparser.y" - { - OUTYY(("P(master:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->masters, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6417 "util/configparser.c" - break; - - case 580: /* auth_url: VAR_URL STRING_ARG */ -#line 3081 "util/configparser.y" - { - OUTYY(("P(url:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->urls, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6427 "util/configparser.c" - break; - - case 581: /* auth_allow_notify: VAR_ALLOW_NOTIFY STRING_ARG */ -#line 3088 "util/configparser.y" - { - OUTYY(("P(allow-notify:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->allow_notify, - (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6438 "util/configparser.c" - break; - - case 582: /* auth_zonemd_check: VAR_ZONEMD_CHECK STRING_ARG */ -#line 3096 "util/configparser.y" - { - OUTYY(("P(zonemd-check:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->zonemd_check = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6451 "util/configparser.c" - break; - - case 583: /* auth_zonemd_reject_absence: VAR_ZONEMD_REJECT_ABSENCE STRING_ARG */ -#line 3106 "util/configparser.y" - { - OUTYY(("P(zonemd-reject-absence:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->zonemd_reject_absence = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6464 "util/configparser.c" - break; - - case 584: /* auth_for_downstream: VAR_FOR_DOWNSTREAM STRING_ARG */ -#line 3116 "util/configparser.y" - { - OUTYY(("P(for-downstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->for_downstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6477 "util/configparser.c" - break; - - case 585: /* auth_for_upstream: VAR_FOR_UPSTREAM STRING_ARG */ -#line 3126 "util/configparser.y" - { - OUTYY(("P(for-upstream:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->for_upstream = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6490 "util/configparser.c" - break; - - case 586: /* auth_fallback_enabled: VAR_FALLBACK_ENABLED STRING_ARG */ -#line 3136 "util/configparser.y" - { - OUTYY(("P(fallback-enabled:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->fallback_enabled = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6503 "util/configparser.c" - break; - - case 587: /* view_name: VAR_NAME STRING_ARG */ -#line 3146 "util/configparser.y" - { - OUTYY(("P(name:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->views->name) - yyerror("view name override, there must be one " - "name for one view"); - free(cfg_parser->cfg->views->name); - cfg_parser->cfg->views->name = (yyvsp[0].str); - } -#line 6516 "util/configparser.c" - break; - - case 588: /* view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG */ -#line 3156 "util/configparser.y" - { - OUTYY(("P(view_local_zone:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "static")!=0 && strcmp((yyvsp[0].str), "deny")!=0 && - strcmp((yyvsp[0].str), "refuse")!=0 && strcmp((yyvsp[0].str), "redirect")!=0 && - strcmp((yyvsp[0].str), "transparent")!=0 && strcmp((yyvsp[0].str), "nodefault")!=0 - && strcmp((yyvsp[0].str), "typetransparent")!=0 - && strcmp((yyvsp[0].str), "always_transparent")!=0 - && strcmp((yyvsp[0].str), "always_refuse")!=0 - && strcmp((yyvsp[0].str), "always_nxdomain")!=0 - && strcmp((yyvsp[0].str), "always_nodata")!=0 - && strcmp((yyvsp[0].str), "always_deny")!=0 - && strcmp((yyvsp[0].str), "always_null")!=0 - && strcmp((yyvsp[0].str), "noview")!=0 - && strcmp((yyvsp[0].str), "inform")!=0 && strcmp((yyvsp[0].str), "inform_deny")!=0 - && strcmp((yyvsp[0].str), "inform_redirect") != 0 - && strcmp((yyvsp[0].str), "ipset") != 0) { - yyerror("local-zone type: expected static, deny, " - "refuse, redirect, transparent, " - "typetransparent, inform, inform_deny, " - "inform_redirect, always_transparent, " - "always_refuse, always_nxdomain, " - "always_nodata, always_deny, always_null, " - "noview, nodefault or ipset"); - free((yyvsp[-1].str)); - free((yyvsp[0].str)); - } else if(strcmp((yyvsp[0].str), "nodefault")==0) { - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_zones_nodefault, (yyvsp[-1].str))) - fatal_exit("out of memory adding local-zone"); - free((yyvsp[0].str)); -#ifdef USE_IPSET - } else if(strcmp((yyvsp[0].str), "ipset")==0) { - size_t len = strlen((yyvsp[-1].str)); - /* Make sure to add the trailing dot. - * These are str compared to domain names. */ - if((yyvsp[-1].str)[len-1] != '.') { - if(!((yyvsp[-1].str) = realloc((yyvsp[-1].str), len+2))) { - fatal_exit("out of memory adding local-zone"); - } - (yyvsp[-1].str)[len] = '.'; - (yyvsp[-1].str)[len+1] = 0; - } - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_zones_ipset, (yyvsp[-1].str))) - fatal_exit("out of memory adding local-zone"); - free((yyvsp[0].str)); -#endif - } else { - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->local_zones, - (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding local-zone"); - } - } -#line 6575 "util/configparser.c" - break; - - case 589: /* view_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG */ -#line 3212 "util/configparser.y" - { - OUTYY(("P(view_response_ip:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - validate_respip_action((yyvsp[0].str)); - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->respip_actions, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding per-view " - "response-ip action"); - } -#line 6588 "util/configparser.c" - break; - - case 590: /* view_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG */ -#line 3222 "util/configparser.y" - { - OUTYY(("P(view_response_ip_data:%s)\n", (yyvsp[-1].str))); - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->respip_data, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding response-ip-data"); - } -#line 6599 "util/configparser.c" - break; - - case 591: /* view_local_data: VAR_LOCAL_DATA STRING_ARG */ -#line 3230 "util/configparser.y" - { - OUTYY(("P(view_local_data:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->views->local_data, (yyvsp[0].str))) { - fatal_exit("out of memory adding local-data"); - } - } -#line 6610 "util/configparser.c" - break; - - case 592: /* view_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG */ -#line 3238 "util/configparser.y" - { - char* ptr; - OUTYY(("P(view_local_data_ptr:%s)\n", (yyvsp[0].str))); - ptr = cfg_ptr_reverse((yyvsp[0].str)); - free((yyvsp[0].str)); - if(ptr) { - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_data, ptr)) - fatal_exit("out of memory adding local-data"); - } else { - yyerror("local-data-ptr could not be reversed"); - } - } -#line 6628 "util/configparser.c" - break; - - case 593: /* view_first: VAR_VIEW_FIRST STRING_ARG */ -#line 3253 "util/configparser.y" - { - OUTYY(("P(view-first:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->views->isfirst=(strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6640 "util/configparser.c" - break; - - case 594: /* rcstart: VAR_REMOTE_CONTROL */ -#line 3262 "util/configparser.y" - { - OUTYY(("\nP(remote-control:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 6649 "util/configparser.c" - break; - - case 605: /* rc_control_enable: VAR_CONTROL_ENABLE STRING_ARG */ -#line 3274 "util/configparser.y" - { - OUTYY(("P(control_enable:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->remote_control_enable = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6662 "util/configparser.c" - break; - - case 606: /* rc_control_port: VAR_CONTROL_PORT STRING_ARG */ -#line 3284 "util/configparser.y" - { - OUTYY(("P(control_port:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("control port number expected"); - else cfg_parser->cfg->control_port = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 6674 "util/configparser.c" - break; - - case 607: /* rc_control_interface: VAR_CONTROL_INTERFACE STRING_ARG */ -#line 3293 "util/configparser.y" - { - OUTYY(("P(control_interface:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_append(&cfg_parser->cfg->control_ifs, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6684 "util/configparser.c" - break; - - case 608: /* rc_control_use_cert: VAR_CONTROL_USE_CERT STRING_ARG */ -#line 3300 "util/configparser.y" - { - OUTYY(("P(control_use_cert:%s)\n", (yyvsp[0].str))); - cfg_parser->cfg->control_use_cert = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6694 "util/configparser.c" - break; - - case 609: /* rc_server_key_file: VAR_SERVER_KEY_FILE STRING_ARG */ -#line 3307 "util/configparser.y" - { - OUTYY(("P(rc_server_key_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->server_key_file); - cfg_parser->cfg->server_key_file = (yyvsp[0].str); - } -#line 6704 "util/configparser.c" - break; - - case 610: /* rc_server_cert_file: VAR_SERVER_CERT_FILE STRING_ARG */ -#line 3314 "util/configparser.y" - { - OUTYY(("P(rc_server_cert_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->server_cert_file); - cfg_parser->cfg->server_cert_file = (yyvsp[0].str); - } -#line 6714 "util/configparser.c" - break; - - case 611: /* rc_control_key_file: VAR_CONTROL_KEY_FILE STRING_ARG */ -#line 3321 "util/configparser.y" - { - OUTYY(("P(rc_control_key_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->control_key_file); - cfg_parser->cfg->control_key_file = (yyvsp[0].str); - } -#line 6724 "util/configparser.c" - break; - - case 612: /* rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING_ARG */ -#line 3328 "util/configparser.y" - { - OUTYY(("P(rc_control_cert_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->control_cert_file); - cfg_parser->cfg->control_cert_file = (yyvsp[0].str); - } -#line 6734 "util/configparser.c" - break; - - case 613: /* dtstart: VAR_DNSTAP */ -#line 3335 "util/configparser.y" - { - OUTYY(("\nP(dnstap:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 6743 "util/configparser.c" - break; - - case 635: /* dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG */ -#line 3356 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_enable:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6755 "util/configparser.c" - break; - - case 636: /* dt_dnstap_bidirectional: VAR_DNSTAP_BIDIRECTIONAL STRING_ARG */ -#line 3365 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_bidirectional:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_bidirectional = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6768 "util/configparser.c" - break; - - case 637: /* dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG */ -#line 3375 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_socket_path:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_socket_path); - cfg_parser->cfg->dnstap_socket_path = (yyvsp[0].str); - } -#line 6778 "util/configparser.c" - break; - - case 638: /* dt_dnstap_ip: VAR_DNSTAP_IP STRING_ARG */ -#line 3382 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_ip:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_ip); - cfg_parser->cfg->dnstap_ip = (yyvsp[0].str); - } -#line 6788 "util/configparser.c" - break; - - case 639: /* dt_dnstap_tls: VAR_DNSTAP_TLS STRING_ARG */ -#line 3389 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_tls:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_tls = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6800 "util/configparser.c" - break; - - case 640: /* dt_dnstap_tls_server_name: VAR_DNSTAP_TLS_SERVER_NAME STRING_ARG */ -#line 3398 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_tls_server_name:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_tls_server_name); - cfg_parser->cfg->dnstap_tls_server_name = (yyvsp[0].str); - } -#line 6810 "util/configparser.c" - break; - - case 641: /* dt_dnstap_tls_cert_bundle: VAR_DNSTAP_TLS_CERT_BUNDLE STRING_ARG */ -#line 3405 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_tls_cert_bundle:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_tls_cert_bundle); - cfg_parser->cfg->dnstap_tls_cert_bundle = (yyvsp[0].str); - } -#line 6820 "util/configparser.c" - break; - - case 642: /* dt_dnstap_tls_client_key_file: VAR_DNSTAP_TLS_CLIENT_KEY_FILE STRING_ARG */ -#line 3412 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_tls_client_key_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_tls_client_key_file); - cfg_parser->cfg->dnstap_tls_client_key_file = (yyvsp[0].str); - } -#line 6830 "util/configparser.c" - break; - - case 643: /* dt_dnstap_tls_client_cert_file: VAR_DNSTAP_TLS_CLIENT_CERT_FILE STRING_ARG */ -#line 3419 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_tls_client_cert_file:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_tls_client_cert_file); - cfg_parser->cfg->dnstap_tls_client_cert_file = (yyvsp[0].str); - } -#line 6840 "util/configparser.c" - break; - - case 644: /* dt_dnstap_send_identity: VAR_DNSTAP_SEND_IDENTITY STRING_ARG */ -#line 3426 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_send_identity:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_send_identity = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6852 "util/configparser.c" - break; - - case 645: /* dt_dnstap_send_version: VAR_DNSTAP_SEND_VERSION STRING_ARG */ -#line 3435 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_send_version:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_send_version = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6864 "util/configparser.c" - break; - - case 646: /* dt_dnstap_identity: VAR_DNSTAP_IDENTITY STRING_ARG */ -#line 3444 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_identity:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_identity); - cfg_parser->cfg->dnstap_identity = (yyvsp[0].str); - } -#line 6874 "util/configparser.c" - break; - - case 647: /* dt_dnstap_version: VAR_DNSTAP_VERSION STRING_ARG */ -#line 3451 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_version:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnstap_version); - cfg_parser->cfg->dnstap_version = (yyvsp[0].str); - } -#line 6884 "util/configparser.c" - break; - - case 648: /* dt_dnstap_log_resolver_query_messages: VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES STRING_ARG */ -#line 3458 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_resolver_query_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_resolver_query_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6897 "util/configparser.c" - break; - - case 649: /* dt_dnstap_log_resolver_response_messages: VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES STRING_ARG */ -#line 3468 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_resolver_response_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_resolver_response_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6910 "util/configparser.c" - break; - - case 650: /* dt_dnstap_log_client_query_messages: VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES STRING_ARG */ -#line 3478 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_client_query_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_client_query_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6923 "util/configparser.c" - break; - - case 651: /* dt_dnstap_log_client_response_messages: VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES STRING_ARG */ -#line 3488 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_client_response_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_client_response_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6936 "util/configparser.c" - break; - - case 652: /* dt_dnstap_log_forwarder_query_messages: VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES STRING_ARG */ -#line 3498 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_forwarder_query_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_forwarder_query_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6949 "util/configparser.c" - break; - - case 653: /* dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES STRING_ARG */ -#line 3508 "util/configparser.y" - { - OUTYY(("P(dt_dnstap_log_forwarder_response_messages:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_forwarder_response_messages = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 6962 "util/configparser.c" - break; - - case 654: /* pythonstart: VAR_PYTHON */ -#line 3518 "util/configparser.y" - { - OUTYY(("\nP(python:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 6971 "util/configparser.c" - break; - - case 658: /* py_script: VAR_PYTHON_SCRIPT STRING_ARG */ -#line 3528 "util/configparser.y" - { - OUTYY(("P(python-script:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 6981 "util/configparser.c" - break; - - case 659: /* dynlibstart: VAR_DYNLIB */ -#line 3535 "util/configparser.y" - { - OUTYY(("\nP(dynlib:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 6990 "util/configparser.c" - break; - - case 663: /* dl_file: VAR_DYNLIB_FILE STRING_ARG */ -#line 3545 "util/configparser.y" - { - OUTYY(("P(dynlib-file:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, (yyvsp[0].str))) - yyerror("out of memory"); - } -#line 7000 "util/configparser.c" - break; - - case 664: /* server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG */ -#line 3552 "util/configparser.y" - { - OUTYY(("P(disable_dnssec_lame_check:%s)\n", (yyvsp[0].str))); - if (strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->disable_dnssec_lame_check = - (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 7013 "util/configparser.c" - break; - - case 665: /* server_log_identity: VAR_LOG_IDENTITY STRING_ARG */ -#line 3562 "util/configparser.y" - { - OUTYY(("P(server_log_identity:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->log_identity); - cfg_parser->cfg->log_identity = (yyvsp[0].str); - } -#line 7023 "util/configparser.c" - break; - - case 666: /* server_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG */ -#line 3569 "util/configparser.y" - { - OUTYY(("P(server_response_ip:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - validate_respip_action((yyvsp[0].str)); - if(!cfg_str2list_insert(&cfg_parser->cfg->respip_actions, - (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding response-ip"); - } -#line 7035 "util/configparser.c" - break; - - case 667: /* server_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG */ -#line 3578 "util/configparser.y" - { - OUTYY(("P(server_response_ip_data:%s)\n", (yyvsp[-1].str))); - if(!cfg_str2list_insert(&cfg_parser->cfg->respip_data, - (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding response-ip-data"); - } -#line 7046 "util/configparser.c" - break; - - case 668: /* dnscstart: VAR_DNSCRYPT */ -#line 3586 "util/configparser.y" - { - OUTYY(("\nP(dnscrypt:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 7055 "util/configparser.c" - break; - - case 681: /* dnsc_dnscrypt_enable: VAR_DNSCRYPT_ENABLE STRING_ARG */ -#line 3603 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_enable:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnscrypt = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 7067 "util/configparser.c" - break; - - case 682: /* dnsc_dnscrypt_port: VAR_DNSCRYPT_PORT STRING_ARG */ -#line 3612 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_port:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->dnscrypt_port = atoi((yyvsp[0].str)); - free((yyvsp[0].str)); - } -#line 7079 "util/configparser.c" - break; - - case 683: /* dnsc_dnscrypt_provider: VAR_DNSCRYPT_PROVIDER STRING_ARG */ -#line 3621 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_provider:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->dnscrypt_provider); - cfg_parser->cfg->dnscrypt_provider = (yyvsp[0].str); - } -#line 7089 "util/configparser.c" - break; - - case 684: /* dnsc_dnscrypt_provider_cert: VAR_DNSCRYPT_PROVIDER_CERT STRING_ARG */ -#line 3628 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_provider_cert:%s)\n", (yyvsp[0].str))); - if(cfg_strlist_find(cfg_parser->cfg->dnscrypt_provider_cert, (yyvsp[0].str))) - log_warn("dnscrypt-provider-cert %s is a duplicate", (yyvsp[0].str)); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_provider_cert, (yyvsp[0].str))) - fatal_exit("out of memory adding dnscrypt-provider-cert"); - } -#line 7101 "util/configparser.c" - break; - - case 685: /* dnsc_dnscrypt_provider_cert_rotated: VAR_DNSCRYPT_PROVIDER_CERT_ROTATED STRING_ARG */ -#line 3637 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_provider_cert_rotated:%s)\n", (yyvsp[0].str))); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_provider_cert_rotated, (yyvsp[0].str))) - fatal_exit("out of memory adding dnscrypt-provider-cert-rotated"); - } -#line 7111 "util/configparser.c" - break; - - case 686: /* dnsc_dnscrypt_secret_key: VAR_DNSCRYPT_SECRET_KEY STRING_ARG */ -#line 3644 "util/configparser.y" - { - OUTYY(("P(dnsc_dnscrypt_secret_key:%s)\n", (yyvsp[0].str))); - if(cfg_strlist_find(cfg_parser->cfg->dnscrypt_secret_key, (yyvsp[0].str))) - log_warn("dnscrypt-secret-key: %s is a duplicate", (yyvsp[0].str)); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_secret_key, (yyvsp[0].str))) - fatal_exit("out of memory adding dnscrypt-secret-key"); - } -#line 7123 "util/configparser.c" - break; - - case 687: /* dnsc_dnscrypt_shared_secret_cache_size: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE STRING_ARG */ -#line 3653 "util/configparser.y" - { - OUTYY(("P(dnscrypt_shared_secret_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->dnscrypt_shared_secret_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 7134 "util/configparser.c" - break; - - case 688: /* dnsc_dnscrypt_shared_secret_cache_slabs: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS STRING_ARG */ -#line 3661 "util/configparser.y" - { - OUTYY(("P(dnscrypt_shared_secret_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 7150 "util/configparser.c" - break; - - case 689: /* dnsc_dnscrypt_nonce_cache_size: VAR_DNSCRYPT_NONCE_CACHE_SIZE STRING_ARG */ -#line 3674 "util/configparser.y" - { - OUTYY(("P(dnscrypt_nonce_cache_size:%s)\n", (yyvsp[0].str))); - if(!cfg_parse_memsize((yyvsp[0].str), &cfg_parser->cfg->dnscrypt_nonce_cache_size)) - yyerror("memory size expected"); - free((yyvsp[0].str)); - } -#line 7161 "util/configparser.c" - break; - - case 690: /* dnsc_dnscrypt_nonce_cache_slabs: VAR_DNSCRYPT_NONCE_CACHE_SLABS STRING_ARG */ -#line 3682 "util/configparser.y" - { - OUTYY(("P(dnscrypt_nonce_cache_slabs:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->dnscrypt_nonce_cache_slabs = atoi((yyvsp[0].str)); - if(!is_pow2(cfg_parser->cfg->dnscrypt_nonce_cache_slabs)) - yyerror("must be a power of 2"); - } - free((yyvsp[0].str)); - } -#line 7177 "util/configparser.c" - break; - - case 691: /* cachedbstart: VAR_CACHEDB */ -#line 3695 "util/configparser.y" - { - OUTYY(("\nP(cachedb:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 7186 "util/configparser.c" - break; - - case 702: /* cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG */ -#line 3707 "util/configparser.y" - { - #ifdef USE_CACHEDB - OUTYY(("P(backend:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->cachedb_backend); - cfg_parser->cfg->cachedb_backend = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without cachedb, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7201 "util/configparser.c" - break; - - case 703: /* cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG */ -#line 3719 "util/configparser.y" - { - #ifdef USE_CACHEDB - OUTYY(("P(secret-seed:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->cachedb_secret); - cfg_parser->cfg->cachedb_secret = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without cachedb, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7216 "util/configparser.c" - break; - - case 704: /* redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG */ -#line 3731 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_host:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->redis_server_host); - cfg_parser->cfg->redis_server_host = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7231 "util/configparser.c" - break; - - case 705: /* redis_server_port: VAR_CACHEDB_REDISPORT STRING_ARG */ -#line 3743 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - int port; - OUTYY(("P(redis_server_port:%s)\n", (yyvsp[0].str))); - port = atoi((yyvsp[0].str)); - if(port == 0 || port < 0 || port > 65535) - yyerror("valid redis server port number expected"); - else cfg_parser->cfg->redis_server_port = port; - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 7249 "util/configparser.c" - break; - - case 706: /* redis_server_path: VAR_CACHEDB_REDISPATH STRING_ARG */ -#line 3758 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_path:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->redis_server_path); - cfg_parser->cfg->redis_server_path = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7264 "util/configparser.c" - break; - - case 707: /* redis_server_password: VAR_CACHEDB_REDISPASSWORD STRING_ARG */ -#line 3770 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_password:%s)\n", (yyvsp[0].str))); - free(cfg_parser->cfg->redis_server_password); - cfg_parser->cfg->redis_server_password = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7279 "util/configparser.c" - break; - - case 708: /* redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG */ -#line 3782 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_timeout:%s)\n", (yyvsp[0].str))); - if(atoi((yyvsp[0].str)) == 0) - yyerror("redis timeout value expected"); - else cfg_parser->cfg->redis_timeout = atoi((yyvsp[0].str)); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 7295 "util/configparser.c" - break; - - case 709: /* redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG */ -#line 3795 "util/configparser.y" - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_expire_records:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->redis_expire_records = (strcmp((yyvsp[0].str), "yes")==0); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free((yyvsp[0].str)); - } -#line 7311 "util/configparser.c" - break; - - case 710: /* server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG */ -#line 3808 "util/configparser.y" - { - OUTYY(("P(server_tcp_connection_limit:%s %s)\n", (yyvsp[-1].str), (yyvsp[0].str))); - if (atoi((yyvsp[0].str)) < 0) - yyerror("positive number expected"); - else { - if(!cfg_str2list_insert(&cfg_parser->cfg->tcp_connection_limits, (yyvsp[-1].str), (yyvsp[0].str))) - fatal_exit("out of memory adding tcp connection limit"); - } - } -#line 7325 "util/configparser.c" - break; - - case 711: /* server_answer_cookie: VAR_ANSWER_COOKIE STRING_ARG */ -#line 3819 "util/configparser.y" - { - OUTYY(("P(server_answer_cookie:%s)\n", (yyvsp[0].str))); - if(strcmp((yyvsp[0].str), "yes") != 0 && strcmp((yyvsp[0].str), "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_answer_cookie = (strcmp((yyvsp[0].str), "yes")==0); - free((yyvsp[0].str)); - } -#line 7337 "util/configparser.c" - break; - - case 712: /* server_cookie_secret: VAR_COOKIE_SECRET STRING_ARG */ -#line 3828 "util/configparser.y" - { - uint8_t secret[32]; - size_t secret_len = sizeof(secret); - - OUTYY(("P(server_cookie_secret:%s)\n", (yyvsp[0].str))); - if(sldns_str2wire_hex_buf((yyvsp[0].str), secret, &secret_len) - || (secret_len != 16)) - yyerror("expected 128 bit hex string"); - else { - cfg_parser->cfg->cookie_secret_len = secret_len; - memcpy(cfg_parser->cfg->cookie_secret, secret, sizeof(secret)); - } - free((yyvsp[0].str)); - } -#line 7356 "util/configparser.c" - break; - - case 713: /* ipsetstart: VAR_IPSET */ -#line 3844 "util/configparser.y" - { - OUTYY(("\nP(ipset:)\n")); - cfg_parser->started_toplevel = 1; - } -#line 7365 "util/configparser.c" - break; - - case 718: /* ipset_name_v4: VAR_IPSET_NAME_V4 STRING_ARG */ -#line 3854 "util/configparser.y" - { - #ifdef USE_IPSET - OUTYY(("P(name-v4:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->ipset_name_v4) - yyerror("ipset name v4 override, there must be one " - "name for ip v4"); - free(cfg_parser->cfg->ipset_name_v4); - cfg_parser->cfg->ipset_name_v4 = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without ipset, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7383 "util/configparser.c" - break; - - case 719: /* ipset_name_v6: VAR_IPSET_NAME_V6 STRING_ARG */ -#line 3869 "util/configparser.y" - { - #ifdef USE_IPSET - OUTYY(("P(name-v6:%s)\n", (yyvsp[0].str))); - if(cfg_parser->cfg->ipset_name_v6) - yyerror("ipset name v6 override, there must be one " - "name for ip v6"); - free(cfg_parser->cfg->ipset_name_v6); - cfg_parser->cfg->ipset_name_v6 = (yyvsp[0].str); - #else - OUTYY(("P(Compiled without ipset, ignoring)\n")); - free((yyvsp[0].str)); - #endif - } -#line 7401 "util/configparser.c" - break; - - -#line 7405 "util/configparser.c" - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - yyerror (YY_("syntax error")); - } - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - /* Pop stack until we find a state that shifts the error token. */ - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYSYMBOL_YYerror; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - - -#if !defined yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - goto yyreturn; -#endif - - -/*-------------------------------------------------------. -| yyreturn -- parsing is finished, clean up and return. | -`-------------------------------------------------------*/ -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - - return yyresult; -} - -#line 3883 "util/configparser.y" - - -/* parse helper routines could be here */ -static void -validate_respip_action(const char* action) -{ - if(strcmp(action, "deny")!=0 && - strcmp(action, "redirect")!=0 && - strcmp(action, "inform")!=0 && - strcmp(action, "inform_deny")!=0 && - strcmp(action, "always_transparent")!=0 && - strcmp(action, "always_refuse")!=0 && - strcmp(action, "always_nxdomain")!=0) - { - yyerror("response-ip action: expected deny, redirect, " - "inform, inform_deny, always_transparent, " - "always_refuse or always_nxdomain"); - } -} - -static void -validate_acl_action(const char* action) -{ - if(strcmp(action, "deny")!=0 && - strcmp(action, "refuse")!=0 && - strcmp(action, "deny_non_local")!=0 && - strcmp(action, "refuse_non_local")!=0 && - strcmp(action, "allow_setrd")!=0 && - strcmp(action, "allow")!=0 && - strcmp(action, "allow_snoop")!=0 && - strcmp(action, "allow_cookie")!=0) - { - yyerror("expected deny, refuse, deny_non_local, " - "refuse_non_local, allow, allow_setrd, " - "allow_snoop or allow_cookie as access control action"); - } -} diff --git a/crates/libunbound-sys/unbound/util/configparser.h b/crates/libunbound-sys/unbound/util/configparser.h deleted file mode 100644 index 338dfbb7..00000000 --- a/crates/libunbound-sys/unbound/util/configparser.h +++ /dev/null @@ -1,773 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.7.6. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -#ifndef YY_YY_UTIL_CONFIGPARSER_H_INCLUDED -# define YY_YY_UTIL_CONFIGPARSER_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - SPACE = 258, /* SPACE */ - LETTER = 259, /* LETTER */ - NEWLINE = 260, /* NEWLINE */ - COMMENT = 261, /* COMMENT */ - COLON = 262, /* COLON */ - ANY = 263, /* ANY */ - ZONESTR = 264, /* ZONESTR */ - STRING_ARG = 265, /* STRING_ARG */ - VAR_FORCE_TOPLEVEL = 266, /* VAR_FORCE_TOPLEVEL */ - VAR_SERVER = 267, /* VAR_SERVER */ - VAR_VERBOSITY = 268, /* VAR_VERBOSITY */ - VAR_NUM_THREADS = 269, /* VAR_NUM_THREADS */ - VAR_PORT = 270, /* VAR_PORT */ - VAR_OUTGOING_RANGE = 271, /* VAR_OUTGOING_RANGE */ - VAR_INTERFACE = 272, /* VAR_INTERFACE */ - VAR_PREFER_IP4 = 273, /* VAR_PREFER_IP4 */ - VAR_DO_IP4 = 274, /* VAR_DO_IP4 */ - VAR_DO_IP6 = 275, /* VAR_DO_IP6 */ - VAR_DO_NAT64 = 276, /* VAR_DO_NAT64 */ - VAR_PREFER_IP6 = 277, /* VAR_PREFER_IP6 */ - VAR_DO_UDP = 278, /* VAR_DO_UDP */ - VAR_DO_TCP = 279, /* VAR_DO_TCP */ - VAR_TCP_MSS = 280, /* VAR_TCP_MSS */ - VAR_OUTGOING_TCP_MSS = 281, /* VAR_OUTGOING_TCP_MSS */ - VAR_TCP_IDLE_TIMEOUT = 282, /* VAR_TCP_IDLE_TIMEOUT */ - VAR_EDNS_TCP_KEEPALIVE = 283, /* VAR_EDNS_TCP_KEEPALIVE */ - VAR_EDNS_TCP_KEEPALIVE_TIMEOUT = 284, /* VAR_EDNS_TCP_KEEPALIVE_TIMEOUT */ - VAR_SOCK_QUEUE_TIMEOUT = 285, /* VAR_SOCK_QUEUE_TIMEOUT */ - VAR_CHROOT = 286, /* VAR_CHROOT */ - VAR_USERNAME = 287, /* VAR_USERNAME */ - VAR_DIRECTORY = 288, /* VAR_DIRECTORY */ - VAR_LOGFILE = 289, /* VAR_LOGFILE */ - VAR_PIDFILE = 290, /* VAR_PIDFILE */ - VAR_MSG_CACHE_SIZE = 291, /* VAR_MSG_CACHE_SIZE */ - VAR_MSG_CACHE_SLABS = 292, /* VAR_MSG_CACHE_SLABS */ - VAR_NUM_QUERIES_PER_THREAD = 293, /* VAR_NUM_QUERIES_PER_THREAD */ - VAR_RRSET_CACHE_SIZE = 294, /* VAR_RRSET_CACHE_SIZE */ - VAR_RRSET_CACHE_SLABS = 295, /* VAR_RRSET_CACHE_SLABS */ - VAR_OUTGOING_NUM_TCP = 296, /* VAR_OUTGOING_NUM_TCP */ - VAR_INFRA_HOST_TTL = 297, /* VAR_INFRA_HOST_TTL */ - VAR_INFRA_LAME_TTL = 298, /* VAR_INFRA_LAME_TTL */ - VAR_INFRA_CACHE_SLABS = 299, /* VAR_INFRA_CACHE_SLABS */ - VAR_INFRA_CACHE_NUMHOSTS = 300, /* VAR_INFRA_CACHE_NUMHOSTS */ - VAR_INFRA_CACHE_LAME_SIZE = 301, /* VAR_INFRA_CACHE_LAME_SIZE */ - VAR_NAME = 302, /* VAR_NAME */ - VAR_STUB_ZONE = 303, /* VAR_STUB_ZONE */ - VAR_STUB_HOST = 304, /* VAR_STUB_HOST */ - VAR_STUB_ADDR = 305, /* VAR_STUB_ADDR */ - VAR_TARGET_FETCH_POLICY = 306, /* VAR_TARGET_FETCH_POLICY */ - VAR_HARDEN_SHORT_BUFSIZE = 307, /* VAR_HARDEN_SHORT_BUFSIZE */ - VAR_HARDEN_LARGE_QUERIES = 308, /* VAR_HARDEN_LARGE_QUERIES */ - VAR_FORWARD_ZONE = 309, /* VAR_FORWARD_ZONE */ - VAR_FORWARD_HOST = 310, /* VAR_FORWARD_HOST */ - VAR_FORWARD_ADDR = 311, /* VAR_FORWARD_ADDR */ - VAR_DO_NOT_QUERY_ADDRESS = 312, /* VAR_DO_NOT_QUERY_ADDRESS */ - VAR_HIDE_IDENTITY = 313, /* VAR_HIDE_IDENTITY */ - VAR_HIDE_VERSION = 314, /* VAR_HIDE_VERSION */ - VAR_IDENTITY = 315, /* VAR_IDENTITY */ - VAR_VERSION = 316, /* VAR_VERSION */ - VAR_HARDEN_GLUE = 317, /* VAR_HARDEN_GLUE */ - VAR_MODULE_CONF = 318, /* VAR_MODULE_CONF */ - VAR_TRUST_ANCHOR_FILE = 319, /* VAR_TRUST_ANCHOR_FILE */ - VAR_TRUST_ANCHOR = 320, /* VAR_TRUST_ANCHOR */ - VAR_VAL_OVERRIDE_DATE = 321, /* VAR_VAL_OVERRIDE_DATE */ - VAR_BOGUS_TTL = 322, /* VAR_BOGUS_TTL */ - VAR_VAL_CLEAN_ADDITIONAL = 323, /* VAR_VAL_CLEAN_ADDITIONAL */ - VAR_VAL_PERMISSIVE_MODE = 324, /* VAR_VAL_PERMISSIVE_MODE */ - VAR_INCOMING_NUM_TCP = 325, /* VAR_INCOMING_NUM_TCP */ - VAR_MSG_BUFFER_SIZE = 326, /* VAR_MSG_BUFFER_SIZE */ - VAR_KEY_CACHE_SIZE = 327, /* VAR_KEY_CACHE_SIZE */ - VAR_KEY_CACHE_SLABS = 328, /* VAR_KEY_CACHE_SLABS */ - VAR_TRUSTED_KEYS_FILE = 329, /* VAR_TRUSTED_KEYS_FILE */ - VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 330, /* VAR_VAL_NSEC3_KEYSIZE_ITERATIONS */ - VAR_USE_SYSLOG = 331, /* VAR_USE_SYSLOG */ - VAR_OUTGOING_INTERFACE = 332, /* VAR_OUTGOING_INTERFACE */ - VAR_ROOT_HINTS = 333, /* VAR_ROOT_HINTS */ - VAR_DO_NOT_QUERY_LOCALHOST = 334, /* VAR_DO_NOT_QUERY_LOCALHOST */ - VAR_CACHE_MAX_TTL = 335, /* VAR_CACHE_MAX_TTL */ - VAR_HARDEN_DNSSEC_STRIPPED = 336, /* VAR_HARDEN_DNSSEC_STRIPPED */ - VAR_ACCESS_CONTROL = 337, /* VAR_ACCESS_CONTROL */ - VAR_LOCAL_ZONE = 338, /* VAR_LOCAL_ZONE */ - VAR_LOCAL_DATA = 339, /* VAR_LOCAL_DATA */ - VAR_INTERFACE_AUTOMATIC = 340, /* VAR_INTERFACE_AUTOMATIC */ - VAR_STATISTICS_INTERVAL = 341, /* VAR_STATISTICS_INTERVAL */ - VAR_DO_DAEMONIZE = 342, /* VAR_DO_DAEMONIZE */ - VAR_USE_CAPS_FOR_ID = 343, /* VAR_USE_CAPS_FOR_ID */ - VAR_STATISTICS_CUMULATIVE = 344, /* VAR_STATISTICS_CUMULATIVE */ - VAR_OUTGOING_PORT_PERMIT = 345, /* VAR_OUTGOING_PORT_PERMIT */ - VAR_OUTGOING_PORT_AVOID = 346, /* VAR_OUTGOING_PORT_AVOID */ - VAR_DLV_ANCHOR_FILE = 347, /* VAR_DLV_ANCHOR_FILE */ - VAR_DLV_ANCHOR = 348, /* VAR_DLV_ANCHOR */ - VAR_NEG_CACHE_SIZE = 349, /* VAR_NEG_CACHE_SIZE */ - VAR_HARDEN_REFERRAL_PATH = 350, /* VAR_HARDEN_REFERRAL_PATH */ - VAR_PRIVATE_ADDRESS = 351, /* VAR_PRIVATE_ADDRESS */ - VAR_PRIVATE_DOMAIN = 352, /* VAR_PRIVATE_DOMAIN */ - VAR_REMOTE_CONTROL = 353, /* VAR_REMOTE_CONTROL */ - VAR_CONTROL_ENABLE = 354, /* VAR_CONTROL_ENABLE */ - VAR_CONTROL_INTERFACE = 355, /* VAR_CONTROL_INTERFACE */ - VAR_CONTROL_PORT = 356, /* VAR_CONTROL_PORT */ - VAR_SERVER_KEY_FILE = 357, /* VAR_SERVER_KEY_FILE */ - VAR_SERVER_CERT_FILE = 358, /* VAR_SERVER_CERT_FILE */ - VAR_CONTROL_KEY_FILE = 359, /* VAR_CONTROL_KEY_FILE */ - VAR_CONTROL_CERT_FILE = 360, /* VAR_CONTROL_CERT_FILE */ - VAR_CONTROL_USE_CERT = 361, /* VAR_CONTROL_USE_CERT */ - VAR_TCP_REUSE_TIMEOUT = 362, /* VAR_TCP_REUSE_TIMEOUT */ - VAR_MAX_REUSE_TCP_QUERIES = 363, /* VAR_MAX_REUSE_TCP_QUERIES */ - VAR_EXTENDED_STATISTICS = 364, /* VAR_EXTENDED_STATISTICS */ - VAR_LOCAL_DATA_PTR = 365, /* VAR_LOCAL_DATA_PTR */ - VAR_JOSTLE_TIMEOUT = 366, /* VAR_JOSTLE_TIMEOUT */ - VAR_STUB_PRIME = 367, /* VAR_STUB_PRIME */ - VAR_UNWANTED_REPLY_THRESHOLD = 368, /* VAR_UNWANTED_REPLY_THRESHOLD */ - VAR_LOG_TIME_ASCII = 369, /* VAR_LOG_TIME_ASCII */ - VAR_DOMAIN_INSECURE = 370, /* VAR_DOMAIN_INSECURE */ - VAR_PYTHON = 371, /* VAR_PYTHON */ - VAR_PYTHON_SCRIPT = 372, /* VAR_PYTHON_SCRIPT */ - VAR_VAL_SIG_SKEW_MIN = 373, /* VAR_VAL_SIG_SKEW_MIN */ - VAR_VAL_SIG_SKEW_MAX = 374, /* VAR_VAL_SIG_SKEW_MAX */ - VAR_VAL_MAX_RESTART = 375, /* VAR_VAL_MAX_RESTART */ - VAR_CACHE_MIN_TTL = 376, /* VAR_CACHE_MIN_TTL */ - VAR_VAL_LOG_LEVEL = 377, /* VAR_VAL_LOG_LEVEL */ - VAR_AUTO_TRUST_ANCHOR_FILE = 378, /* VAR_AUTO_TRUST_ANCHOR_FILE */ - VAR_KEEP_MISSING = 379, /* VAR_KEEP_MISSING */ - VAR_ADD_HOLDDOWN = 380, /* VAR_ADD_HOLDDOWN */ - VAR_DEL_HOLDDOWN = 381, /* VAR_DEL_HOLDDOWN */ - VAR_SO_RCVBUF = 382, /* VAR_SO_RCVBUF */ - VAR_EDNS_BUFFER_SIZE = 383, /* VAR_EDNS_BUFFER_SIZE */ - VAR_PREFETCH = 384, /* VAR_PREFETCH */ - VAR_PREFETCH_KEY = 385, /* VAR_PREFETCH_KEY */ - VAR_SO_SNDBUF = 386, /* VAR_SO_SNDBUF */ - VAR_SO_REUSEPORT = 387, /* VAR_SO_REUSEPORT */ - VAR_HARDEN_BELOW_NXDOMAIN = 388, /* VAR_HARDEN_BELOW_NXDOMAIN */ - VAR_IGNORE_CD_FLAG = 389, /* VAR_IGNORE_CD_FLAG */ - VAR_LOG_QUERIES = 390, /* VAR_LOG_QUERIES */ - VAR_LOG_REPLIES = 391, /* VAR_LOG_REPLIES */ - VAR_LOG_LOCAL_ACTIONS = 392, /* VAR_LOG_LOCAL_ACTIONS */ - VAR_TCP_UPSTREAM = 393, /* VAR_TCP_UPSTREAM */ - VAR_SSL_UPSTREAM = 394, /* VAR_SSL_UPSTREAM */ - VAR_TCP_AUTH_QUERY_TIMEOUT = 395, /* VAR_TCP_AUTH_QUERY_TIMEOUT */ - VAR_SSL_SERVICE_KEY = 396, /* VAR_SSL_SERVICE_KEY */ - VAR_SSL_SERVICE_PEM = 397, /* VAR_SSL_SERVICE_PEM */ - VAR_SSL_PORT = 398, /* VAR_SSL_PORT */ - VAR_FORWARD_FIRST = 399, /* VAR_FORWARD_FIRST */ - VAR_STUB_SSL_UPSTREAM = 400, /* VAR_STUB_SSL_UPSTREAM */ - VAR_FORWARD_SSL_UPSTREAM = 401, /* VAR_FORWARD_SSL_UPSTREAM */ - VAR_TLS_CERT_BUNDLE = 402, /* VAR_TLS_CERT_BUNDLE */ - VAR_STUB_TCP_UPSTREAM = 403, /* VAR_STUB_TCP_UPSTREAM */ - VAR_FORWARD_TCP_UPSTREAM = 404, /* VAR_FORWARD_TCP_UPSTREAM */ - VAR_HTTPS_PORT = 405, /* VAR_HTTPS_PORT */ - VAR_HTTP_ENDPOINT = 406, /* VAR_HTTP_ENDPOINT */ - VAR_HTTP_MAX_STREAMS = 407, /* VAR_HTTP_MAX_STREAMS */ - VAR_HTTP_QUERY_BUFFER_SIZE = 408, /* VAR_HTTP_QUERY_BUFFER_SIZE */ - VAR_HTTP_RESPONSE_BUFFER_SIZE = 409, /* VAR_HTTP_RESPONSE_BUFFER_SIZE */ - VAR_HTTP_NODELAY = 410, /* VAR_HTTP_NODELAY */ - VAR_HTTP_NOTLS_DOWNSTREAM = 411, /* VAR_HTTP_NOTLS_DOWNSTREAM */ - VAR_STUB_FIRST = 412, /* VAR_STUB_FIRST */ - VAR_MINIMAL_RESPONSES = 413, /* VAR_MINIMAL_RESPONSES */ - VAR_RRSET_ROUNDROBIN = 414, /* VAR_RRSET_ROUNDROBIN */ - VAR_MAX_UDP_SIZE = 415, /* VAR_MAX_UDP_SIZE */ - VAR_DELAY_CLOSE = 416, /* VAR_DELAY_CLOSE */ - VAR_UDP_CONNECT = 417, /* VAR_UDP_CONNECT */ - VAR_UNBLOCK_LAN_ZONES = 418, /* VAR_UNBLOCK_LAN_ZONES */ - VAR_INSECURE_LAN_ZONES = 419, /* VAR_INSECURE_LAN_ZONES */ - VAR_INFRA_CACHE_MIN_RTT = 420, /* VAR_INFRA_CACHE_MIN_RTT */ - VAR_INFRA_CACHE_MAX_RTT = 421, /* VAR_INFRA_CACHE_MAX_RTT */ - VAR_INFRA_KEEP_PROBING = 422, /* VAR_INFRA_KEEP_PROBING */ - VAR_DNS64_PREFIX = 423, /* VAR_DNS64_PREFIX */ - VAR_DNS64_SYNTHALL = 424, /* VAR_DNS64_SYNTHALL */ - VAR_DNS64_IGNORE_AAAA = 425, /* VAR_DNS64_IGNORE_AAAA */ - VAR_NAT64_PREFIX = 426, /* VAR_NAT64_PREFIX */ - VAR_DNSTAP = 427, /* VAR_DNSTAP */ - VAR_DNSTAP_ENABLE = 428, /* VAR_DNSTAP_ENABLE */ - VAR_DNSTAP_SOCKET_PATH = 429, /* VAR_DNSTAP_SOCKET_PATH */ - VAR_DNSTAP_IP = 430, /* VAR_DNSTAP_IP */ - VAR_DNSTAP_TLS = 431, /* VAR_DNSTAP_TLS */ - VAR_DNSTAP_TLS_SERVER_NAME = 432, /* VAR_DNSTAP_TLS_SERVER_NAME */ - VAR_DNSTAP_TLS_CERT_BUNDLE = 433, /* VAR_DNSTAP_TLS_CERT_BUNDLE */ - VAR_DNSTAP_TLS_CLIENT_KEY_FILE = 434, /* VAR_DNSTAP_TLS_CLIENT_KEY_FILE */ - VAR_DNSTAP_TLS_CLIENT_CERT_FILE = 435, /* VAR_DNSTAP_TLS_CLIENT_CERT_FILE */ - VAR_DNSTAP_SEND_IDENTITY = 436, /* VAR_DNSTAP_SEND_IDENTITY */ - VAR_DNSTAP_SEND_VERSION = 437, /* VAR_DNSTAP_SEND_VERSION */ - VAR_DNSTAP_BIDIRECTIONAL = 438, /* VAR_DNSTAP_BIDIRECTIONAL */ - VAR_DNSTAP_IDENTITY = 439, /* VAR_DNSTAP_IDENTITY */ - VAR_DNSTAP_VERSION = 440, /* VAR_DNSTAP_VERSION */ - VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES = 441, /* VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES */ - VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES = 442, /* VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES */ - VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES = 443, /* VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES */ - VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES = 444, /* VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES */ - VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES = 445, /* VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES */ - VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES = 446, /* VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES */ - VAR_RESPONSE_IP_TAG = 447, /* VAR_RESPONSE_IP_TAG */ - VAR_RESPONSE_IP = 448, /* VAR_RESPONSE_IP */ - VAR_RESPONSE_IP_DATA = 449, /* VAR_RESPONSE_IP_DATA */ - VAR_HARDEN_ALGO_DOWNGRADE = 450, /* VAR_HARDEN_ALGO_DOWNGRADE */ - VAR_IP_TRANSPARENT = 451, /* VAR_IP_TRANSPARENT */ - VAR_IP_DSCP = 452, /* VAR_IP_DSCP */ - VAR_DISABLE_DNSSEC_LAME_CHECK = 453, /* VAR_DISABLE_DNSSEC_LAME_CHECK */ - VAR_IP_RATELIMIT = 454, /* VAR_IP_RATELIMIT */ - VAR_IP_RATELIMIT_SLABS = 455, /* VAR_IP_RATELIMIT_SLABS */ - VAR_IP_RATELIMIT_SIZE = 456, /* VAR_IP_RATELIMIT_SIZE */ - VAR_RATELIMIT = 457, /* VAR_RATELIMIT */ - VAR_RATELIMIT_SLABS = 458, /* VAR_RATELIMIT_SLABS */ - VAR_RATELIMIT_SIZE = 459, /* VAR_RATELIMIT_SIZE */ - VAR_OUTBOUND_MSG_RETRY = 460, /* VAR_OUTBOUND_MSG_RETRY */ - VAR_MAX_SENT_COUNT = 461, /* VAR_MAX_SENT_COUNT */ - VAR_MAX_QUERY_RESTARTS = 462, /* VAR_MAX_QUERY_RESTARTS */ - VAR_RATELIMIT_FOR_DOMAIN = 463, /* VAR_RATELIMIT_FOR_DOMAIN */ - VAR_RATELIMIT_BELOW_DOMAIN = 464, /* VAR_RATELIMIT_BELOW_DOMAIN */ - VAR_IP_RATELIMIT_FACTOR = 465, /* VAR_IP_RATELIMIT_FACTOR */ - VAR_RATELIMIT_FACTOR = 466, /* VAR_RATELIMIT_FACTOR */ - VAR_IP_RATELIMIT_BACKOFF = 467, /* VAR_IP_RATELIMIT_BACKOFF */ - VAR_RATELIMIT_BACKOFF = 468, /* VAR_RATELIMIT_BACKOFF */ - VAR_SEND_CLIENT_SUBNET = 469, /* VAR_SEND_CLIENT_SUBNET */ - VAR_CLIENT_SUBNET_ZONE = 470, /* VAR_CLIENT_SUBNET_ZONE */ - VAR_CLIENT_SUBNET_ALWAYS_FORWARD = 471, /* VAR_CLIENT_SUBNET_ALWAYS_FORWARD */ - VAR_CLIENT_SUBNET_OPCODE = 472, /* VAR_CLIENT_SUBNET_OPCODE */ - VAR_MAX_CLIENT_SUBNET_IPV4 = 473, /* VAR_MAX_CLIENT_SUBNET_IPV4 */ - VAR_MAX_CLIENT_SUBNET_IPV6 = 474, /* VAR_MAX_CLIENT_SUBNET_IPV6 */ - VAR_MIN_CLIENT_SUBNET_IPV4 = 475, /* VAR_MIN_CLIENT_SUBNET_IPV4 */ - VAR_MIN_CLIENT_SUBNET_IPV6 = 476, /* VAR_MIN_CLIENT_SUBNET_IPV6 */ - VAR_MAX_ECS_TREE_SIZE_IPV4 = 477, /* VAR_MAX_ECS_TREE_SIZE_IPV4 */ - VAR_MAX_ECS_TREE_SIZE_IPV6 = 478, /* VAR_MAX_ECS_TREE_SIZE_IPV6 */ - VAR_CAPS_WHITELIST = 479, /* VAR_CAPS_WHITELIST */ - VAR_CACHE_MAX_NEGATIVE_TTL = 480, /* VAR_CACHE_MAX_NEGATIVE_TTL */ - VAR_PERMIT_SMALL_HOLDDOWN = 481, /* VAR_PERMIT_SMALL_HOLDDOWN */ - VAR_QNAME_MINIMISATION = 482, /* VAR_QNAME_MINIMISATION */ - VAR_QNAME_MINIMISATION_STRICT = 483, /* VAR_QNAME_MINIMISATION_STRICT */ - VAR_IP_FREEBIND = 484, /* VAR_IP_FREEBIND */ - VAR_DEFINE_TAG = 485, /* VAR_DEFINE_TAG */ - VAR_LOCAL_ZONE_TAG = 486, /* VAR_LOCAL_ZONE_TAG */ - VAR_ACCESS_CONTROL_TAG = 487, /* VAR_ACCESS_CONTROL_TAG */ - VAR_LOCAL_ZONE_OVERRIDE = 488, /* VAR_LOCAL_ZONE_OVERRIDE */ - VAR_ACCESS_CONTROL_TAG_ACTION = 489, /* VAR_ACCESS_CONTROL_TAG_ACTION */ - VAR_ACCESS_CONTROL_TAG_DATA = 490, /* VAR_ACCESS_CONTROL_TAG_DATA */ - VAR_VIEW = 491, /* VAR_VIEW */ - VAR_ACCESS_CONTROL_VIEW = 492, /* VAR_ACCESS_CONTROL_VIEW */ - VAR_VIEW_FIRST = 493, /* VAR_VIEW_FIRST */ - VAR_SERVE_EXPIRED = 494, /* VAR_SERVE_EXPIRED */ - VAR_SERVE_EXPIRED_TTL = 495, /* VAR_SERVE_EXPIRED_TTL */ - VAR_SERVE_EXPIRED_TTL_RESET = 496, /* VAR_SERVE_EXPIRED_TTL_RESET */ - VAR_SERVE_EXPIRED_REPLY_TTL = 497, /* VAR_SERVE_EXPIRED_REPLY_TTL */ - VAR_SERVE_EXPIRED_CLIENT_TIMEOUT = 498, /* VAR_SERVE_EXPIRED_CLIENT_TIMEOUT */ - VAR_EDE_SERVE_EXPIRED = 499, /* VAR_EDE_SERVE_EXPIRED */ - VAR_SERVE_ORIGINAL_TTL = 500, /* VAR_SERVE_ORIGINAL_TTL */ - VAR_FAKE_DSA = 501, /* VAR_FAKE_DSA */ - VAR_FAKE_SHA1 = 502, /* VAR_FAKE_SHA1 */ - VAR_LOG_IDENTITY = 503, /* VAR_LOG_IDENTITY */ - VAR_HIDE_TRUSTANCHOR = 504, /* VAR_HIDE_TRUSTANCHOR */ - VAR_HIDE_HTTP_USER_AGENT = 505, /* VAR_HIDE_HTTP_USER_AGENT */ - VAR_HTTP_USER_AGENT = 506, /* VAR_HTTP_USER_AGENT */ - VAR_TRUST_ANCHOR_SIGNALING = 507, /* VAR_TRUST_ANCHOR_SIGNALING */ - VAR_AGGRESSIVE_NSEC = 508, /* VAR_AGGRESSIVE_NSEC */ - VAR_USE_SYSTEMD = 509, /* VAR_USE_SYSTEMD */ - VAR_SHM_ENABLE = 510, /* VAR_SHM_ENABLE */ - VAR_SHM_KEY = 511, /* VAR_SHM_KEY */ - VAR_ROOT_KEY_SENTINEL = 512, /* VAR_ROOT_KEY_SENTINEL */ - VAR_DNSCRYPT = 513, /* VAR_DNSCRYPT */ - VAR_DNSCRYPT_ENABLE = 514, /* VAR_DNSCRYPT_ENABLE */ - VAR_DNSCRYPT_PORT = 515, /* VAR_DNSCRYPT_PORT */ - VAR_DNSCRYPT_PROVIDER = 516, /* VAR_DNSCRYPT_PROVIDER */ - VAR_DNSCRYPT_SECRET_KEY = 517, /* VAR_DNSCRYPT_SECRET_KEY */ - VAR_DNSCRYPT_PROVIDER_CERT = 518, /* VAR_DNSCRYPT_PROVIDER_CERT */ - VAR_DNSCRYPT_PROVIDER_CERT_ROTATED = 519, /* VAR_DNSCRYPT_PROVIDER_CERT_ROTATED */ - VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE = 520, /* VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE */ - VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS = 521, /* VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS */ - VAR_DNSCRYPT_NONCE_CACHE_SIZE = 522, /* VAR_DNSCRYPT_NONCE_CACHE_SIZE */ - VAR_DNSCRYPT_NONCE_CACHE_SLABS = 523, /* VAR_DNSCRYPT_NONCE_CACHE_SLABS */ - VAR_PAD_RESPONSES = 524, /* VAR_PAD_RESPONSES */ - VAR_PAD_RESPONSES_BLOCK_SIZE = 525, /* VAR_PAD_RESPONSES_BLOCK_SIZE */ - VAR_PAD_QUERIES = 526, /* VAR_PAD_QUERIES */ - VAR_PAD_QUERIES_BLOCK_SIZE = 527, /* VAR_PAD_QUERIES_BLOCK_SIZE */ - VAR_IPSECMOD_ENABLED = 528, /* VAR_IPSECMOD_ENABLED */ - VAR_IPSECMOD_HOOK = 529, /* VAR_IPSECMOD_HOOK */ - VAR_IPSECMOD_IGNORE_BOGUS = 530, /* VAR_IPSECMOD_IGNORE_BOGUS */ - VAR_IPSECMOD_MAX_TTL = 531, /* VAR_IPSECMOD_MAX_TTL */ - VAR_IPSECMOD_WHITELIST = 532, /* VAR_IPSECMOD_WHITELIST */ - VAR_IPSECMOD_STRICT = 533, /* VAR_IPSECMOD_STRICT */ - VAR_CACHEDB = 534, /* VAR_CACHEDB */ - VAR_CACHEDB_BACKEND = 535, /* VAR_CACHEDB_BACKEND */ - VAR_CACHEDB_SECRETSEED = 536, /* VAR_CACHEDB_SECRETSEED */ - VAR_CACHEDB_REDISHOST = 537, /* VAR_CACHEDB_REDISHOST */ - VAR_CACHEDB_REDISPORT = 538, /* VAR_CACHEDB_REDISPORT */ - VAR_CACHEDB_REDISTIMEOUT = 539, /* VAR_CACHEDB_REDISTIMEOUT */ - VAR_CACHEDB_REDISEXPIRERECORDS = 540, /* VAR_CACHEDB_REDISEXPIRERECORDS */ - VAR_CACHEDB_REDISPATH = 541, /* VAR_CACHEDB_REDISPATH */ - VAR_CACHEDB_REDISPASSWORD = 542, /* VAR_CACHEDB_REDISPASSWORD */ - VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 543, /* VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM */ - VAR_FOR_UPSTREAM = 544, /* VAR_FOR_UPSTREAM */ - VAR_AUTH_ZONE = 545, /* VAR_AUTH_ZONE */ - VAR_ZONEFILE = 546, /* VAR_ZONEFILE */ - VAR_MASTER = 547, /* VAR_MASTER */ - VAR_URL = 548, /* VAR_URL */ - VAR_FOR_DOWNSTREAM = 549, /* VAR_FOR_DOWNSTREAM */ - VAR_FALLBACK_ENABLED = 550, /* VAR_FALLBACK_ENABLED */ - VAR_TLS_ADDITIONAL_PORT = 551, /* VAR_TLS_ADDITIONAL_PORT */ - VAR_LOW_RTT = 552, /* VAR_LOW_RTT */ - VAR_LOW_RTT_PERMIL = 553, /* VAR_LOW_RTT_PERMIL */ - VAR_FAST_SERVER_PERMIL = 554, /* VAR_FAST_SERVER_PERMIL */ - VAR_FAST_SERVER_NUM = 555, /* VAR_FAST_SERVER_NUM */ - VAR_ALLOW_NOTIFY = 556, /* VAR_ALLOW_NOTIFY */ - VAR_TLS_WIN_CERT = 557, /* VAR_TLS_WIN_CERT */ - VAR_TCP_CONNECTION_LIMIT = 558, /* VAR_TCP_CONNECTION_LIMIT */ - VAR_ANSWER_COOKIE = 559, /* VAR_ANSWER_COOKIE */ - VAR_COOKIE_SECRET = 560, /* VAR_COOKIE_SECRET */ - VAR_IP_RATELIMIT_COOKIE = 561, /* VAR_IP_RATELIMIT_COOKIE */ - VAR_FORWARD_NO_CACHE = 562, /* VAR_FORWARD_NO_CACHE */ - VAR_STUB_NO_CACHE = 563, /* VAR_STUB_NO_CACHE */ - VAR_LOG_SERVFAIL = 564, /* VAR_LOG_SERVFAIL */ - VAR_DENY_ANY = 565, /* VAR_DENY_ANY */ - VAR_UNKNOWN_SERVER_TIME_LIMIT = 566, /* VAR_UNKNOWN_SERVER_TIME_LIMIT */ - VAR_LOG_TAG_QUERYREPLY = 567, /* VAR_LOG_TAG_QUERYREPLY */ - VAR_STREAM_WAIT_SIZE = 568, /* VAR_STREAM_WAIT_SIZE */ - VAR_TLS_CIPHERS = 569, /* VAR_TLS_CIPHERS */ - VAR_TLS_CIPHERSUITES = 570, /* VAR_TLS_CIPHERSUITES */ - VAR_TLS_USE_SNI = 571, /* VAR_TLS_USE_SNI */ - VAR_IPSET = 572, /* VAR_IPSET */ - VAR_IPSET_NAME_V4 = 573, /* VAR_IPSET_NAME_V4 */ - VAR_IPSET_NAME_V6 = 574, /* VAR_IPSET_NAME_V6 */ - VAR_TLS_SESSION_TICKET_KEYS = 575, /* VAR_TLS_SESSION_TICKET_KEYS */ - VAR_RPZ = 576, /* VAR_RPZ */ - VAR_TAGS = 577, /* VAR_TAGS */ - VAR_RPZ_ACTION_OVERRIDE = 578, /* VAR_RPZ_ACTION_OVERRIDE */ - VAR_RPZ_CNAME_OVERRIDE = 579, /* VAR_RPZ_CNAME_OVERRIDE */ - VAR_RPZ_LOG = 580, /* VAR_RPZ_LOG */ - VAR_RPZ_LOG_NAME = 581, /* VAR_RPZ_LOG_NAME */ - VAR_DYNLIB = 582, /* VAR_DYNLIB */ - VAR_DYNLIB_FILE = 583, /* VAR_DYNLIB_FILE */ - VAR_EDNS_CLIENT_STRING = 584, /* VAR_EDNS_CLIENT_STRING */ - VAR_EDNS_CLIENT_STRING_OPCODE = 585, /* VAR_EDNS_CLIENT_STRING_OPCODE */ - VAR_NSID = 586, /* VAR_NSID */ - VAR_ZONEMD_PERMISSIVE_MODE = 587, /* VAR_ZONEMD_PERMISSIVE_MODE */ - VAR_ZONEMD_CHECK = 588, /* VAR_ZONEMD_CHECK */ - VAR_ZONEMD_REJECT_ABSENCE = 589, /* VAR_ZONEMD_REJECT_ABSENCE */ - VAR_RPZ_SIGNAL_NXDOMAIN_RA = 590, /* VAR_RPZ_SIGNAL_NXDOMAIN_RA */ - VAR_INTERFACE_AUTOMATIC_PORTS = 591, /* VAR_INTERFACE_AUTOMATIC_PORTS */ - VAR_EDE = 592, /* VAR_EDE */ - VAR_INTERFACE_ACTION = 593, /* VAR_INTERFACE_ACTION */ - VAR_INTERFACE_VIEW = 594, /* VAR_INTERFACE_VIEW */ - VAR_INTERFACE_TAG = 595, /* VAR_INTERFACE_TAG */ - VAR_INTERFACE_TAG_ACTION = 596, /* VAR_INTERFACE_TAG_ACTION */ - VAR_INTERFACE_TAG_DATA = 597, /* VAR_INTERFACE_TAG_DATA */ - VAR_PROXY_PROTOCOL_PORT = 598, /* VAR_PROXY_PROTOCOL_PORT */ - VAR_STATISTICS_INHIBIT_ZERO = 599, /* VAR_STATISTICS_INHIBIT_ZERO */ - VAR_HARDEN_UNKNOWN_ADDITIONAL = 600 /* VAR_HARDEN_UNKNOWN_ADDITIONAL */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif -/* Token kinds. */ -#define YYEMPTY -2 -#define YYEOF 0 -#define YYerror 256 -#define YYUNDEF 257 -#define SPACE 258 -#define LETTER 259 -#define NEWLINE 260 -#define COMMENT 261 -#define COLON 262 -#define ANY 263 -#define ZONESTR 264 -#define STRING_ARG 265 -#define VAR_FORCE_TOPLEVEL 266 -#define VAR_SERVER 267 -#define VAR_VERBOSITY 268 -#define VAR_NUM_THREADS 269 -#define VAR_PORT 270 -#define VAR_OUTGOING_RANGE 271 -#define VAR_INTERFACE 272 -#define VAR_PREFER_IP4 273 -#define VAR_DO_IP4 274 -#define VAR_DO_IP6 275 -#define VAR_DO_NAT64 276 -#define VAR_PREFER_IP6 277 -#define VAR_DO_UDP 278 -#define VAR_DO_TCP 279 -#define VAR_TCP_MSS 280 -#define VAR_OUTGOING_TCP_MSS 281 -#define VAR_TCP_IDLE_TIMEOUT 282 -#define VAR_EDNS_TCP_KEEPALIVE 283 -#define VAR_EDNS_TCP_KEEPALIVE_TIMEOUT 284 -#define VAR_SOCK_QUEUE_TIMEOUT 285 -#define VAR_CHROOT 286 -#define VAR_USERNAME 287 -#define VAR_DIRECTORY 288 -#define VAR_LOGFILE 289 -#define VAR_PIDFILE 290 -#define VAR_MSG_CACHE_SIZE 291 -#define VAR_MSG_CACHE_SLABS 292 -#define VAR_NUM_QUERIES_PER_THREAD 293 -#define VAR_RRSET_CACHE_SIZE 294 -#define VAR_RRSET_CACHE_SLABS 295 -#define VAR_OUTGOING_NUM_TCP 296 -#define VAR_INFRA_HOST_TTL 297 -#define VAR_INFRA_LAME_TTL 298 -#define VAR_INFRA_CACHE_SLABS 299 -#define VAR_INFRA_CACHE_NUMHOSTS 300 -#define VAR_INFRA_CACHE_LAME_SIZE 301 -#define VAR_NAME 302 -#define VAR_STUB_ZONE 303 -#define VAR_STUB_HOST 304 -#define VAR_STUB_ADDR 305 -#define VAR_TARGET_FETCH_POLICY 306 -#define VAR_HARDEN_SHORT_BUFSIZE 307 -#define VAR_HARDEN_LARGE_QUERIES 308 -#define VAR_FORWARD_ZONE 309 -#define VAR_FORWARD_HOST 310 -#define VAR_FORWARD_ADDR 311 -#define VAR_DO_NOT_QUERY_ADDRESS 312 -#define VAR_HIDE_IDENTITY 313 -#define VAR_HIDE_VERSION 314 -#define VAR_IDENTITY 315 -#define VAR_VERSION 316 -#define VAR_HARDEN_GLUE 317 -#define VAR_MODULE_CONF 318 -#define VAR_TRUST_ANCHOR_FILE 319 -#define VAR_TRUST_ANCHOR 320 -#define VAR_VAL_OVERRIDE_DATE 321 -#define VAR_BOGUS_TTL 322 -#define VAR_VAL_CLEAN_ADDITIONAL 323 -#define VAR_VAL_PERMISSIVE_MODE 324 -#define VAR_INCOMING_NUM_TCP 325 -#define VAR_MSG_BUFFER_SIZE 326 -#define VAR_KEY_CACHE_SIZE 327 -#define VAR_KEY_CACHE_SLABS 328 -#define VAR_TRUSTED_KEYS_FILE 329 -#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 330 -#define VAR_USE_SYSLOG 331 -#define VAR_OUTGOING_INTERFACE 332 -#define VAR_ROOT_HINTS 333 -#define VAR_DO_NOT_QUERY_LOCALHOST 334 -#define VAR_CACHE_MAX_TTL 335 -#define VAR_HARDEN_DNSSEC_STRIPPED 336 -#define VAR_ACCESS_CONTROL 337 -#define VAR_LOCAL_ZONE 338 -#define VAR_LOCAL_DATA 339 -#define VAR_INTERFACE_AUTOMATIC 340 -#define VAR_STATISTICS_INTERVAL 341 -#define VAR_DO_DAEMONIZE 342 -#define VAR_USE_CAPS_FOR_ID 343 -#define VAR_STATISTICS_CUMULATIVE 344 -#define VAR_OUTGOING_PORT_PERMIT 345 -#define VAR_OUTGOING_PORT_AVOID 346 -#define VAR_DLV_ANCHOR_FILE 347 -#define VAR_DLV_ANCHOR 348 -#define VAR_NEG_CACHE_SIZE 349 -#define VAR_HARDEN_REFERRAL_PATH 350 -#define VAR_PRIVATE_ADDRESS 351 -#define VAR_PRIVATE_DOMAIN 352 -#define VAR_REMOTE_CONTROL 353 -#define VAR_CONTROL_ENABLE 354 -#define VAR_CONTROL_INTERFACE 355 -#define VAR_CONTROL_PORT 356 -#define VAR_SERVER_KEY_FILE 357 -#define VAR_SERVER_CERT_FILE 358 -#define VAR_CONTROL_KEY_FILE 359 -#define VAR_CONTROL_CERT_FILE 360 -#define VAR_CONTROL_USE_CERT 361 -#define VAR_TCP_REUSE_TIMEOUT 362 -#define VAR_MAX_REUSE_TCP_QUERIES 363 -#define VAR_EXTENDED_STATISTICS 364 -#define VAR_LOCAL_DATA_PTR 365 -#define VAR_JOSTLE_TIMEOUT 366 -#define VAR_STUB_PRIME 367 -#define VAR_UNWANTED_REPLY_THRESHOLD 368 -#define VAR_LOG_TIME_ASCII 369 -#define VAR_DOMAIN_INSECURE 370 -#define VAR_PYTHON 371 -#define VAR_PYTHON_SCRIPT 372 -#define VAR_VAL_SIG_SKEW_MIN 373 -#define VAR_VAL_SIG_SKEW_MAX 374 -#define VAR_VAL_MAX_RESTART 375 -#define VAR_CACHE_MIN_TTL 376 -#define VAR_VAL_LOG_LEVEL 377 -#define VAR_AUTO_TRUST_ANCHOR_FILE 378 -#define VAR_KEEP_MISSING 379 -#define VAR_ADD_HOLDDOWN 380 -#define VAR_DEL_HOLDDOWN 381 -#define VAR_SO_RCVBUF 382 -#define VAR_EDNS_BUFFER_SIZE 383 -#define VAR_PREFETCH 384 -#define VAR_PREFETCH_KEY 385 -#define VAR_SO_SNDBUF 386 -#define VAR_SO_REUSEPORT 387 -#define VAR_HARDEN_BELOW_NXDOMAIN 388 -#define VAR_IGNORE_CD_FLAG 389 -#define VAR_LOG_QUERIES 390 -#define VAR_LOG_REPLIES 391 -#define VAR_LOG_LOCAL_ACTIONS 392 -#define VAR_TCP_UPSTREAM 393 -#define VAR_SSL_UPSTREAM 394 -#define VAR_TCP_AUTH_QUERY_TIMEOUT 395 -#define VAR_SSL_SERVICE_KEY 396 -#define VAR_SSL_SERVICE_PEM 397 -#define VAR_SSL_PORT 398 -#define VAR_FORWARD_FIRST 399 -#define VAR_STUB_SSL_UPSTREAM 400 -#define VAR_FORWARD_SSL_UPSTREAM 401 -#define VAR_TLS_CERT_BUNDLE 402 -#define VAR_STUB_TCP_UPSTREAM 403 -#define VAR_FORWARD_TCP_UPSTREAM 404 -#define VAR_HTTPS_PORT 405 -#define VAR_HTTP_ENDPOINT 406 -#define VAR_HTTP_MAX_STREAMS 407 -#define VAR_HTTP_QUERY_BUFFER_SIZE 408 -#define VAR_HTTP_RESPONSE_BUFFER_SIZE 409 -#define VAR_HTTP_NODELAY 410 -#define VAR_HTTP_NOTLS_DOWNSTREAM 411 -#define VAR_STUB_FIRST 412 -#define VAR_MINIMAL_RESPONSES 413 -#define VAR_RRSET_ROUNDROBIN 414 -#define VAR_MAX_UDP_SIZE 415 -#define VAR_DELAY_CLOSE 416 -#define VAR_UDP_CONNECT 417 -#define VAR_UNBLOCK_LAN_ZONES 418 -#define VAR_INSECURE_LAN_ZONES 419 -#define VAR_INFRA_CACHE_MIN_RTT 420 -#define VAR_INFRA_CACHE_MAX_RTT 421 -#define VAR_INFRA_KEEP_PROBING 422 -#define VAR_DNS64_PREFIX 423 -#define VAR_DNS64_SYNTHALL 424 -#define VAR_DNS64_IGNORE_AAAA 425 -#define VAR_NAT64_PREFIX 426 -#define VAR_DNSTAP 427 -#define VAR_DNSTAP_ENABLE 428 -#define VAR_DNSTAP_SOCKET_PATH 429 -#define VAR_DNSTAP_IP 430 -#define VAR_DNSTAP_TLS 431 -#define VAR_DNSTAP_TLS_SERVER_NAME 432 -#define VAR_DNSTAP_TLS_CERT_BUNDLE 433 -#define VAR_DNSTAP_TLS_CLIENT_KEY_FILE 434 -#define VAR_DNSTAP_TLS_CLIENT_CERT_FILE 435 -#define VAR_DNSTAP_SEND_IDENTITY 436 -#define VAR_DNSTAP_SEND_VERSION 437 -#define VAR_DNSTAP_BIDIRECTIONAL 438 -#define VAR_DNSTAP_IDENTITY 439 -#define VAR_DNSTAP_VERSION 440 -#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 441 -#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 442 -#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 443 -#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 444 -#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 445 -#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 446 -#define VAR_RESPONSE_IP_TAG 447 -#define VAR_RESPONSE_IP 448 -#define VAR_RESPONSE_IP_DATA 449 -#define VAR_HARDEN_ALGO_DOWNGRADE 450 -#define VAR_IP_TRANSPARENT 451 -#define VAR_IP_DSCP 452 -#define VAR_DISABLE_DNSSEC_LAME_CHECK 453 -#define VAR_IP_RATELIMIT 454 -#define VAR_IP_RATELIMIT_SLABS 455 -#define VAR_IP_RATELIMIT_SIZE 456 -#define VAR_RATELIMIT 457 -#define VAR_RATELIMIT_SLABS 458 -#define VAR_RATELIMIT_SIZE 459 -#define VAR_OUTBOUND_MSG_RETRY 460 -#define VAR_MAX_SENT_COUNT 461 -#define VAR_MAX_QUERY_RESTARTS 462 -#define VAR_RATELIMIT_FOR_DOMAIN 463 -#define VAR_RATELIMIT_BELOW_DOMAIN 464 -#define VAR_IP_RATELIMIT_FACTOR 465 -#define VAR_RATELIMIT_FACTOR 466 -#define VAR_IP_RATELIMIT_BACKOFF 467 -#define VAR_RATELIMIT_BACKOFF 468 -#define VAR_SEND_CLIENT_SUBNET 469 -#define VAR_CLIENT_SUBNET_ZONE 470 -#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 471 -#define VAR_CLIENT_SUBNET_OPCODE 472 -#define VAR_MAX_CLIENT_SUBNET_IPV4 473 -#define VAR_MAX_CLIENT_SUBNET_IPV6 474 -#define VAR_MIN_CLIENT_SUBNET_IPV4 475 -#define VAR_MIN_CLIENT_SUBNET_IPV6 476 -#define VAR_MAX_ECS_TREE_SIZE_IPV4 477 -#define VAR_MAX_ECS_TREE_SIZE_IPV6 478 -#define VAR_CAPS_WHITELIST 479 -#define VAR_CACHE_MAX_NEGATIVE_TTL 480 -#define VAR_PERMIT_SMALL_HOLDDOWN 481 -#define VAR_QNAME_MINIMISATION 482 -#define VAR_QNAME_MINIMISATION_STRICT 483 -#define VAR_IP_FREEBIND 484 -#define VAR_DEFINE_TAG 485 -#define VAR_LOCAL_ZONE_TAG 486 -#define VAR_ACCESS_CONTROL_TAG 487 -#define VAR_LOCAL_ZONE_OVERRIDE 488 -#define VAR_ACCESS_CONTROL_TAG_ACTION 489 -#define VAR_ACCESS_CONTROL_TAG_DATA 490 -#define VAR_VIEW 491 -#define VAR_ACCESS_CONTROL_VIEW 492 -#define VAR_VIEW_FIRST 493 -#define VAR_SERVE_EXPIRED 494 -#define VAR_SERVE_EXPIRED_TTL 495 -#define VAR_SERVE_EXPIRED_TTL_RESET 496 -#define VAR_SERVE_EXPIRED_REPLY_TTL 497 -#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 498 -#define VAR_EDE_SERVE_EXPIRED 499 -#define VAR_SERVE_ORIGINAL_TTL 500 -#define VAR_FAKE_DSA 501 -#define VAR_FAKE_SHA1 502 -#define VAR_LOG_IDENTITY 503 -#define VAR_HIDE_TRUSTANCHOR 504 -#define VAR_HIDE_HTTP_USER_AGENT 505 -#define VAR_HTTP_USER_AGENT 506 -#define VAR_TRUST_ANCHOR_SIGNALING 507 -#define VAR_AGGRESSIVE_NSEC 508 -#define VAR_USE_SYSTEMD 509 -#define VAR_SHM_ENABLE 510 -#define VAR_SHM_KEY 511 -#define VAR_ROOT_KEY_SENTINEL 512 -#define VAR_DNSCRYPT 513 -#define VAR_DNSCRYPT_ENABLE 514 -#define VAR_DNSCRYPT_PORT 515 -#define VAR_DNSCRYPT_PROVIDER 516 -#define VAR_DNSCRYPT_SECRET_KEY 517 -#define VAR_DNSCRYPT_PROVIDER_CERT 518 -#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 519 -#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 520 -#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 521 -#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 522 -#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 523 -#define VAR_PAD_RESPONSES 524 -#define VAR_PAD_RESPONSES_BLOCK_SIZE 525 -#define VAR_PAD_QUERIES 526 -#define VAR_PAD_QUERIES_BLOCK_SIZE 527 -#define VAR_IPSECMOD_ENABLED 528 -#define VAR_IPSECMOD_HOOK 529 -#define VAR_IPSECMOD_IGNORE_BOGUS 530 -#define VAR_IPSECMOD_MAX_TTL 531 -#define VAR_IPSECMOD_WHITELIST 532 -#define VAR_IPSECMOD_STRICT 533 -#define VAR_CACHEDB 534 -#define VAR_CACHEDB_BACKEND 535 -#define VAR_CACHEDB_SECRETSEED 536 -#define VAR_CACHEDB_REDISHOST 537 -#define VAR_CACHEDB_REDISPORT 538 -#define VAR_CACHEDB_REDISTIMEOUT 539 -#define VAR_CACHEDB_REDISEXPIRERECORDS 540 -#define VAR_CACHEDB_REDISPATH 541 -#define VAR_CACHEDB_REDISPASSWORD 542 -#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 543 -#define VAR_FOR_UPSTREAM 544 -#define VAR_AUTH_ZONE 545 -#define VAR_ZONEFILE 546 -#define VAR_MASTER 547 -#define VAR_URL 548 -#define VAR_FOR_DOWNSTREAM 549 -#define VAR_FALLBACK_ENABLED 550 -#define VAR_TLS_ADDITIONAL_PORT 551 -#define VAR_LOW_RTT 552 -#define VAR_LOW_RTT_PERMIL 553 -#define VAR_FAST_SERVER_PERMIL 554 -#define VAR_FAST_SERVER_NUM 555 -#define VAR_ALLOW_NOTIFY 556 -#define VAR_TLS_WIN_CERT 557 -#define VAR_TCP_CONNECTION_LIMIT 558 -#define VAR_ANSWER_COOKIE 559 -#define VAR_COOKIE_SECRET 560 -#define VAR_IP_RATELIMIT_COOKIE 561 -#define VAR_FORWARD_NO_CACHE 562 -#define VAR_STUB_NO_CACHE 563 -#define VAR_LOG_SERVFAIL 564 -#define VAR_DENY_ANY 565 -#define VAR_UNKNOWN_SERVER_TIME_LIMIT 566 -#define VAR_LOG_TAG_QUERYREPLY 567 -#define VAR_STREAM_WAIT_SIZE 568 -#define VAR_TLS_CIPHERS 569 -#define VAR_TLS_CIPHERSUITES 570 -#define VAR_TLS_USE_SNI 571 -#define VAR_IPSET 572 -#define VAR_IPSET_NAME_V4 573 -#define VAR_IPSET_NAME_V6 574 -#define VAR_TLS_SESSION_TICKET_KEYS 575 -#define VAR_RPZ 576 -#define VAR_TAGS 577 -#define VAR_RPZ_ACTION_OVERRIDE 578 -#define VAR_RPZ_CNAME_OVERRIDE 579 -#define VAR_RPZ_LOG 580 -#define VAR_RPZ_LOG_NAME 581 -#define VAR_DYNLIB 582 -#define VAR_DYNLIB_FILE 583 -#define VAR_EDNS_CLIENT_STRING 584 -#define VAR_EDNS_CLIENT_STRING_OPCODE 585 -#define VAR_NSID 586 -#define VAR_ZONEMD_PERMISSIVE_MODE 587 -#define VAR_ZONEMD_CHECK 588 -#define VAR_ZONEMD_REJECT_ABSENCE 589 -#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 590 -#define VAR_INTERFACE_AUTOMATIC_PORTS 591 -#define VAR_EDE 592 -#define VAR_INTERFACE_ACTION 593 -#define VAR_INTERFACE_VIEW 594 -#define VAR_INTERFACE_TAG 595 -#define VAR_INTERFACE_TAG_ACTION 596 -#define VAR_INTERFACE_TAG_DATA 597 -#define VAR_PROXY_PROTOCOL_PORT 598 -#define VAR_STATISTICS_INHIBIT_ZERO 599 -#define VAR_HARDEN_UNKNOWN_ADDITIONAL 600 - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -#line 68 "util/configparser.y" - - char* str; - -#line 761 "util/configparser.h" - -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE yylval; - -int yyparse (void); - -#endif /* !YY_YY_UTIL_CONFIGPARSER_H_INCLUDED */ diff --git a/crates/libunbound-sys/unbound/util/configparser.y b/crates/libunbound-sys/unbound/util/configparser.y deleted file mode 100644 index d8f25a67..00000000 --- a/crates/libunbound-sys/unbound/util/configparser.y +++ /dev/null @@ -1,3919 +0,0 @@ -/* - * configparser.y -- yacc grammar for unbound configuration files - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -%{ -#include "config.h" - -#include -#include -#include -#include -#include - -#include "util/configyyrename.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "sldns/str2wire.h" - -int ub_c_lex(void); -void ub_c_error(const char *message); - -static void validate_respip_action(const char* action); -static void validate_acl_action(const char* action); - -/* these need to be global, otherwise they cannot be used inside yacc */ -extern struct config_parser_state* cfg_parser; - -#if 0 -#define OUTYY(s) printf s /* used ONLY when debugging */ -#else -#define OUTYY(s) -#endif - -%} -%union { - char* str; -}; - -%token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR -%token STRING_ARG -%token VAR_FORCE_TOPLEVEL -%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT -%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_PREFER_IP4 -%token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_NAT64 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP -%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT -%token VAR_EDNS_TCP_KEEPALIVE VAR_EDNS_TCP_KEEPALIVE_TIMEOUT -%token VAR_SOCK_QUEUE_TIMEOUT -%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE -%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD -%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP -%token VAR_INFRA_HOST_TTL VAR_INFRA_LAME_TTL VAR_INFRA_CACHE_SLABS -%token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_LAME_SIZE VAR_NAME -%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY -%token VAR_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES -%token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR -%token VAR_DO_NOT_QUERY_ADDRESS VAR_HIDE_IDENTITY VAR_HIDE_VERSION -%token VAR_IDENTITY VAR_VERSION VAR_HARDEN_GLUE VAR_MODULE_CONF -%token VAR_TRUST_ANCHOR_FILE VAR_TRUST_ANCHOR VAR_VAL_OVERRIDE_DATE -%token VAR_BOGUS_TTL VAR_VAL_CLEAN_ADDITIONAL VAR_VAL_PERMISSIVE_MODE -%token VAR_INCOMING_NUM_TCP VAR_MSG_BUFFER_SIZE VAR_KEY_CACHE_SIZE -%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE -%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG -%token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST -%token VAR_CACHE_MAX_TTL VAR_HARDEN_DNSSEC_STRIPPED VAR_ACCESS_CONTROL -%token VAR_LOCAL_ZONE VAR_LOCAL_DATA VAR_INTERFACE_AUTOMATIC -%token VAR_STATISTICS_INTERVAL VAR_DO_DAEMONIZE VAR_USE_CAPS_FOR_ID -%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT -%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR -%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS -%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE -%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE -%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE -%token VAR_CONTROL_USE_CERT VAR_TCP_REUSE_TIMEOUT VAR_MAX_REUSE_TCP_QUERIES -%token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT -%token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD VAR_LOG_TIME_ASCII -%token VAR_DOMAIN_INSECURE VAR_PYTHON VAR_PYTHON_SCRIPT VAR_VAL_SIG_SKEW_MIN -%token VAR_VAL_SIG_SKEW_MAX VAR_VAL_MAX_RESTART VAR_CACHE_MIN_TTL -%token VAR_VAL_LOG_LEVEL VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING -%token VAR_ADD_HOLDDOWN VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE -%token VAR_PREFETCH VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT -%token VAR_HARDEN_BELOW_NXDOMAIN VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES -%token VAR_LOG_REPLIES VAR_LOG_LOCAL_ACTIONS VAR_TCP_UPSTREAM -%token VAR_SSL_UPSTREAM VAR_TCP_AUTH_QUERY_TIMEOUT VAR_SSL_SERVICE_KEY -%token VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST -%token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE -%token VAR_STUB_TCP_UPSTREAM VAR_FORWARD_TCP_UPSTREAM -%token VAR_HTTPS_PORT VAR_HTTP_ENDPOINT VAR_HTTP_MAX_STREAMS -%token VAR_HTTP_QUERY_BUFFER_SIZE VAR_HTTP_RESPONSE_BUFFER_SIZE -%token VAR_HTTP_NODELAY VAR_HTTP_NOTLS_DOWNSTREAM -%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN -%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UDP_CONNECT -%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES -%token VAR_INFRA_CACHE_MIN_RTT VAR_INFRA_CACHE_MAX_RTT VAR_INFRA_KEEP_PROBING -%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA -%token VAR_NAT64_PREFIX -%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP -%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE -%token VAR_DNSTAP_TLS_CLIENT_KEY_FILE VAR_DNSTAP_TLS_CLIENT_CERT_FILE -%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION VAR_DNSTAP_BIDIRECTIONAL -%token VAR_DNSTAP_IDENTITY VAR_DNSTAP_VERSION -%token VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES -%token VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES -%token VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES -%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES -%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES -%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES -%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA -%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT -%token VAR_IP_DSCP -%token VAR_DISABLE_DNSSEC_LAME_CHECK -%token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE -%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE -%token VAR_OUTBOUND_MSG_RETRY VAR_MAX_SENT_COUNT VAR_MAX_QUERY_RESTARTS -%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN -%token VAR_IP_RATELIMIT_FACTOR VAR_RATELIMIT_FACTOR -%token VAR_IP_RATELIMIT_BACKOFF VAR_RATELIMIT_BACKOFF -%token VAR_SEND_CLIENT_SUBNET VAR_CLIENT_SUBNET_ZONE -%token VAR_CLIENT_SUBNET_ALWAYS_FORWARD VAR_CLIENT_SUBNET_OPCODE -%token VAR_MAX_CLIENT_SUBNET_IPV4 VAR_MAX_CLIENT_SUBNET_IPV6 -%token VAR_MIN_CLIENT_SUBNET_IPV4 VAR_MIN_CLIENT_SUBNET_IPV6 -%token VAR_MAX_ECS_TREE_SIZE_IPV4 VAR_MAX_ECS_TREE_SIZE_IPV6 -%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN -%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND -%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG -%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION -%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW -%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_TTL -%token VAR_SERVE_EXPIRED_TTL_RESET VAR_SERVE_EXPIRED_REPLY_TTL -%token VAR_SERVE_EXPIRED_CLIENT_TIMEOUT VAR_EDE_SERVE_EXPIRED -%token VAR_SERVE_ORIGINAL_TTL VAR_FAKE_DSA -%token VAR_FAKE_SHA1 VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR -%token VAR_HIDE_HTTP_USER_AGENT VAR_HTTP_USER_AGENT -%token VAR_TRUST_ANCHOR_SIGNALING VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD -%token VAR_SHM_ENABLE VAR_SHM_KEY VAR_ROOT_KEY_SENTINEL -%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER -%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT -%token VAR_DNSCRYPT_PROVIDER_CERT_ROTATED -%token VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE -%token VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS -%token VAR_DNSCRYPT_NONCE_CACHE_SIZE -%token VAR_DNSCRYPT_NONCE_CACHE_SLABS -%token VAR_PAD_RESPONSES VAR_PAD_RESPONSES_BLOCK_SIZE -%token VAR_PAD_QUERIES VAR_PAD_QUERIES_BLOCK_SIZE -%token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS -%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT -%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED -%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT -%token VAR_CACHEDB_REDISEXPIRERECORDS VAR_CACHEDB_REDISPATH VAR_CACHEDB_REDISPASSWORD -%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM -%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM -%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL -%token VAR_FAST_SERVER_PERMIL VAR_FAST_SERVER_NUM -%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT -%token VAR_ANSWER_COOKIE VAR_COOKIE_SECRET VAR_IP_RATELIMIT_COOKIE -%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY -%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY -%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI -%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6 -%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE -%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME -%token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_STRING -%token VAR_EDNS_CLIENT_STRING_OPCODE VAR_NSID -%token VAR_ZONEMD_PERMISSIVE_MODE VAR_ZONEMD_CHECK VAR_ZONEMD_REJECT_ABSENCE -%token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS VAR_EDE -%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG -%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA -%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO -%token VAR_HARDEN_UNKNOWN_ADDITIONAL - -%% -toplevelvars: /* empty */ | toplevelvars toplevelvar ; -toplevelvar: serverstart contents_server | stubstart contents_stub | - forwardstart contents_forward | pythonstart contents_py | - rcstart contents_rc | dtstart contents_dt | viewstart contents_view | - dnscstart contents_dnsc | cachedbstart contents_cachedb | - ipsetstart contents_ipset | authstart contents_auth | - rpzstart contents_rpz | dynlibstart contents_dl | - force_toplevel - ; -force_toplevel: VAR_FORCE_TOPLEVEL - { - OUTYY(("\nP(force-toplevel)\n")); - cfg_parser->started_toplevel = 0; - } - ; -/* server: declaration */ -serverstart: VAR_SERVER - { - OUTYY(("\nP(server:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_server: contents_server content_server - | ; -content_server: server_num_threads | server_verbosity | server_port | - server_outgoing_range | server_do_ip4 | - server_do_ip6 | server_do_nat64 | server_prefer_ip4 | - server_prefer_ip6 | server_do_udp | server_do_tcp | - server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout | - server_tcp_keepalive | server_tcp_keepalive_timeout | - server_sock_queue_timeout | - server_interface | server_chroot | server_username | - server_directory | server_logfile | server_pidfile | - server_msg_cache_size | server_msg_cache_slabs | - server_num_queries_per_thread | server_rrset_cache_size | - server_rrset_cache_slabs | server_outgoing_num_tcp | - server_infra_host_ttl | server_infra_lame_ttl | - server_infra_cache_slabs | server_infra_cache_numhosts | - server_infra_cache_lame_size | server_target_fetch_policy | - server_harden_short_bufsize | server_harden_large_queries | - server_do_not_query_address | server_hide_identity | - server_hide_version | server_identity | server_version | - server_hide_http_user_agent | server_http_user_agent | - server_harden_glue | server_module_conf | server_trust_anchor_file | - server_trust_anchor | server_val_override_date | server_bogus_ttl | - server_val_clean_additional | server_val_permissive_mode | - server_incoming_num_tcp | server_msg_buffer_size | - server_key_cache_size | server_key_cache_slabs | - server_trusted_keys_file | server_val_nsec3_keysize_iterations | - server_use_syslog | server_outgoing_interface | server_root_hints | - server_do_not_query_localhost | server_cache_max_ttl | - server_harden_dnssec_stripped | server_access_control | - server_local_zone | server_local_data | server_interface_automatic | - server_statistics_interval | server_do_daemonize | - server_use_caps_for_id | server_statistics_cumulative | - server_outgoing_port_permit | server_outgoing_port_avoid | - server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size | - server_harden_referral_path | server_private_address | - server_private_domain | server_extended_statistics | - server_local_data_ptr | server_jostle_timeout | - server_unwanted_reply_threshold | server_log_time_ascii | - server_domain_insecure | server_val_sig_skew_min | - server_val_sig_skew_max | server_val_max_restart | - server_cache_min_ttl | server_val_log_level | - server_auto_trust_anchor_file | server_add_holddown | - server_del_holddown | server_keep_missing | server_so_rcvbuf | - server_edns_buffer_size | server_prefetch | server_prefetch_key | - server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag | - server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream | - server_log_local_actions | - server_ssl_service_key | server_ssl_service_pem | server_ssl_port | - server_https_port | server_http_endpoint | server_http_max_streams | - server_http_query_buffer_size | server_http_response_buffer_size | - server_http_nodelay | server_http_notls_downstream | - server_minimal_responses | server_rrset_roundrobin | server_max_udp_size | - server_so_reuseport | server_delay_close | server_udp_connect | - server_unblock_lan_zones | server_insecure_lan_zones | - server_dns64_prefix | server_dns64_synthall | server_dns64_ignore_aaaa | - server_nat64_prefix | - server_infra_cache_min_rtt | server_infra_cache_max_rtt | server_harden_algo_downgrade | - server_ip_transparent | server_ip_ratelimit | server_ratelimit | - server_ip_dscp | server_infra_keep_probing | - server_ip_ratelimit_slabs | server_ratelimit_slabs | - server_ip_ratelimit_size | server_ratelimit_size | - server_ratelimit_for_domain | - server_ratelimit_below_domain | server_ratelimit_factor | - server_ip_ratelimit_factor | server_ratelimit_backoff | - server_ip_ratelimit_backoff | server_outbound_msg_retry | - server_max_sent_count | server_max_query_restarts | - server_send_client_subnet | server_client_subnet_zone | - server_client_subnet_always_forward | server_client_subnet_opcode | - server_max_client_subnet_ipv4 | server_max_client_subnet_ipv6 | - server_min_client_subnet_ipv4 | server_min_client_subnet_ipv6 | - server_max_ecs_tree_size_ipv4 | server_max_ecs_tree_size_ipv6 | - server_caps_whitelist | server_cache_max_negative_ttl | - server_permit_small_holddown | server_qname_minimisation | - server_ip_freebind | server_define_tag | server_local_zone_tag | - server_disable_dnssec_lame_check | server_access_control_tag | - server_local_zone_override | server_access_control_tag_action | - server_access_control_tag_data | server_access_control_view | - server_interface_action | server_interface_view | server_interface_tag | - server_interface_tag_action | server_interface_tag_data | - server_qname_minimisation_strict | - server_pad_responses | server_pad_responses_block_size | - server_pad_queries | server_pad_queries_block_size | - server_serve_expired | - server_serve_expired_ttl | server_serve_expired_ttl_reset | - server_serve_expired_reply_ttl | server_serve_expired_client_timeout | - server_ede_serve_expired | server_serve_original_ttl | server_fake_dsa | - server_log_identity | server_use_systemd | - server_response_ip_tag | server_response_ip | server_response_ip_data | - server_shm_enable | server_shm_key | server_fake_sha1 | - server_hide_trustanchor | server_trust_anchor_signaling | - server_root_key_sentinel | - server_ipsecmod_enabled | server_ipsecmod_hook | - server_ipsecmod_ignore_bogus | server_ipsecmod_max_ttl | - server_ipsecmod_whitelist | server_ipsecmod_strict | - server_udp_upstream_without_downstream | server_aggressive_nsec | - server_tls_cert_bundle | server_tls_additional_port | server_low_rtt | - server_fast_server_permil | server_fast_server_num | server_tls_win_cert | - server_tcp_connection_limit | server_log_servfail | server_deny_any | - server_unknown_server_time_limit | server_log_tag_queryreply | - server_stream_wait_size | server_tls_ciphers | - server_tls_ciphersuites | server_tls_session_ticket_keys | - server_answer_cookie | server_cookie_secret | server_ip_ratelimit_cookie | - server_tls_use_sni | server_edns_client_string | - server_edns_client_string_opcode | server_nsid | - server_zonemd_permissive_mode | server_max_reuse_tcp_queries | - server_tcp_reuse_timeout | server_tcp_auth_query_timeout | - server_interface_automatic_ports | server_ede | - server_proxy_protocol_port | server_statistics_inhibit_zero | - server_harden_unknown_additional - ; -stubstart: VAR_STUB_ZONE - { - struct config_stub* s; - OUTYY(("\nP(stub_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); - if(s) { - s->next = cfg_parser->cfg->stubs; - cfg_parser->cfg->stubs = s; - } else { - yyerror("out of memory"); - } - } - ; -contents_stub: contents_stub content_stub - | ; -content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first | - stub_no_cache | stub_ssl_upstream | stub_tcp_upstream - ; -forwardstart: VAR_FORWARD_ZONE - { - struct config_stub* s; - OUTYY(("\nP(forward_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); - if(s) { - s->next = cfg_parser->cfg->forwards; - cfg_parser->cfg->forwards = s; - } else { - yyerror("out of memory"); - } - } - ; -contents_forward: contents_forward content_forward - | ; -content_forward: forward_name | forward_host | forward_addr | forward_first | - forward_no_cache | forward_ssl_upstream | forward_tcp_upstream - ; -viewstart: VAR_VIEW - { - struct config_view* s; - OUTYY(("\nP(view:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_view*)calloc(1, sizeof(struct config_view)); - if(s) { - s->next = cfg_parser->cfg->views; - if(s->next && !s->next->name) - yyerror("view without name"); - cfg_parser->cfg->views = s; - } else { - yyerror("out of memory"); - } - } - ; -contents_view: contents_view content_view - | ; -content_view: view_name | view_local_zone | view_local_data | view_first | - view_response_ip | view_response_ip_data | view_local_data_ptr - ; -authstart: VAR_AUTH_ZONE - { - struct config_auth* s; - OUTYY(("\nP(auth_zone:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_auth*)calloc(1, sizeof(struct config_auth)); - if(s) { - s->next = cfg_parser->cfg->auths; - cfg_parser->cfg->auths = s; - /* defaults for auth zone */ - s->for_downstream = 1; - s->for_upstream = 1; - s->fallback_enabled = 0; - s->zonemd_check = 0; - s->zonemd_reject_absence = 0; - s->isrpz = 0; - } else { - yyerror("out of memory"); - } - } - ; -contents_auth: contents_auth content_auth - | ; -content_auth: auth_name | auth_zonefile | auth_master | auth_url | - auth_for_downstream | auth_for_upstream | auth_fallback_enabled | - auth_allow_notify | auth_zonemd_check | auth_zonemd_reject_absence - ; - -rpz_tag: VAR_TAGS STRING_ARG - { - uint8_t* bitlist; - size_t len = 0; - OUTYY(("P(server_local_zone_tag:%s)\n", $2)); - bitlist = config_parse_taglist(cfg_parser->cfg, $2, - &len); - free($2); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - } - if(bitlist) { - cfg_parser->cfg->auths->rpz_taglist = bitlist; - cfg_parser->cfg->auths->rpz_taglistlen = len; - - } - } - ; - -rpz_action_override: VAR_RPZ_ACTION_OVERRIDE STRING_ARG - { - OUTYY(("P(rpz_action_override:%s)\n", $2)); - if(strcmp($2, "nxdomain")!=0 && strcmp($2, "nodata")!=0 && - strcmp($2, "passthru")!=0 && strcmp($2, "drop")!=0 && - strcmp($2, "cname")!=0 && strcmp($2, "disabled")!=0) { - yyerror("rpz-action-override action: expected nxdomain, " - "nodata, passthru, drop, cname or disabled"); - free($2); - cfg_parser->cfg->auths->rpz_action_override = NULL; - } - else { - cfg_parser->cfg->auths->rpz_action_override = $2; - } - } - ; - -rpz_cname_override: VAR_RPZ_CNAME_OVERRIDE STRING_ARG - { - OUTYY(("P(rpz_cname_override:%s)\n", $2)); - free(cfg_parser->cfg->auths->rpz_cname); - cfg_parser->cfg->auths->rpz_cname = $2; - } - ; - -rpz_log: VAR_RPZ_LOG STRING_ARG - { - OUTYY(("P(rpz_log:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->rpz_log = (strcmp($2, "yes")==0); - free($2); - } - ; - -rpz_log_name: VAR_RPZ_LOG_NAME STRING_ARG - { - OUTYY(("P(rpz_log_name:%s)\n", $2)); - free(cfg_parser->cfg->auths->rpz_log_name); - cfg_parser->cfg->auths->rpz_log_name = $2; - } - ; -rpz_signal_nxdomain_ra: VAR_RPZ_SIGNAL_NXDOMAIN_RA STRING_ARG - { - OUTYY(("P(rpz_signal_nxdomain_ra:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->rpz_signal_nxdomain_ra = (strcmp($2, "yes")==0); - free($2); - } - ; - -rpzstart: VAR_RPZ - { - struct config_auth* s; - OUTYY(("\nP(rpz:)\n")); - cfg_parser->started_toplevel = 1; - s = (struct config_auth*)calloc(1, sizeof(struct config_auth)); - if(s) { - s->next = cfg_parser->cfg->auths; - cfg_parser->cfg->auths = s; - /* defaults for RPZ auth zone */ - s->for_downstream = 0; - s->for_upstream = 0; - s->fallback_enabled = 0; - s->isrpz = 1; - } else { - yyerror("out of memory"); - } - } - ; -contents_rpz: contents_rpz content_rpz - | ; -content_rpz: auth_name | auth_zonefile | rpz_tag | auth_master | auth_url | - auth_allow_notify | rpz_action_override | rpz_cname_override | - rpz_log | rpz_log_name | rpz_signal_nxdomain_ra | auth_for_downstream - ; -server_num_threads: VAR_NUM_THREADS STRING_ARG - { - OUTYY(("P(server_num_threads:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->num_threads = atoi($2); - free($2); - } - ; -server_verbosity: VAR_VERBOSITY STRING_ARG - { - OUTYY(("P(server_verbosity:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->verbosity = atoi($2); - free($2); - } - ; -server_statistics_interval: VAR_STATISTICS_INTERVAL STRING_ARG - { - OUTYY(("P(server_statistics_interval:%s)\n", $2)); - if(strcmp($2, "") == 0 || strcmp($2, "0") == 0) - cfg_parser->cfg->stat_interval = 0; - else if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->stat_interval = atoi($2); - free($2); - } - ; -server_statistics_cumulative: VAR_STATISTICS_CUMULATIVE STRING_ARG - { - OUTYY(("P(server_statistics_cumulative:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_cumulative = (strcmp($2, "yes")==0); - free($2); - } - ; -server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG - { - OUTYY(("P(server_extended_statistics:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_extended = (strcmp($2, "yes")==0); - free($2); - } - ; -server_statistics_inhibit_zero: VAR_STATISTICS_INHIBIT_ZERO STRING_ARG - { - OUTYY(("P(server_statistics_inhibit_zero:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stat_inhibit_zero = (strcmp($2, "yes")==0); - free($2); - } - ; -server_shm_enable: VAR_SHM_ENABLE STRING_ARG - { - OUTYY(("P(server_shm_enable:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->shm_enable = (strcmp($2, "yes")==0); - free($2); - } - ; -server_shm_key: VAR_SHM_KEY STRING_ARG - { - OUTYY(("P(server_shm_key:%s)\n", $2)); - if(strcmp($2, "") == 0 || strcmp($2, "0") == 0) - cfg_parser->cfg->shm_key = 0; - else if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->shm_key = atoi($2); - free($2); - } - ; -server_port: VAR_PORT STRING_ARG - { - OUTYY(("P(server_port:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->port = atoi($2); - free($2); - } - ; -server_send_client_subnet: VAR_SEND_CLIENT_SUBNET STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_send_client_subnet:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->client_subnet, $2)) - fatal_exit("out of memory adding client-subnet"); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - free($2); - #endif - } - ; -server_client_subnet_zone: VAR_CLIENT_SUBNET_ZONE STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_client_subnet_zone:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->client_subnet_zone, - $2)) - fatal_exit("out of memory adding client-subnet-zone"); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - free($2); - #endif - } - ; -server_client_subnet_always_forward: - VAR_CLIENT_SUBNET_ALWAYS_FORWARD STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(server_client_subnet_always_forward:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->client_subnet_always_forward = - (strcmp($2, "yes")==0); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_client_subnet_opcode: VAR_CLIENT_SUBNET_OPCODE STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(client_subnet_opcode:%s)\n", $2)); - OUTYY(("P(Deprecated option, ignoring)\n")); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_max_client_subnet_ipv4: VAR_MAX_CLIENT_SUBNET_IPV4 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_client_subnet_ipv4:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("IPv4 subnet length expected"); - else if (atoi($2) > 32) - cfg_parser->cfg->max_client_subnet_ipv4 = 32; - else if (atoi($2) < 0) - cfg_parser->cfg->max_client_subnet_ipv4 = 0; - else cfg_parser->cfg->max_client_subnet_ipv4 = (uint8_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_max_client_subnet_ipv6: VAR_MAX_CLIENT_SUBNET_IPV6 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_client_subnet_ipv6:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("Ipv6 subnet length expected"); - else if (atoi($2) > 128) - cfg_parser->cfg->max_client_subnet_ipv6 = 128; - else if (atoi($2) < 0) - cfg_parser->cfg->max_client_subnet_ipv6 = 0; - else cfg_parser->cfg->max_client_subnet_ipv6 = (uint8_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_min_client_subnet_ipv4: VAR_MIN_CLIENT_SUBNET_IPV4 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(min_client_subnet_ipv4:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("IPv4 subnet length expected"); - else if (atoi($2) > 32) - cfg_parser->cfg->min_client_subnet_ipv4 = 32; - else if (atoi($2) < 0) - cfg_parser->cfg->min_client_subnet_ipv4 = 0; - else cfg_parser->cfg->min_client_subnet_ipv4 = (uint8_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_min_client_subnet_ipv6: VAR_MIN_CLIENT_SUBNET_IPV6 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(min_client_subnet_ipv6:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("Ipv6 subnet length expected"); - else if (atoi($2) > 128) - cfg_parser->cfg->min_client_subnet_ipv6 = 128; - else if (atoi($2) < 0) - cfg_parser->cfg->min_client_subnet_ipv6 = 0; - else cfg_parser->cfg->min_client_subnet_ipv6 = (uint8_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_max_ecs_tree_size_ipv4: VAR_MAX_ECS_TREE_SIZE_IPV4 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_ecs_tree_size_ipv4:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("IPv4 ECS tree size expected"); - else if (atoi($2) < 0) - cfg_parser->cfg->max_ecs_tree_size_ipv4 = 0; - else cfg_parser->cfg->max_ecs_tree_size_ipv4 = (uint32_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_max_ecs_tree_size_ipv6: VAR_MAX_ECS_TREE_SIZE_IPV6 STRING_ARG - { - #ifdef CLIENT_SUBNET - OUTYY(("P(max_ecs_tree_size_ipv6:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("IPv6 ECS tree size expected"); - else if (atoi($2) < 0) - cfg_parser->cfg->max_ecs_tree_size_ipv6 = 0; - else cfg_parser->cfg->max_ecs_tree_size_ipv6 = (uint32_t)atoi($2); - #else - OUTYY(("P(Compiled without edns subnet option, ignoring)\n")); - #endif - free($2); - } - ; -server_interface: VAR_INTERFACE STRING_ARG - { - OUTYY(("P(server_interface:%s)\n", $2)); - if(cfg_parser->cfg->num_ifs == 0) - cfg_parser->cfg->ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, - (cfg_parser->cfg->num_ifs+1)*sizeof(char*)); - if(!cfg_parser->cfg->ifs) - yyerror("out of memory"); - else - cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = $2; - } - ; -server_outgoing_interface: VAR_OUTGOING_INTERFACE STRING_ARG - { - OUTYY(("P(server_outgoing_interface:%s)\n", $2)); - if(cfg_parser->cfg->num_out_ifs == 0) - cfg_parser->cfg->out_ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->out_ifs = realloc( - cfg_parser->cfg->out_ifs, - (cfg_parser->cfg->num_out_ifs+1)*sizeof(char*)); - if(!cfg_parser->cfg->out_ifs) - yyerror("out of memory"); - else - cfg_parser->cfg->out_ifs[ - cfg_parser->cfg->num_out_ifs++] = $2; - } - ; -server_outgoing_range: VAR_OUTGOING_RANGE STRING_ARG - { - OUTYY(("P(server_outgoing_range:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_num_ports = atoi($2); - free($2); - } - ; -server_outgoing_port_permit: VAR_OUTGOING_PORT_PERMIT STRING_ARG - { - OUTYY(("P(server_outgoing_port_permit:%s)\n", $2)); - if(!cfg_mark_ports($2, 1, - cfg_parser->cfg->outgoing_avail_ports, 65536)) - yyerror("port number or range (\"low-high\") expected"); - free($2); - } - ; -server_outgoing_port_avoid: VAR_OUTGOING_PORT_AVOID STRING_ARG - { - OUTYY(("P(server_outgoing_port_avoid:%s)\n", $2)); - if(!cfg_mark_ports($2, 0, - cfg_parser->cfg->outgoing_avail_ports, 65536)) - yyerror("port number or range (\"low-high\") expected"); - free($2); - } - ; -server_outgoing_num_tcp: VAR_OUTGOING_NUM_TCP STRING_ARG - { - OUTYY(("P(server_outgoing_num_tcp:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_num_tcp = atoi($2); - free($2); - } - ; -server_incoming_num_tcp: VAR_INCOMING_NUM_TCP STRING_ARG - { - OUTYY(("P(server_incoming_num_tcp:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->incoming_num_tcp = atoi($2); - free($2); - } - ; -server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG - { - OUTYY(("P(server_interface_automatic:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->if_automatic = (strcmp($2, "yes")==0); - free($2); - } - ; -server_interface_automatic_ports: VAR_INTERFACE_AUTOMATIC_PORTS STRING_ARG - { - OUTYY(("P(server_interface_automatic_ports:%s)\n", $2)); - free(cfg_parser->cfg->if_automatic_ports); - cfg_parser->cfg->if_automatic_ports = $2; - } - ; -server_do_ip4: VAR_DO_IP4 STRING_ARG - { - OUTYY(("P(server_do_ip4:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_ip4 = (strcmp($2, "yes")==0); - free($2); - } - ; -server_do_ip6: VAR_DO_IP6 STRING_ARG - { - OUTYY(("P(server_do_ip6:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_ip6 = (strcmp($2, "yes")==0); - free($2); - } - ; -server_do_nat64: VAR_DO_NAT64 STRING_ARG - { - OUTYY(("P(server_do_nat64:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_nat64 = (strcmp($2, "yes")==0); - free($2); - } - ; -server_do_udp: VAR_DO_UDP STRING_ARG - { - OUTYY(("P(server_do_udp:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_udp = (strcmp($2, "yes")==0); - free($2); - } - ; -server_do_tcp: VAR_DO_TCP STRING_ARG - { - OUTYY(("P(server_do_tcp:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_tcp = (strcmp($2, "yes")==0); - free($2); - } - ; -server_prefer_ip4: VAR_PREFER_IP4 STRING_ARG - { - OUTYY(("P(server_prefer_ip4:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefer_ip4 = (strcmp($2, "yes")==0); - free($2); - } - ; -server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG - { - OUTYY(("P(server_prefer_ip6:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefer_ip6 = (strcmp($2, "yes")==0); - free($2); - } - ; -server_tcp_mss: VAR_TCP_MSS STRING_ARG - { - OUTYY(("P(server_tcp_mss:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->tcp_mss = atoi($2); - free($2); - } - ; -server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING_ARG - { - OUTYY(("P(server_outgoing_tcp_mss:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outgoing_tcp_mss = atoi($2); - free($2); - } - ; -server_tcp_idle_timeout: VAR_TCP_IDLE_TIMEOUT STRING_ARG - { - OUTYY(("P(server_tcp_idle_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) > 120000) - cfg_parser->cfg->tcp_idle_timeout = 120000; - else if (atoi($2) < 1) - cfg_parser->cfg->tcp_idle_timeout = 1; - else cfg_parser->cfg->tcp_idle_timeout = atoi($2); - free($2); - } - ; -server_max_reuse_tcp_queries: VAR_MAX_REUSE_TCP_QUERIES STRING_ARG - { - OUTYY(("P(server_max_reuse_tcp_queries:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) < 1) - cfg_parser->cfg->max_reuse_tcp_queries = 0; - else cfg_parser->cfg->max_reuse_tcp_queries = atoi($2); - free($2); - } - ; -server_tcp_reuse_timeout: VAR_TCP_REUSE_TIMEOUT STRING_ARG - { - OUTYY(("P(server_tcp_reuse_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) < 1) - cfg_parser->cfg->tcp_reuse_timeout = 0; - else cfg_parser->cfg->tcp_reuse_timeout = atoi($2); - free($2); - } - ; -server_tcp_auth_query_timeout: VAR_TCP_AUTH_QUERY_TIMEOUT STRING_ARG - { - OUTYY(("P(server_tcp_auth_query_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) < 1) - cfg_parser->cfg->tcp_auth_query_timeout = 0; - else cfg_parser->cfg->tcp_auth_query_timeout = atoi($2); - free($2); - } - ; -server_tcp_keepalive: VAR_EDNS_TCP_KEEPALIVE STRING_ARG - { - OUTYY(("P(server_tcp_keepalive:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_tcp_keepalive = (strcmp($2, "yes")==0); - free($2); - } - ; -server_tcp_keepalive_timeout: VAR_EDNS_TCP_KEEPALIVE_TIMEOUT STRING_ARG - { - OUTYY(("P(server_tcp_keepalive_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) > 6553500) - cfg_parser->cfg->tcp_keepalive_timeout = 6553500; - else if (atoi($2) < 1) - cfg_parser->cfg->tcp_keepalive_timeout = 0; - else cfg_parser->cfg->tcp_keepalive_timeout = atoi($2); - free($2); - } - ; -server_sock_queue_timeout: VAR_SOCK_QUEUE_TIMEOUT STRING_ARG - { - OUTYY(("P(server_sock_queue_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) > 6553500) - cfg_parser->cfg->sock_queue_timeout = 6553500; - else if (atoi($2) < 1) - cfg_parser->cfg->sock_queue_timeout = 0; - else cfg_parser->cfg->sock_queue_timeout = atoi($2); - free($2); - } - ; -server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG - { - OUTYY(("P(server_tcp_upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tcp_upstream = (strcmp($2, "yes")==0); - free($2); - } - ; -server_udp_upstream_without_downstream: VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM STRING_ARG - { - OUTYY(("P(server_udp_upstream_without_downstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->udp_upstream_without_downstream = (strcmp($2, "yes")==0); - free($2); - } - ; -server_ssl_upstream: VAR_SSL_UPSTREAM STRING_ARG - { - OUTYY(("P(server_ssl_upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ssl_upstream = (strcmp($2, "yes")==0); - free($2); - } - ; -server_ssl_service_key: VAR_SSL_SERVICE_KEY STRING_ARG - { - OUTYY(("P(server_ssl_service_key:%s)\n", $2)); - free(cfg_parser->cfg->ssl_service_key); - cfg_parser->cfg->ssl_service_key = $2; - } - ; -server_ssl_service_pem: VAR_SSL_SERVICE_PEM STRING_ARG - { - OUTYY(("P(server_ssl_service_pem:%s)\n", $2)); - free(cfg_parser->cfg->ssl_service_pem); - cfg_parser->cfg->ssl_service_pem = $2; - } - ; -server_ssl_port: VAR_SSL_PORT STRING_ARG - { - OUTYY(("P(server_ssl_port:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->ssl_port = atoi($2); - free($2); - } - ; -server_tls_cert_bundle: VAR_TLS_CERT_BUNDLE STRING_ARG - { - OUTYY(("P(server_tls_cert_bundle:%s)\n", $2)); - free(cfg_parser->cfg->tls_cert_bundle); - cfg_parser->cfg->tls_cert_bundle = $2; - } - ; -server_tls_win_cert: VAR_TLS_WIN_CERT STRING_ARG - { - OUTYY(("P(server_tls_win_cert:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tls_win_cert = (strcmp($2, "yes")==0); - free($2); - } - ; -server_tls_additional_port: VAR_TLS_ADDITIONAL_PORT STRING_ARG - { - OUTYY(("P(server_tls_additional_port:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->tls_additional_port, - $2)) - yyerror("out of memory"); - } - ; -server_tls_ciphers: VAR_TLS_CIPHERS STRING_ARG - { - OUTYY(("P(server_tls_ciphers:%s)\n", $2)); - free(cfg_parser->cfg->tls_ciphers); - cfg_parser->cfg->tls_ciphers = $2; - } - ; -server_tls_ciphersuites: VAR_TLS_CIPHERSUITES STRING_ARG - { - OUTYY(("P(server_tls_ciphersuites:%s)\n", $2)); - free(cfg_parser->cfg->tls_ciphersuites); - cfg_parser->cfg->tls_ciphersuites = $2; - } - ; -server_tls_session_ticket_keys: VAR_TLS_SESSION_TICKET_KEYS STRING_ARG - { - OUTYY(("P(server_tls_session_ticket_keys:%s)\n", $2)); - if(!cfg_strlist_append(&cfg_parser->cfg->tls_session_ticket_keys, - $2)) - yyerror("out of memory"); - } - ; -server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG - { - OUTYY(("P(server_tls_use_sni:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->tls_use_sni = (strcmp($2, "yes")==0); - free($2); - } - ; -server_https_port: VAR_HTTPS_PORT STRING_ARG - { - OUTYY(("P(server_https_port:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->https_port = atoi($2); - free($2); - }; -server_http_endpoint: VAR_HTTP_ENDPOINT STRING_ARG - { - OUTYY(("P(server_http_endpoint:%s)\n", $2)); - free(cfg_parser->cfg->http_endpoint); - if($2 && $2[0] != '/') { - cfg_parser->cfg->http_endpoint = malloc(strlen($2)+2); - if(!cfg_parser->cfg->http_endpoint) - yyerror("out of memory"); - cfg_parser->cfg->http_endpoint[0] = '/'; - memmove(cfg_parser->cfg->http_endpoint+1, $2, - strlen($2)+1); - free($2); - } else { - cfg_parser->cfg->http_endpoint = $2; - } - }; -server_http_max_streams: VAR_HTTP_MAX_STREAMS STRING_ARG - { - OUTYY(("P(server_http_max_streams:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->http_max_streams = atoi($2); - free($2); - }; -server_http_query_buffer_size: VAR_HTTP_QUERY_BUFFER_SIZE STRING_ARG - { - OUTYY(("P(server_http_query_buffer_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, - &cfg_parser->cfg->http_query_buffer_size)) - yyerror("memory size expected"); - free($2); - }; -server_http_response_buffer_size: VAR_HTTP_RESPONSE_BUFFER_SIZE STRING_ARG - { - OUTYY(("P(server_http_response_buffer_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, - &cfg_parser->cfg->http_response_buffer_size)) - yyerror("memory size expected"); - free($2); - }; -server_http_nodelay: VAR_HTTP_NODELAY STRING_ARG - { - OUTYY(("P(server_http_nodelay:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->http_nodelay = (strcmp($2, "yes")==0); - free($2); - }; -server_http_notls_downstream: VAR_HTTP_NOTLS_DOWNSTREAM STRING_ARG - { - OUTYY(("P(server_http_notls_downstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->http_notls_downstream = (strcmp($2, "yes")==0); - free($2); - }; -server_use_systemd: VAR_USE_SYSTEMD STRING_ARG - { - OUTYY(("P(server_use_systemd:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_systemd = (strcmp($2, "yes")==0); - free($2); - } - ; -server_do_daemonize: VAR_DO_DAEMONIZE STRING_ARG - { - OUTYY(("P(server_do_daemonize:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_daemonize = (strcmp($2, "yes")==0); - free($2); - } - ; -server_use_syslog: VAR_USE_SYSLOG STRING_ARG - { - OUTYY(("P(server_use_syslog:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_syslog = (strcmp($2, "yes")==0); -#if !defined(HAVE_SYSLOG_H) && !defined(UB_ON_WINDOWS) - if(strcmp($2, "yes") == 0) - yyerror("no syslog services are available. " - "(reconfigure and compile to add)"); -#endif - free($2); - } - ; -server_log_time_ascii: VAR_LOG_TIME_ASCII STRING_ARG - { - OUTYY(("P(server_log_time_ascii:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_time_ascii = (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_queries: VAR_LOG_QUERIES STRING_ARG - { - OUTYY(("P(server_log_queries:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_queries = (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_replies: VAR_LOG_REPLIES STRING_ARG - { - OUTYY(("P(server_log_replies:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_replies = (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_tag_queryreply: VAR_LOG_TAG_QUERYREPLY STRING_ARG - { - OUTYY(("P(server_log_tag_queryreply:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_tag_queryreply = (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG - { - OUTYY(("P(server_log_servfail:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_servfail = (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG - { - OUTYY(("P(server_log_local_actions:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_local_actions = (strcmp($2, "yes")==0); - free($2); - } - ; -server_chroot: VAR_CHROOT STRING_ARG - { - OUTYY(("P(server_chroot:%s)\n", $2)); - free(cfg_parser->cfg->chrootdir); - cfg_parser->cfg->chrootdir = $2; - } - ; -server_username: VAR_USERNAME STRING_ARG - { - OUTYY(("P(server_username:%s)\n", $2)); - free(cfg_parser->cfg->username); - cfg_parser->cfg->username = $2; - } - ; -server_directory: VAR_DIRECTORY STRING_ARG - { - OUTYY(("P(server_directory:%s)\n", $2)); - free(cfg_parser->cfg->directory); - cfg_parser->cfg->directory = $2; - /* change there right away for includes relative to this */ - if($2[0]) { - char* d; -#ifdef UB_ON_WINDOWS - w_config_adjust_directory(cfg_parser->cfg); -#endif - d = cfg_parser->cfg->directory; - /* adjust directory if we have already chroot, - * like, we reread after sighup */ - if(cfg_parser->chroot && cfg_parser->chroot[0] && - strncmp(d, cfg_parser->chroot, strlen( - cfg_parser->chroot)) == 0) - d += strlen(cfg_parser->chroot); - if(d[0]) { - if(chdir(d)) - log_err("cannot chdir to directory: %s (%s)", - d, strerror(errno)); - } - } - } - ; -server_logfile: VAR_LOGFILE STRING_ARG - { - OUTYY(("P(server_logfile:%s)\n", $2)); - free(cfg_parser->cfg->logfile); - cfg_parser->cfg->logfile = $2; - cfg_parser->cfg->use_syslog = 0; - } - ; -server_pidfile: VAR_PIDFILE STRING_ARG - { - OUTYY(("P(server_pidfile:%s)\n", $2)); - free(cfg_parser->cfg->pidfile); - cfg_parser->cfg->pidfile = $2; - } - ; -server_root_hints: VAR_ROOT_HINTS STRING_ARG - { - OUTYY(("P(server_root_hints:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->root_hints, $2)) - yyerror("out of memory"); - } - ; -server_dlv_anchor_file: VAR_DLV_ANCHOR_FILE STRING_ARG - { - OUTYY(("P(server_dlv_anchor_file:%s)\n", $2)); - log_warn("option dlv-anchor-file ignored: DLV is decommissioned"); - free($2); - } - ; -server_dlv_anchor: VAR_DLV_ANCHOR STRING_ARG - { - OUTYY(("P(server_dlv_anchor:%s)\n", $2)); - log_warn("option dlv-anchor ignored: DLV is decommissioned"); - free($2); - } - ; -server_auto_trust_anchor_file: VAR_AUTO_TRUST_ANCHOR_FILE STRING_ARG - { - OUTYY(("P(server_auto_trust_anchor_file:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - auto_trust_anchor_file_list, $2)) - yyerror("out of memory"); - } - ; -server_trust_anchor_file: VAR_TRUST_ANCHOR_FILE STRING_ARG - { - OUTYY(("P(server_trust_anchor_file:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - trust_anchor_file_list, $2)) - yyerror("out of memory"); - } - ; -server_trusted_keys_file: VAR_TRUSTED_KEYS_FILE STRING_ARG - { - OUTYY(("P(server_trusted_keys_file:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg-> - trusted_keys_file_list, $2)) - yyerror("out of memory"); - } - ; -server_trust_anchor: VAR_TRUST_ANCHOR STRING_ARG - { - OUTYY(("P(server_trust_anchor:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->trust_anchor_list, $2)) - yyerror("out of memory"); - } - ; -server_trust_anchor_signaling: VAR_TRUST_ANCHOR_SIGNALING STRING_ARG - { - OUTYY(("P(server_trust_anchor_signaling:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->trust_anchor_signaling = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_root_key_sentinel: VAR_ROOT_KEY_SENTINEL STRING_ARG - { - OUTYY(("P(server_root_key_sentinel:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->root_key_sentinel = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_domain_insecure: VAR_DOMAIN_INSECURE STRING_ARG - { - OUTYY(("P(server_domain_insecure:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->domain_insecure, $2)) - yyerror("out of memory"); - } - ; -server_hide_identity: VAR_HIDE_IDENTITY STRING_ARG - { - OUTYY(("P(server_hide_identity:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_identity = (strcmp($2, "yes")==0); - free($2); - } - ; -server_hide_version: VAR_HIDE_VERSION STRING_ARG - { - OUTYY(("P(server_hide_version:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_version = (strcmp($2, "yes")==0); - free($2); - } - ; -server_hide_trustanchor: VAR_HIDE_TRUSTANCHOR STRING_ARG - { - OUTYY(("P(server_hide_trustanchor:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_trustanchor = (strcmp($2, "yes")==0); - free($2); - } - ; -server_hide_http_user_agent: VAR_HIDE_HTTP_USER_AGENT STRING_ARG - { - OUTYY(("P(server_hide_user_agent:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->hide_http_user_agent = (strcmp($2, "yes")==0); - free($2); - } - ; -server_identity: VAR_IDENTITY STRING_ARG - { - OUTYY(("P(server_identity:%s)\n", $2)); - free(cfg_parser->cfg->identity); - cfg_parser->cfg->identity = $2; - } - ; -server_version: VAR_VERSION STRING_ARG - { - OUTYY(("P(server_version:%s)\n", $2)); - free(cfg_parser->cfg->version); - cfg_parser->cfg->version = $2; - } - ; -server_http_user_agent: VAR_HTTP_USER_AGENT STRING_ARG - { - OUTYY(("P(server_http_user_agent:%s)\n", $2)); - free(cfg_parser->cfg->http_user_agent); - cfg_parser->cfg->http_user_agent = $2; - } - ; -server_nsid: VAR_NSID STRING_ARG - { - OUTYY(("P(server_nsid:%s)\n", $2)); - free(cfg_parser->cfg->nsid_cfg_str); - cfg_parser->cfg->nsid_cfg_str = $2; - free(cfg_parser->cfg->nsid); - cfg_parser->cfg->nsid = NULL; - cfg_parser->cfg->nsid_len = 0; - if (*$2 == 0) - ; /* pass; empty string is not setting nsid */ - else if (!(cfg_parser->cfg->nsid = cfg_parse_nsid( - $2, &cfg_parser->cfg->nsid_len))) - yyerror("the NSID must be either a hex string or an " - "ascii character string prepended with ascii_."); - } - ; -server_so_rcvbuf: VAR_SO_RCVBUF STRING_ARG - { - OUTYY(("P(server_so_rcvbuf:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->so_rcvbuf)) - yyerror("buffer size expected"); - free($2); - } - ; -server_so_sndbuf: VAR_SO_SNDBUF STRING_ARG - { - OUTYY(("P(server_so_sndbuf:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->so_sndbuf)) - yyerror("buffer size expected"); - free($2); - } - ; -server_so_reuseport: VAR_SO_REUSEPORT STRING_ARG - { - OUTYY(("P(server_so_reuseport:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->so_reuseport = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG - { - OUTYY(("P(server_ip_transparent:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_transparent = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_ip_freebind: VAR_IP_FREEBIND STRING_ARG - { - OUTYY(("P(server_ip_freebind:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_freebind = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_ip_dscp: VAR_IP_DSCP STRING_ARG - { - OUTYY(("P(server_ip_dscp:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else if (atoi($2) > 63) - yyerror("value too large (max 63)"); - else if (atoi($2) < 0) - yyerror("value too small (min 0)"); - else - cfg_parser->cfg->ip_dscp = atoi($2); - free($2); - } - ; -server_stream_wait_size: VAR_STREAM_WAIT_SIZE STRING_ARG - { - OUTYY(("P(server_stream_wait_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->stream_wait_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG - { - OUTYY(("P(server_edns_buffer_size:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else if (atoi($2) < 12) - yyerror("edns buffer size too small"); - else if (atoi($2) > 65535) - cfg_parser->cfg->edns_buffer_size = 65535; - else cfg_parser->cfg->edns_buffer_size = atoi($2); - free($2); - } - ; -server_msg_buffer_size: VAR_MSG_BUFFER_SIZE STRING_ARG - { - OUTYY(("P(server_msg_buffer_size:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else if (atoi($2) < 4096) - yyerror("message buffer size too small (use 4096)"); - else cfg_parser->cfg->msg_buffer_size = atoi($2); - free($2); - } - ; -server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING_ARG - { - OUTYY(("P(server_msg_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->msg_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_msg_cache_slabs: VAR_MSG_CACHE_SLABS STRING_ARG - { - OUTYY(("P(server_msg_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->msg_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->msg_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_num_queries_per_thread: VAR_NUM_QUERIES_PER_THREAD STRING_ARG - { - OUTYY(("P(server_num_queries_per_thread:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->num_queries_per_thread = atoi($2); - free($2); - } - ; -server_jostle_timeout: VAR_JOSTLE_TIMEOUT STRING_ARG - { - OUTYY(("P(server_jostle_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->jostle_time = atoi($2); - free($2); - } - ; -server_delay_close: VAR_DELAY_CLOSE STRING_ARG - { - OUTYY(("P(server_delay_close:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->delay_close = atoi($2); - free($2); - } - ; -server_udp_connect: VAR_UDP_CONNECT STRING_ARG - { - OUTYY(("P(server_udp_connect:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->udp_connect = (strcmp($2, "yes")==0); - free($2); - } - ; -server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG - { - OUTYY(("P(server_unblock_lan_zones:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->unblock_lan_zones = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG - { - OUTYY(("P(server_insecure_lan_zones:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->insecure_lan_zones = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG - { - OUTYY(("P(server_rrset_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->rrset_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_rrset_cache_slabs: VAR_RRSET_CACHE_SLABS STRING_ARG - { - OUTYY(("P(server_rrset_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->rrset_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->rrset_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_infra_host_ttl: VAR_INFRA_HOST_TTL STRING_ARG - { - OUTYY(("P(server_infra_host_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->host_ttl = atoi($2); - free($2); - } - ; -server_infra_lame_ttl: VAR_INFRA_LAME_TTL STRING_ARG - { - OUTYY(("P(server_infra_lame_ttl:%s)\n", $2)); - verbose(VERB_DETAIL, "ignored infra-lame-ttl: %s (option " - "removed, use infra-host-ttl)", $2); - free($2); - } - ; -server_infra_cache_numhosts: VAR_INFRA_CACHE_NUMHOSTS STRING_ARG - { - OUTYY(("P(server_infra_cache_numhosts:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_numhosts = atoi($2); - free($2); - } - ; -server_infra_cache_lame_size: VAR_INFRA_CACHE_LAME_SIZE STRING_ARG - { - OUTYY(("P(server_infra_cache_lame_size:%s)\n", $2)); - verbose(VERB_DETAIL, "ignored infra-cache-lame-size: %s " - "(option removed, use infra-cache-numhosts)", $2); - free($2); - } - ; -server_infra_cache_slabs: VAR_INFRA_CACHE_SLABS STRING_ARG - { - OUTYY(("P(server_infra_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->infra_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->infra_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_infra_cache_min_rtt: VAR_INFRA_CACHE_MIN_RTT STRING_ARG - { - OUTYY(("P(server_infra_cache_min_rtt:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_min_rtt = atoi($2); - free($2); - } - ; -server_infra_cache_max_rtt: VAR_INFRA_CACHE_MAX_RTT STRING_ARG - { - OUTYY(("P(server_infra_cache_max_rtt:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->infra_cache_max_rtt = atoi($2); - free($2); - } - ; -server_infra_keep_probing: VAR_INFRA_KEEP_PROBING STRING_ARG - { - OUTYY(("P(server_infra_keep_probing:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->infra_keep_probing = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_target_fetch_policy: VAR_TARGET_FETCH_POLICY STRING_ARG - { - OUTYY(("P(server_target_fetch_policy:%s)\n", $2)); - free(cfg_parser->cfg->target_fetch_policy); - cfg_parser->cfg->target_fetch_policy = $2; - } - ; -server_harden_short_bufsize: VAR_HARDEN_SHORT_BUFSIZE STRING_ARG - { - OUTYY(("P(server_harden_short_bufsize:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_short_bufsize = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING_ARG - { - OUTYY(("P(server_harden_large_queries:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_large_queries = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_glue: VAR_HARDEN_GLUE STRING_ARG - { - OUTYY(("P(server_harden_glue:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_glue = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_dnssec_stripped: VAR_HARDEN_DNSSEC_STRIPPED STRING_ARG - { - OUTYY(("P(server_harden_dnssec_stripped:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_dnssec_stripped = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_below_nxdomain: VAR_HARDEN_BELOW_NXDOMAIN STRING_ARG - { - OUTYY(("P(server_harden_below_nxdomain:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_below_nxdomain = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_referral_path: VAR_HARDEN_REFERRAL_PATH STRING_ARG - { - OUTYY(("P(server_harden_referral_path:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_referral_path = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_algo_downgrade: VAR_HARDEN_ALGO_DOWNGRADE STRING_ARG - { - OUTYY(("P(server_harden_algo_downgrade:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_algo_downgrade = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_harden_unknown_additional: VAR_HARDEN_UNKNOWN_ADDITIONAL STRING_ARG - { - OUTYY(("P(server_harden_unknown_additional:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->harden_unknown_additional = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG - { - OUTYY(("P(server_use_caps_for_id:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->use_caps_bits_for_id = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG - { - OUTYY(("P(server_caps_whitelist:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, $2)) - yyerror("out of memory"); - } - ; -server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG - { - OUTYY(("P(server_private_address:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->private_address, $2)) - yyerror("out of memory"); - } - ; -server_private_domain: VAR_PRIVATE_DOMAIN STRING_ARG - { - OUTYY(("P(server_private_domain:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->private_domain, $2)) - yyerror("out of memory"); - } - ; -server_prefetch: VAR_PREFETCH STRING_ARG - { - OUTYY(("P(server_prefetch:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefetch = (strcmp($2, "yes")==0); - free($2); - } - ; -server_prefetch_key: VAR_PREFETCH_KEY STRING_ARG - { - OUTYY(("P(server_prefetch_key:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->prefetch_key = (strcmp($2, "yes")==0); - free($2); - } - ; -server_deny_any: VAR_DENY_ANY STRING_ARG - { - OUTYY(("P(server_deny_any:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->deny_any = (strcmp($2, "yes")==0); - free($2); - } - ; -server_unwanted_reply_threshold: VAR_UNWANTED_REPLY_THRESHOLD STRING_ARG - { - OUTYY(("P(server_unwanted_reply_threshold:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->unwanted_threshold = atoi($2); - free($2); - } - ; -server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING_ARG - { - OUTYY(("P(server_do_not_query_address:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, $2)) - yyerror("out of memory"); - } - ; -server_do_not_query_localhost: VAR_DO_NOT_QUERY_LOCALHOST STRING_ARG - { - OUTYY(("P(server_do_not_query_localhost:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->donotquery_localhost = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_access_control: VAR_ACCESS_CONTROL STRING_ARG STRING_ARG - { - OUTYY(("P(server_access_control:%s %s)\n", $2, $3)); - validate_acl_action($3); - if(!cfg_str2list_insert(&cfg_parser->cfg->acls, $2, $3)) - fatal_exit("out of memory adding acl"); - } - ; -server_interface_action: VAR_INTERFACE_ACTION STRING_ARG STRING_ARG - { - OUTYY(("P(server_interface_action:%s %s)\n", $2, $3)); - validate_acl_action($3); - if(!cfg_str2list_insert( - &cfg_parser->cfg->interface_actions, $2, $3)) - fatal_exit("out of memory adding acl"); - } - ; -server_module_conf: VAR_MODULE_CONF STRING_ARG - { - OUTYY(("P(server_module_conf:%s)\n", $2)); - free(cfg_parser->cfg->module_conf); - cfg_parser->cfg->module_conf = $2; - } - ; -server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG - { - OUTYY(("P(server_val_override_date:%s)\n", $2)); - if(*$2 == '\0' || strcmp($2, "0") == 0) { - cfg_parser->cfg->val_date_override = 0; - } else if(strlen($2) == 14) { - cfg_parser->cfg->val_date_override = - cfg_convert_timeval($2); - if(!cfg_parser->cfg->val_date_override) - yyerror("bad date/time specification"); - } else { - if(atoi($2) == 0) - yyerror("number expected"); - cfg_parser->cfg->val_date_override = atoi($2); - } - free($2); - } - ; -server_val_sig_skew_min: VAR_VAL_SIG_SKEW_MIN STRING_ARG - { - OUTYY(("P(server_val_sig_skew_min:%s)\n", $2)); - if(*$2 == '\0' || strcmp($2, "0") == 0) { - cfg_parser->cfg->val_sig_skew_min = 0; - } else { - cfg_parser->cfg->val_sig_skew_min = atoi($2); - if(!cfg_parser->cfg->val_sig_skew_min) - yyerror("number expected"); - } - free($2); - } - ; -server_val_sig_skew_max: VAR_VAL_SIG_SKEW_MAX STRING_ARG - { - OUTYY(("P(server_val_sig_skew_max:%s)\n", $2)); - if(*$2 == '\0' || strcmp($2, "0") == 0) { - cfg_parser->cfg->val_sig_skew_max = 0; - } else { - cfg_parser->cfg->val_sig_skew_max = atoi($2); - if(!cfg_parser->cfg->val_sig_skew_max) - yyerror("number expected"); - } - free($2); - } - ; -server_val_max_restart: VAR_VAL_MAX_RESTART STRING_ARG - { - OUTYY(("P(server_val_max_restart:%s)\n", $2)); - if(*$2 == '\0' || strcmp($2, "0") == 0) { - cfg_parser->cfg->val_max_restart = 0; - } else { - cfg_parser->cfg->val_max_restart = atoi($2); - if(!cfg_parser->cfg->val_max_restart) - yyerror("number expected"); - } - free($2); - } - ; -server_cache_max_ttl: VAR_CACHE_MAX_TTL STRING_ARG - { - OUTYY(("P(server_cache_max_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_ttl = atoi($2); - free($2); - } - ; -server_cache_max_negative_ttl: VAR_CACHE_MAX_NEGATIVE_TTL STRING_ARG - { - OUTYY(("P(server_cache_max_negative_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_negative_ttl = atoi($2); - free($2); - } - ; -server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG - { - OUTYY(("P(server_cache_min_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->min_ttl = atoi($2); - free($2); - } - ; -server_bogus_ttl: VAR_BOGUS_TTL STRING_ARG - { - OUTYY(("P(server_bogus_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->bogus_ttl = atoi($2); - free($2); - } - ; -server_val_clean_additional: VAR_VAL_CLEAN_ADDITIONAL STRING_ARG - { - OUTYY(("P(server_val_clean_additional:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->val_clean_additional = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_val_permissive_mode: VAR_VAL_PERMISSIVE_MODE STRING_ARG - { - OUTYY(("P(server_val_permissive_mode:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->val_permissive_mode = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_aggressive_nsec: VAR_AGGRESSIVE_NSEC STRING_ARG - { - OUTYY(("P(server_aggressive_nsec:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else - cfg_parser->cfg->aggressive_nsec = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG - { - OUTYY(("P(server_ignore_cd_flag:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ignore_cd = (strcmp($2, "yes")==0); - free($2); - } - ; -server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG - { - OUTYY(("P(server_serve_expired:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_expired = (strcmp($2, "yes")==0); - free($2); - } - ; -server_serve_expired_ttl: VAR_SERVE_EXPIRED_TTL STRING_ARG - { - OUTYY(("P(server_serve_expired_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_ttl = atoi($2); - free($2); - } - ; -server_serve_expired_ttl_reset: VAR_SERVE_EXPIRED_TTL_RESET STRING_ARG - { - OUTYY(("P(server_serve_expired_ttl_reset:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_expired_ttl_reset = (strcmp($2, "yes")==0); - free($2); - } - ; -server_serve_expired_reply_ttl: VAR_SERVE_EXPIRED_REPLY_TTL STRING_ARG - { - OUTYY(("P(server_serve_expired_reply_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_reply_ttl = atoi($2); - free($2); - } - ; -server_serve_expired_client_timeout: VAR_SERVE_EXPIRED_CLIENT_TIMEOUT STRING_ARG - { - OUTYY(("P(server_serve_expired_client_timeout:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->serve_expired_client_timeout = atoi($2); - free($2); - } - ; -server_ede_serve_expired: VAR_EDE_SERVE_EXPIRED STRING_ARG - { - OUTYY(("P(server_ede_serve_expired:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ede_serve_expired = (strcmp($2, "yes")==0); - free($2); - } - ; -server_serve_original_ttl: VAR_SERVE_ORIGINAL_TTL STRING_ARG - { - OUTYY(("P(server_serve_original_ttl:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->serve_original_ttl = (strcmp($2, "yes")==0); - free($2); - } - ; -server_fake_dsa: VAR_FAKE_DSA STRING_ARG - { - OUTYY(("P(server_fake_dsa:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); -#if defined(HAVE_SSL) || defined(HAVE_NETTLE) - else fake_dsa = (strcmp($2, "yes")==0); - if(fake_dsa) - log_warn("test option fake_dsa is enabled"); -#endif - free($2); - } - ; -server_fake_sha1: VAR_FAKE_SHA1 STRING_ARG - { - OUTYY(("P(server_fake_sha1:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); -#if defined(HAVE_SSL) || defined(HAVE_NETTLE) - else fake_sha1 = (strcmp($2, "yes")==0); - if(fake_sha1) - log_warn("test option fake_sha1 is enabled"); -#endif - free($2); - } - ; -server_val_log_level: VAR_VAL_LOG_LEVEL STRING_ARG - { - OUTYY(("P(server_val_log_level:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->val_log_level = atoi($2); - free($2); - } - ; -server_val_nsec3_keysize_iterations: VAR_VAL_NSEC3_KEYSIZE_ITERATIONS STRING_ARG - { - OUTYY(("P(server_val_nsec3_keysize_iterations:%s)\n", $2)); - free(cfg_parser->cfg->val_nsec3_key_iterations); - cfg_parser->cfg->val_nsec3_key_iterations = $2; - } - ; -server_zonemd_permissive_mode: VAR_ZONEMD_PERMISSIVE_MODE STRING_ARG - { - OUTYY(("P(server_zonemd_permissive_mode:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->zonemd_permissive_mode = (strcmp($2, "yes")==0); - free($2); - } - ; -server_add_holddown: VAR_ADD_HOLDDOWN STRING_ARG - { - OUTYY(("P(server_add_holddown:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->add_holddown = atoi($2); - free($2); - } - ; -server_del_holddown: VAR_DEL_HOLDDOWN STRING_ARG - { - OUTYY(("P(server_del_holddown:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->del_holddown = atoi($2); - free($2); - } - ; -server_keep_missing: VAR_KEEP_MISSING STRING_ARG - { - OUTYY(("P(server_keep_missing:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->keep_missing = atoi($2); - free($2); - } - ; -server_permit_small_holddown: VAR_PERMIT_SMALL_HOLDDOWN STRING_ARG - { - OUTYY(("P(server_permit_small_holddown:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->permit_small_holddown = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_key_cache_size: VAR_KEY_CACHE_SIZE STRING_ARG - { - OUTYY(("P(server_key_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->key_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_key_cache_slabs: VAR_KEY_CACHE_SLABS STRING_ARG - { - OUTYY(("P(server_key_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->key_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->key_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_neg_cache_size: VAR_NEG_CACHE_SIZE STRING_ARG - { - OUTYY(("P(server_neg_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->neg_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG - { - OUTYY(("P(server_local_zone:%s %s)\n", $2, $3)); - if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 && - strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 && - strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0 - && strcmp($3, "typetransparent")!=0 - && strcmp($3, "always_transparent")!=0 - && strcmp($3, "block_a")!=0 - && strcmp($3, "always_refuse")!=0 - && strcmp($3, "always_nxdomain")!=0 - && strcmp($3, "always_nodata")!=0 - && strcmp($3, "always_deny")!=0 - && strcmp($3, "always_null")!=0 - && strcmp($3, "noview")!=0 - && strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0 - && strcmp($3, "inform_redirect") != 0 - && strcmp($3, "ipset") != 0) { - yyerror("local-zone type: expected static, deny, " - "refuse, redirect, transparent, " - "typetransparent, inform, inform_deny, " - "inform_redirect, always_transparent, block_a," - "always_refuse, always_nxdomain, " - "always_nodata, always_deny, always_null, " - "noview, nodefault or ipset"); - free($2); - free($3); - } else if(strcmp($3, "nodefault")==0) { - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_zones_nodefault, $2)) - fatal_exit("out of memory adding local-zone"); - free($3); -#ifdef USE_IPSET - } else if(strcmp($3, "ipset")==0) { - size_t len = strlen($2); - /* Make sure to add the trailing dot. - * These are str compared to domain names. */ - if($2[len-1] != '.') { - if(!($2 = realloc($2, len+2))) { - fatal_exit("out of memory adding local-zone"); - } - $2[len] = '.'; - $2[len+1] = 0; - } - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_zones_ipset, $2)) - fatal_exit("out of memory adding local-zone"); - free($3); -#endif - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, - $2, $3)) - fatal_exit("out of memory adding local-zone"); - } - } - ; -server_local_data: VAR_LOCAL_DATA STRING_ARG - { - OUTYY(("P(server_local_data:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, $2)) - fatal_exit("out of memory adding local-data"); - } - ; -server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG - { - char* ptr; - OUTYY(("P(server_local_data_ptr:%s)\n", $2)); - ptr = cfg_ptr_reverse($2); - free($2); - if(ptr) { - if(!cfg_strlist_insert(&cfg_parser->cfg-> - local_data, ptr)) - fatal_exit("out of memory adding local-data"); - } else { - yyerror("local-data-ptr could not be reversed"); - } - } - ; -server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG - { - OUTYY(("P(server_minimal_responses:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->minimal_responses = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_rrset_roundrobin: VAR_RRSET_ROUNDROBIN STRING_ARG - { - OUTYY(("P(server_rrset_roundrobin:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->rrset_roundrobin = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_unknown_server_time_limit: VAR_UNKNOWN_SERVER_TIME_LIMIT STRING_ARG - { - OUTYY(("P(server_unknown_server_time_limit:%s)\n", $2)); - cfg_parser->cfg->unknown_server_time_limit = atoi($2); - free($2); - } - ; -server_max_udp_size: VAR_MAX_UDP_SIZE STRING_ARG - { - OUTYY(("P(server_max_udp_size:%s)\n", $2)); - cfg_parser->cfg->max_udp_size = atoi($2); - free($2); - } - ; -server_dns64_prefix: VAR_DNS64_PREFIX STRING_ARG - { - OUTYY(("P(dns64_prefix:%s)\n", $2)); - free(cfg_parser->cfg->dns64_prefix); - cfg_parser->cfg->dns64_prefix = $2; - } - ; -server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG - { - OUTYY(("P(server_dns64_synthall:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dns64_synthall = (strcmp($2, "yes")==0); - free($2); - } - ; -server_dns64_ignore_aaaa: VAR_DNS64_IGNORE_AAAA STRING_ARG - { - OUTYY(("P(dns64_ignore_aaaa:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->dns64_ignore_aaaa, - $2)) - fatal_exit("out of memory adding dns64-ignore-aaaa"); - } - ; -server_nat64_prefix: VAR_NAT64_PREFIX STRING_ARG - { - OUTYY(("P(nat64_prefix:%s)\n", $2)); - free(cfg_parser->cfg->nat64_prefix); - cfg_parser->cfg->nat64_prefix = $2; - } - ; -server_define_tag: VAR_DEFINE_TAG STRING_ARG - { - char* p, *s = $2; - OUTYY(("P(server_define_tag:%s)\n", $2)); - while((p=strsep(&s, " \t\n")) != NULL) { - if(*p) { - if(!config_add_tag(cfg_parser->cfg, p)) - yyerror("could not define-tag, " - "out of memory"); - } - } - free($2); - } - ; -server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3, - &len); - free($3); - OUTYY(("P(server_local_zone_tag:%s)\n", $2)); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free($2); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->local_zone_tags, - $2, bitlist, len)) { - yyerror("out of memory"); - free($2); - } - } - } - ; -server_access_control_tag: VAR_ACCESS_CONTROL_TAG STRING_ARG STRING_ARG - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3, - &len); - free($3); - OUTYY(("P(server_access_control_tag:%s)\n", $2)); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free($2); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->acl_tags, - $2, bitlist, len)) { - yyerror("out of memory"); - free($2); - } - } - } - ; -server_access_control_tag_action: VAR_ACCESS_CONTROL_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG - { - OUTYY(("P(server_access_control_tag_action:%s %s %s)\n", $2, $3, $4)); - if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_actions, - $2, $3, $4)) { - yyerror("out of memory"); - free($2); - free($3); - free($4); - } - } - ; -server_access_control_tag_data: VAR_ACCESS_CONTROL_TAG_DATA STRING_ARG STRING_ARG STRING_ARG - { - OUTYY(("P(server_access_control_tag_data:%s %s %s)\n", $2, $3, $4)); - if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_datas, - $2, $3, $4)) { - yyerror("out of memory"); - free($2); - free($3); - free($4); - } - } - ; -server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING_ARG - { - OUTYY(("P(server_local_zone_override:%s %s %s)\n", $2, $3, $4)); - if(!cfg_str3list_insert(&cfg_parser->cfg->local_zone_overrides, - $2, $3, $4)) { - yyerror("out of memory"); - free($2); - free($3); - free($4); - } - } - ; -server_access_control_view: VAR_ACCESS_CONTROL_VIEW STRING_ARG STRING_ARG - { - OUTYY(("P(server_access_control_view:%s %s)\n", $2, $3)); - if(!cfg_str2list_insert(&cfg_parser->cfg->acl_view, - $2, $3)) { - yyerror("out of memory"); - } - } - ; -server_interface_tag: VAR_INTERFACE_TAG STRING_ARG STRING_ARG - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3, - &len); - free($3); - OUTYY(("P(server_interface_tag:%s)\n", $2)); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free($2); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->interface_tags, - $2, bitlist, len)) { - yyerror("out of memory"); - free($2); - } - } - } - ; -server_interface_tag_action: VAR_INTERFACE_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG - { - OUTYY(("P(server_interface_tag_action:%s %s %s)\n", $2, $3, $4)); - if(!cfg_str3list_insert(&cfg_parser->cfg->interface_tag_actions, - $2, $3, $4)) { - yyerror("out of memory"); - free($2); - free($3); - free($4); - } - } - ; -server_interface_tag_data: VAR_INTERFACE_TAG_DATA STRING_ARG STRING_ARG STRING_ARG - { - OUTYY(("P(server_interface_tag_data:%s %s %s)\n", $2, $3, $4)); - if(!cfg_str3list_insert(&cfg_parser->cfg->interface_tag_datas, - $2, $3, $4)) { - yyerror("out of memory"); - free($2); - free($3); - free($4); - } - } - ; -server_interface_view: VAR_INTERFACE_VIEW STRING_ARG STRING_ARG - { - OUTYY(("P(server_interface_view:%s %s)\n", $2, $3)); - if(!cfg_str2list_insert(&cfg_parser->cfg->interface_view, - $2, $3)) { - yyerror("out of memory"); - } - } - ; -server_response_ip_tag: VAR_RESPONSE_IP_TAG STRING_ARG STRING_ARG - { - size_t len = 0; - uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3, - &len); - free($3); - OUTYY(("P(response_ip_tag:%s)\n", $2)); - if(!bitlist) { - yyerror("could not parse tags, (define-tag them first)"); - free($2); - } - if(bitlist) { - if(!cfg_strbytelist_insert( - &cfg_parser->cfg->respip_tags, - $2, bitlist, len)) { - yyerror("out of memory"); - free($2); - } - } - } - ; -server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG - { - OUTYY(("P(server_ip_ratelimit:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit = atoi($2); - free($2); - } - ; -server_ip_ratelimit_cookie: VAR_IP_RATELIMIT_COOKIE STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_cookie:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit_cookie = atoi($2); - free($2); - } - ; -server_ratelimit: VAR_RATELIMIT STRING_ARG - { - OUTYY(("P(server_ratelimit:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ratelimit = atoi($2); - free($2); - } - ; -server_ip_ratelimit_size: VAR_IP_RATELIMIT_SIZE STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->ip_ratelimit_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG - { - OUTYY(("P(server_ratelimit_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->ratelimit_size)) - yyerror("memory size expected"); - free($2); - } - ; -server_ip_ratelimit_slabs: VAR_IP_RATELIMIT_SLABS STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->ip_ratelimit_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG - { - OUTYY(("P(server_ratelimit_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->ratelimit_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->ratelimit_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -server_ratelimit_for_domain: VAR_RATELIMIT_FOR_DOMAIN STRING_ARG STRING_ARG - { - OUTYY(("P(server_ratelimit_for_domain:%s %s)\n", $2, $3)); - if(atoi($3) == 0 && strcmp($3, "0") != 0) { - yyerror("number expected"); - free($2); - free($3); - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg-> - ratelimit_for_domain, $2, $3)) - fatal_exit("out of memory adding " - "ratelimit-for-domain"); - } - } - ; -server_ratelimit_below_domain: VAR_RATELIMIT_BELOW_DOMAIN STRING_ARG STRING_ARG - { - OUTYY(("P(server_ratelimit_below_domain:%s %s)\n", $2, $3)); - if(atoi($3) == 0 && strcmp($3, "0") != 0) { - yyerror("number expected"); - free($2); - free($3); - } else { - if(!cfg_str2list_insert(&cfg_parser->cfg-> - ratelimit_below_domain, $2, $3)) - fatal_exit("out of memory adding " - "ratelimit-below-domain"); - } - } - ; -server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_factor:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit_factor = atoi($2); - free($2); - } - ; -server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG - { - OUTYY(("P(server_ratelimit_factor:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ratelimit_factor = atoi($2); - free($2); - } - ; -server_ip_ratelimit_backoff: VAR_IP_RATELIMIT_BACKOFF STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_backoff:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_ratelimit_backoff = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_ratelimit_backoff: VAR_RATELIMIT_BACKOFF STRING_ARG - { - OUTYY(("P(server_ratelimit_backoff:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ratelimit_backoff = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_outbound_msg_retry: VAR_OUTBOUND_MSG_RETRY STRING_ARG - { - OUTYY(("P(server_outbound_msg_retry:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->outbound_msg_retry = atoi($2); - free($2); - } - ; -server_max_sent_count: VAR_MAX_SENT_COUNT STRING_ARG - { - OUTYY(("P(server_max_sent_count:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_sent_count = atoi($2); - free($2); - } - ; -server_max_query_restarts: VAR_MAX_QUERY_RESTARTS STRING_ARG - { - OUTYY(("P(server_max_query_restarts:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->max_query_restarts = atoi($2); - free($2); - } - ; -server_low_rtt: VAR_LOW_RTT STRING_ARG - { - OUTYY(("P(low-rtt option is deprecated, use fast-server-num instead)\n")); - free($2); - } - ; -server_fast_server_num: VAR_FAST_SERVER_NUM STRING_ARG - { - OUTYY(("P(server_fast_server_num:%s)\n", $2)); - if(atoi($2) <= 0) - yyerror("number expected"); - else cfg_parser->cfg->fast_server_num = atoi($2); - free($2); - } - ; -server_fast_server_permil: VAR_FAST_SERVER_PERMIL STRING_ARG - { - OUTYY(("P(server_fast_server_permil:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->fast_server_permil = atoi($2); - free($2); - } - ; -server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG - { - OUTYY(("P(server_qname_minimisation:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_qname_minimisation_strict: VAR_QNAME_MINIMISATION_STRICT STRING_ARG - { - OUTYY(("P(server_qname_minimisation_strict:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation_strict = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_pad_responses: VAR_PAD_RESPONSES STRING_ARG - { - OUTYY(("P(server_pad_responses:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->pad_responses = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_pad_responses_block_size: VAR_PAD_RESPONSES_BLOCK_SIZE STRING_ARG - { - OUTYY(("P(server_pad_responses_block_size:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->pad_responses_block_size = atoi($2); - free($2); - } - ; -server_pad_queries: VAR_PAD_QUERIES STRING_ARG - { - OUTYY(("P(server_pad_queries:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->pad_queries = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_pad_queries_block_size: VAR_PAD_QUERIES_BLOCK_SIZE STRING_ARG - { - OUTYY(("P(server_pad_queries_block_size:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else cfg_parser->cfg->pad_queries_block_size = atoi($2); - free($2); - } - ; -server_ipsecmod_enabled: VAR_IPSECMOD_ENABLED STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_enabled:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_enabled = (strcmp($2, "yes")==0); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - #endif - free($2); - } - ; -server_ipsecmod_ignore_bogus: VAR_IPSECMOD_IGNORE_BOGUS STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_ignore_bogus:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_ignore_bogus = (strcmp($2, "yes")==0); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - #endif - free($2); - } - ; -server_ipsecmod_hook: VAR_IPSECMOD_HOOK STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_hook:%s)\n", $2)); - free(cfg_parser->cfg->ipsecmod_hook); - cfg_parser->cfg->ipsecmod_hook = $2; - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free($2); - #endif - } - ; -server_ipsecmod_max_ttl: VAR_IPSECMOD_MAX_TTL STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_max_ttl:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ipsecmod_max_ttl = atoi($2); - free($2); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free($2); - #endif - } - ; -server_ipsecmod_whitelist: VAR_IPSECMOD_WHITELIST STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_whitelist:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->ipsecmod_whitelist, $2)) - yyerror("out of memory"); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free($2); - #endif - } - ; -server_ipsecmod_strict: VAR_IPSECMOD_STRICT STRING_ARG - { - #ifdef USE_IPSECMOD - OUTYY(("P(server_ipsecmod_strict:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ipsecmod_strict = (strcmp($2, "yes")==0); - free($2); - #else - OUTYY(("P(Compiled without IPsec module, ignoring)\n")); - free($2); - #endif - } - ; -server_edns_client_string: VAR_EDNS_CLIENT_STRING STRING_ARG STRING_ARG - { - OUTYY(("P(server_edns_client_string:%s %s)\n", $2, $3)); - if(!cfg_str2list_insert( - &cfg_parser->cfg->edns_client_strings, $2, $3)) - fatal_exit("out of memory adding " - "edns-client-string"); - } - ; -server_edns_client_string_opcode: VAR_EDNS_CLIENT_STRING_OPCODE STRING_ARG - { - OUTYY(("P(edns_client_string_opcode:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("option code expected"); - else if(atoi($2) > 65535 || atoi($2) < 0) - yyerror("option code must be in interval [0, 65535]"); - else cfg_parser->cfg->edns_client_string_opcode = atoi($2); - free($2); - } - ; -server_ede: VAR_EDE STRING_ARG - { - OUTYY(("P(server_ede:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ede = (strcmp($2, "yes")==0); - free($2); - } - ; -server_proxy_protocol_port: VAR_PROXY_PROTOCOL_PORT STRING_ARG - { - OUTYY(("P(server_proxy_protocol_port:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->proxy_protocol_port, $2)) - yyerror("out of memory"); - } - ; -stub_name: VAR_NAME STRING_ARG - { - OUTYY(("P(name:%s)\n", $2)); - if(cfg_parser->cfg->stubs->name) - yyerror("stub name override, there must be one name " - "for one stub-zone"); - free(cfg_parser->cfg->stubs->name); - cfg_parser->cfg->stubs->name = $2; - } - ; -stub_host: VAR_STUB_HOST STRING_ARG - { - OUTYY(("P(stub-host:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, $2)) - yyerror("out of memory"); - } - ; -stub_addr: VAR_STUB_ADDR STRING_ARG - { - OUTYY(("P(stub-addr:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, $2)) - yyerror("out of memory"); - } - ; -stub_first: VAR_STUB_FIRST STRING_ARG - { - OUTYY(("P(stub-first:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->isfirst=(strcmp($2, "yes")==0); - free($2); - } - ; -stub_no_cache: VAR_STUB_NO_CACHE STRING_ARG - { - OUTYY(("P(stub-no-cache:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->no_cache=(strcmp($2, "yes")==0); - free($2); - } - ; -stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG - { - OUTYY(("P(stub-ssl-upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->ssl_upstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -stub_tcp_upstream: VAR_STUB_TCP_UPSTREAM STRING_ARG - { - OUTYY(("P(stub-tcp-upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->tcp_upstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -stub_prime: VAR_STUB_PRIME STRING_ARG - { - OUTYY(("P(stub-prime:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->isprime = - (strcmp($2, "yes")==0); - free($2); - } - ; -forward_name: VAR_NAME STRING_ARG - { - OUTYY(("P(name:%s)\n", $2)); - if(cfg_parser->cfg->forwards->name) - yyerror("forward name override, there must be one " - "name for one forward-zone"); - free(cfg_parser->cfg->forwards->name); - cfg_parser->cfg->forwards->name = $2; - } - ; -forward_host: VAR_FORWARD_HOST STRING_ARG - { - OUTYY(("P(forward-host:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, $2)) - yyerror("out of memory"); - } - ; -forward_addr: VAR_FORWARD_ADDR STRING_ARG - { - OUTYY(("P(forward-addr:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, $2)) - yyerror("out of memory"); - } - ; -forward_first: VAR_FORWARD_FIRST STRING_ARG - { - OUTYY(("P(forward-first:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->isfirst=(strcmp($2, "yes")==0); - free($2); - } - ; -forward_no_cache: VAR_FORWARD_NO_CACHE STRING_ARG - { - OUTYY(("P(forward-no-cache:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->no_cache=(strcmp($2, "yes")==0); - free($2); - } - ; -forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG - { - OUTYY(("P(forward-ssl-upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->ssl_upstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -forward_tcp_upstream: VAR_FORWARD_TCP_UPSTREAM STRING_ARG - { - OUTYY(("P(forward-tcp-upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->tcp_upstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -auth_name: VAR_NAME STRING_ARG - { - OUTYY(("P(name:%s)\n", $2)); - if(cfg_parser->cfg->auths->name) - yyerror("auth name override, there must be one name " - "for one auth-zone"); - free(cfg_parser->cfg->auths->name); - cfg_parser->cfg->auths->name = $2; - } - ; -auth_zonefile: VAR_ZONEFILE STRING_ARG - { - OUTYY(("P(zonefile:%s)\n", $2)); - free(cfg_parser->cfg->auths->zonefile); - cfg_parser->cfg->auths->zonefile = $2; - } - ; -auth_master: VAR_MASTER STRING_ARG - { - OUTYY(("P(master:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->masters, $2)) - yyerror("out of memory"); - } - ; -auth_url: VAR_URL STRING_ARG - { - OUTYY(("P(url:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->urls, $2)) - yyerror("out of memory"); - } - ; -auth_allow_notify: VAR_ALLOW_NOTIFY STRING_ARG - { - OUTYY(("P(allow-notify:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->auths->allow_notify, - $2)) - yyerror("out of memory"); - } - ; -auth_zonemd_check: VAR_ZONEMD_CHECK STRING_ARG - { - OUTYY(("P(zonemd-check:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->zonemd_check = - (strcmp($2, "yes")==0); - free($2); - } - ; -auth_zonemd_reject_absence: VAR_ZONEMD_REJECT_ABSENCE STRING_ARG - { - OUTYY(("P(zonemd-reject-absence:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->zonemd_reject_absence = - (strcmp($2, "yes")==0); - free($2); - } - ; -auth_for_downstream: VAR_FOR_DOWNSTREAM STRING_ARG - { - OUTYY(("P(for-downstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->for_downstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -auth_for_upstream: VAR_FOR_UPSTREAM STRING_ARG - { - OUTYY(("P(for-upstream:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->for_upstream = - (strcmp($2, "yes")==0); - free($2); - } - ; -auth_fallback_enabled: VAR_FALLBACK_ENABLED STRING_ARG - { - OUTYY(("P(fallback-enabled:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->auths->fallback_enabled = - (strcmp($2, "yes")==0); - free($2); - } - ; -view_name: VAR_NAME STRING_ARG - { - OUTYY(("P(name:%s)\n", $2)); - if(cfg_parser->cfg->views->name) - yyerror("view name override, there must be one " - "name for one view"); - free(cfg_parser->cfg->views->name); - cfg_parser->cfg->views->name = $2; - } - ; -view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG - { - OUTYY(("P(view_local_zone:%s %s)\n", $2, $3)); - if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 && - strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 && - strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0 - && strcmp($3, "typetransparent")!=0 - && strcmp($3, "always_transparent")!=0 - && strcmp($3, "always_refuse")!=0 - && strcmp($3, "always_nxdomain")!=0 - && strcmp($3, "always_nodata")!=0 - && strcmp($3, "always_deny")!=0 - && strcmp($3, "always_null")!=0 - && strcmp($3, "noview")!=0 - && strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0 - && strcmp($3, "inform_redirect") != 0 - && strcmp($3, "ipset") != 0) { - yyerror("local-zone type: expected static, deny, " - "refuse, redirect, transparent, " - "typetransparent, inform, inform_deny, " - "inform_redirect, always_transparent, " - "always_refuse, always_nxdomain, " - "always_nodata, always_deny, always_null, " - "noview, nodefault or ipset"); - free($2); - free($3); - } else if(strcmp($3, "nodefault")==0) { - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_zones_nodefault, $2)) - fatal_exit("out of memory adding local-zone"); - free($3); -#ifdef USE_IPSET - } else if(strcmp($3, "ipset")==0) { - size_t len = strlen($2); - /* Make sure to add the trailing dot. - * These are str compared to domain names. */ - if($2[len-1] != '.') { - if(!($2 = realloc($2, len+2))) { - fatal_exit("out of memory adding local-zone"); - } - $2[len] = '.'; - $2[len+1] = 0; - } - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_zones_ipset, $2)) - fatal_exit("out of memory adding local-zone"); - free($3); -#endif - } else { - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->local_zones, - $2, $3)) - fatal_exit("out of memory adding local-zone"); - } - } - ; -view_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG - { - OUTYY(("P(view_response_ip:%s %s)\n", $2, $3)); - validate_respip_action($3); - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->respip_actions, $2, $3)) - fatal_exit("out of memory adding per-view " - "response-ip action"); - } - ; -view_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG - { - OUTYY(("P(view_response_ip_data:%s)\n", $2)); - if(!cfg_str2list_insert( - &cfg_parser->cfg->views->respip_data, $2, $3)) - fatal_exit("out of memory adding response-ip-data"); - } - ; -view_local_data: VAR_LOCAL_DATA STRING_ARG - { - OUTYY(("P(view_local_data:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->views->local_data, $2)) { - fatal_exit("out of memory adding local-data"); - } - } - ; -view_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG - { - char* ptr; - OUTYY(("P(view_local_data_ptr:%s)\n", $2)); - ptr = cfg_ptr_reverse($2); - free($2); - if(ptr) { - if(!cfg_strlist_insert(&cfg_parser->cfg->views-> - local_data, ptr)) - fatal_exit("out of memory adding local-data"); - } else { - yyerror("local-data-ptr could not be reversed"); - } - } - ; -view_first: VAR_VIEW_FIRST STRING_ARG - { - OUTYY(("P(view-first:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->views->isfirst=(strcmp($2, "yes")==0); - free($2); - } - ; -rcstart: VAR_REMOTE_CONTROL - { - OUTYY(("\nP(remote-control:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_rc: contents_rc content_rc - | ; -content_rc: rc_control_enable | rc_control_interface | rc_control_port | - rc_server_key_file | rc_server_cert_file | rc_control_key_file | - rc_control_cert_file | rc_control_use_cert - ; -rc_control_enable: VAR_CONTROL_ENABLE STRING_ARG - { - OUTYY(("P(control_enable:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->remote_control_enable = - (strcmp($2, "yes")==0); - free($2); - } - ; -rc_control_port: VAR_CONTROL_PORT STRING_ARG - { - OUTYY(("P(control_port:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("control port number expected"); - else cfg_parser->cfg->control_port = atoi($2); - free($2); - } - ; -rc_control_interface: VAR_CONTROL_INTERFACE STRING_ARG - { - OUTYY(("P(control_interface:%s)\n", $2)); - if(!cfg_strlist_append(&cfg_parser->cfg->control_ifs, $2)) - yyerror("out of memory"); - } - ; -rc_control_use_cert: VAR_CONTROL_USE_CERT STRING_ARG - { - OUTYY(("P(control_use_cert:%s)\n", $2)); - cfg_parser->cfg->control_use_cert = (strcmp($2, "yes")==0); - free($2); - } - ; -rc_server_key_file: VAR_SERVER_KEY_FILE STRING_ARG - { - OUTYY(("P(rc_server_key_file:%s)\n", $2)); - free(cfg_parser->cfg->server_key_file); - cfg_parser->cfg->server_key_file = $2; - } - ; -rc_server_cert_file: VAR_SERVER_CERT_FILE STRING_ARG - { - OUTYY(("P(rc_server_cert_file:%s)\n", $2)); - free(cfg_parser->cfg->server_cert_file); - cfg_parser->cfg->server_cert_file = $2; - } - ; -rc_control_key_file: VAR_CONTROL_KEY_FILE STRING_ARG - { - OUTYY(("P(rc_control_key_file:%s)\n", $2)); - free(cfg_parser->cfg->control_key_file); - cfg_parser->cfg->control_key_file = $2; - } - ; -rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING_ARG - { - OUTYY(("P(rc_control_cert_file:%s)\n", $2)); - free(cfg_parser->cfg->control_cert_file); - cfg_parser->cfg->control_cert_file = $2; - } - ; -dtstart: VAR_DNSTAP - { - OUTYY(("\nP(dnstap:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_dt: contents_dt content_dt - | ; -content_dt: dt_dnstap_enable | dt_dnstap_socket_path | dt_dnstap_bidirectional | - dt_dnstap_ip | dt_dnstap_tls | dt_dnstap_tls_server_name | - dt_dnstap_tls_cert_bundle | - dt_dnstap_tls_client_key_file | dt_dnstap_tls_client_cert_file | - dt_dnstap_send_identity | dt_dnstap_send_version | - dt_dnstap_identity | dt_dnstap_version | - dt_dnstap_log_resolver_query_messages | - dt_dnstap_log_resolver_response_messages | - dt_dnstap_log_client_query_messages | - dt_dnstap_log_client_response_messages | - dt_dnstap_log_forwarder_query_messages | - dt_dnstap_log_forwarder_response_messages - ; -dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG - { - OUTYY(("P(dt_dnstap_enable:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap = (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_bidirectional: VAR_DNSTAP_BIDIRECTIONAL STRING_ARG - { - OUTYY(("P(dt_dnstap_bidirectional:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_bidirectional = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG - { - OUTYY(("P(dt_dnstap_socket_path:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_socket_path); - cfg_parser->cfg->dnstap_socket_path = $2; - } - ; -dt_dnstap_ip: VAR_DNSTAP_IP STRING_ARG - { - OUTYY(("P(dt_dnstap_ip:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_ip); - cfg_parser->cfg->dnstap_ip = $2; - } - ; -dt_dnstap_tls: VAR_DNSTAP_TLS STRING_ARG - { - OUTYY(("P(dt_dnstap_tls:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_tls = (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_tls_server_name: VAR_DNSTAP_TLS_SERVER_NAME STRING_ARG - { - OUTYY(("P(dt_dnstap_tls_server_name:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_tls_server_name); - cfg_parser->cfg->dnstap_tls_server_name = $2; - } - ; -dt_dnstap_tls_cert_bundle: VAR_DNSTAP_TLS_CERT_BUNDLE STRING_ARG - { - OUTYY(("P(dt_dnstap_tls_cert_bundle:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_tls_cert_bundle); - cfg_parser->cfg->dnstap_tls_cert_bundle = $2; - } - ; -dt_dnstap_tls_client_key_file: VAR_DNSTAP_TLS_CLIENT_KEY_FILE STRING_ARG - { - OUTYY(("P(dt_dnstap_tls_client_key_file:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_tls_client_key_file); - cfg_parser->cfg->dnstap_tls_client_key_file = $2; - } - ; -dt_dnstap_tls_client_cert_file: VAR_DNSTAP_TLS_CLIENT_CERT_FILE STRING_ARG - { - OUTYY(("P(dt_dnstap_tls_client_cert_file:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_tls_client_cert_file); - cfg_parser->cfg->dnstap_tls_client_cert_file = $2; - } - ; -dt_dnstap_send_identity: VAR_DNSTAP_SEND_IDENTITY STRING_ARG - { - OUTYY(("P(dt_dnstap_send_identity:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_send_identity = (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_send_version: VAR_DNSTAP_SEND_VERSION STRING_ARG - { - OUTYY(("P(dt_dnstap_send_version:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_send_version = (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_identity: VAR_DNSTAP_IDENTITY STRING_ARG - { - OUTYY(("P(dt_dnstap_identity:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_identity); - cfg_parser->cfg->dnstap_identity = $2; - } - ; -dt_dnstap_version: VAR_DNSTAP_VERSION STRING_ARG - { - OUTYY(("P(dt_dnstap_version:%s)\n", $2)); - free(cfg_parser->cfg->dnstap_version); - cfg_parser->cfg->dnstap_version = $2; - } - ; -dt_dnstap_log_resolver_query_messages: VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_resolver_query_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_resolver_query_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_log_resolver_response_messages: VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_resolver_response_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_resolver_response_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_log_client_query_messages: VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_client_query_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_client_query_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_log_client_response_messages: VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_client_response_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_client_response_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_log_forwarder_query_messages: VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_forwarder_query_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_forwarder_query_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES STRING_ARG - { - OUTYY(("P(dt_dnstap_log_forwarder_response_messages:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnstap_log_forwarder_response_messages = - (strcmp($2, "yes")==0); - free($2); - } - ; -pythonstart: VAR_PYTHON - { - OUTYY(("\nP(python:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_py: contents_py content_py - | ; -content_py: py_script - ; -py_script: VAR_PYTHON_SCRIPT STRING_ARG - { - OUTYY(("P(python-script:%s)\n", $2)); - if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2)) - yyerror("out of memory"); - } - ; -dynlibstart: VAR_DYNLIB - { - OUTYY(("\nP(dynlib:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_dl: contents_dl content_dl - | ; -content_dl: dl_file - ; -dl_file: VAR_DYNLIB_FILE STRING_ARG - { - OUTYY(("P(dynlib-file:%s)\n", $2)); - if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, $2)) - yyerror("out of memory"); - } - ; -server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG - { - OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2)); - if (strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->disable_dnssec_lame_check = - (strcmp($2, "yes")==0); - free($2); - } - ; -server_log_identity: VAR_LOG_IDENTITY STRING_ARG - { - OUTYY(("P(server_log_identity:%s)\n", $2)); - free(cfg_parser->cfg->log_identity); - cfg_parser->cfg->log_identity = $2; - } - ; -server_response_ip: VAR_RESPONSE_IP STRING_ARG STRING_ARG - { - OUTYY(("P(server_response_ip:%s %s)\n", $2, $3)); - validate_respip_action($3); - if(!cfg_str2list_insert(&cfg_parser->cfg->respip_actions, - $2, $3)) - fatal_exit("out of memory adding response-ip"); - } - ; -server_response_ip_data: VAR_RESPONSE_IP_DATA STRING_ARG STRING_ARG - { - OUTYY(("P(server_response_ip_data:%s)\n", $2)); - if(!cfg_str2list_insert(&cfg_parser->cfg->respip_data, - $2, $3)) - fatal_exit("out of memory adding response-ip-data"); - } - ; -dnscstart: VAR_DNSCRYPT - { - OUTYY(("\nP(dnscrypt:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_dnsc: contents_dnsc content_dnsc - | ; -content_dnsc: - dnsc_dnscrypt_enable | dnsc_dnscrypt_port | dnsc_dnscrypt_provider | - dnsc_dnscrypt_secret_key | dnsc_dnscrypt_provider_cert | - dnsc_dnscrypt_provider_cert_rotated | - dnsc_dnscrypt_shared_secret_cache_size | - dnsc_dnscrypt_shared_secret_cache_slabs | - dnsc_dnscrypt_nonce_cache_size | - dnsc_dnscrypt_nonce_cache_slabs - ; -dnsc_dnscrypt_enable: VAR_DNSCRYPT_ENABLE STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_enable:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->dnscrypt = (strcmp($2, "yes")==0); - free($2); - } - ; -dnsc_dnscrypt_port: VAR_DNSCRYPT_PORT STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_port:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("port number expected"); - else cfg_parser->cfg->dnscrypt_port = atoi($2); - free($2); - } - ; -dnsc_dnscrypt_provider: VAR_DNSCRYPT_PROVIDER STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_provider:%s)\n", $2)); - free(cfg_parser->cfg->dnscrypt_provider); - cfg_parser->cfg->dnscrypt_provider = $2; - } - ; -dnsc_dnscrypt_provider_cert: VAR_DNSCRYPT_PROVIDER_CERT STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_provider_cert:%s)\n", $2)); - if(cfg_strlist_find(cfg_parser->cfg->dnscrypt_provider_cert, $2)) - log_warn("dnscrypt-provider-cert %s is a duplicate", $2); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_provider_cert, $2)) - fatal_exit("out of memory adding dnscrypt-provider-cert"); - } - ; -dnsc_dnscrypt_provider_cert_rotated: VAR_DNSCRYPT_PROVIDER_CERT_ROTATED STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_provider_cert_rotated:%s)\n", $2)); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_provider_cert_rotated, $2)) - fatal_exit("out of memory adding dnscrypt-provider-cert-rotated"); - } - ; -dnsc_dnscrypt_secret_key: VAR_DNSCRYPT_SECRET_KEY STRING_ARG - { - OUTYY(("P(dnsc_dnscrypt_secret_key:%s)\n", $2)); - if(cfg_strlist_find(cfg_parser->cfg->dnscrypt_secret_key, $2)) - log_warn("dnscrypt-secret-key: %s is a duplicate", $2); - if(!cfg_strlist_insert(&cfg_parser->cfg->dnscrypt_secret_key, $2)) - fatal_exit("out of memory adding dnscrypt-secret-key"); - } - ; -dnsc_dnscrypt_shared_secret_cache_size: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE STRING_ARG - { - OUTYY(("P(dnscrypt_shared_secret_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_shared_secret_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -dnsc_dnscrypt_shared_secret_cache_slabs: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS STRING_ARG - { - OUTYY(("P(dnscrypt_shared_secret_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -dnsc_dnscrypt_nonce_cache_size: VAR_DNSCRYPT_NONCE_CACHE_SIZE STRING_ARG - { - OUTYY(("P(dnscrypt_nonce_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_nonce_cache_size)) - yyerror("memory size expected"); - free($2); - } - ; -dnsc_dnscrypt_nonce_cache_slabs: VAR_DNSCRYPT_NONCE_CACHE_SLABS STRING_ARG - { - OUTYY(("P(dnscrypt_nonce_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) { - yyerror("number expected"); - } else { - cfg_parser->cfg->dnscrypt_nonce_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->dnscrypt_nonce_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; -cachedbstart: VAR_CACHEDB - { - OUTYY(("\nP(cachedb:)\n")); - cfg_parser->started_toplevel = 1; - } - ; -contents_cachedb: contents_cachedb content_cachedb - | ; -content_cachedb: cachedb_backend_name | cachedb_secret_seed | - redis_server_host | redis_server_port | redis_timeout | - redis_expire_records | redis_server_path | redis_server_password - ; -cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG - { - #ifdef USE_CACHEDB - OUTYY(("P(backend:%s)\n", $2)); - free(cfg_parser->cfg->cachedb_backend); - cfg_parser->cfg->cachedb_backend = $2; - #else - OUTYY(("P(Compiled without cachedb, ignoring)\n")); - free($2); - #endif - } - ; -cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG - { - #ifdef USE_CACHEDB - OUTYY(("P(secret-seed:%s)\n", $2)); - free(cfg_parser->cfg->cachedb_secret); - cfg_parser->cfg->cachedb_secret = $2; - #else - OUTYY(("P(Compiled without cachedb, ignoring)\n")); - free($2); - #endif - } - ; -redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_host:%s)\n", $2)); - free(cfg_parser->cfg->redis_server_host); - cfg_parser->cfg->redis_server_host = $2; - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free($2); - #endif - } - ; -redis_server_port: VAR_CACHEDB_REDISPORT STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - int port; - OUTYY(("P(redis_server_port:%s)\n", $2)); - port = atoi($2); - if(port == 0 || port < 0 || port > 65535) - yyerror("valid redis server port number expected"); - else cfg_parser->cfg->redis_server_port = port; - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free($2); - } - ; -redis_server_path: VAR_CACHEDB_REDISPATH STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_path:%s)\n", $2)); - free(cfg_parser->cfg->redis_server_path); - cfg_parser->cfg->redis_server_path = $2; - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free($2); - #endif - } - ; -redis_server_password: VAR_CACHEDB_REDISPASSWORD STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_server_password:%s)\n", $2)); - free(cfg_parser->cfg->redis_server_password); - cfg_parser->cfg->redis_server_password = $2; - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - free($2); - #endif - } - ; -redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_timeout:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("redis timeout value expected"); - else cfg_parser->cfg->redis_timeout = atoi($2); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free($2); - } - ; -redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG - { - #if defined(USE_CACHEDB) && defined(USE_REDIS) - OUTYY(("P(redis_expire_records:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->redis_expire_records = (strcmp($2, "yes")==0); - #else - OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); - #endif - free($2); - } - ; -server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG - { - OUTYY(("P(server_tcp_connection_limit:%s %s)\n", $2, $3)); - if (atoi($3) < 0) - yyerror("positive number expected"); - else { - if(!cfg_str2list_insert(&cfg_parser->cfg->tcp_connection_limits, $2, $3)) - fatal_exit("out of memory adding tcp connection limit"); - } - } - ; -server_answer_cookie: VAR_ANSWER_COOKIE STRING_ARG - { - OUTYY(("P(server_answer_cookie:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->do_answer_cookie = (strcmp($2, "yes")==0); - free($2); - } - ; -server_cookie_secret: VAR_COOKIE_SECRET STRING_ARG - { - uint8_t secret[32]; - size_t secret_len = sizeof(secret); - - OUTYY(("P(server_cookie_secret:%s)\n", $2)); - if(sldns_str2wire_hex_buf($2, secret, &secret_len) - || (secret_len != 16)) - yyerror("expected 128 bit hex string"); - else { - cfg_parser->cfg->cookie_secret_len = secret_len; - memcpy(cfg_parser->cfg->cookie_secret, secret, sizeof(secret)); - } - free($2); - } - ; - ipsetstart: VAR_IPSET - { - OUTYY(("\nP(ipset:)\n")); - cfg_parser->started_toplevel = 1; - } - ; - contents_ipset: contents_ipset content_ipset - | ; - content_ipset: ipset_name_v4 | ipset_name_v6 - ; - ipset_name_v4: VAR_IPSET_NAME_V4 STRING_ARG - { - #ifdef USE_IPSET - OUTYY(("P(name-v4:%s)\n", $2)); - if(cfg_parser->cfg->ipset_name_v4) - yyerror("ipset name v4 override, there must be one " - "name for ip v4"); - free(cfg_parser->cfg->ipset_name_v4); - cfg_parser->cfg->ipset_name_v4 = $2; - #else - OUTYY(("P(Compiled without ipset, ignoring)\n")); - free($2); - #endif - } - ; - ipset_name_v6: VAR_IPSET_NAME_V6 STRING_ARG - { - #ifdef USE_IPSET - OUTYY(("P(name-v6:%s)\n", $2)); - if(cfg_parser->cfg->ipset_name_v6) - yyerror("ipset name v6 override, there must be one " - "name for ip v6"); - free(cfg_parser->cfg->ipset_name_v6); - cfg_parser->cfg->ipset_name_v6 = $2; - #else - OUTYY(("P(Compiled without ipset, ignoring)\n")); - free($2); - #endif - } - ; -%% - -/* parse helper routines could be here */ -static void -validate_respip_action(const char* action) -{ - if(strcmp(action, "deny")!=0 && - strcmp(action, "redirect")!=0 && - strcmp(action, "inform")!=0 && - strcmp(action, "inform_deny")!=0 && - strcmp(action, "always_transparent")!=0 && - strcmp(action, "always_refuse")!=0 && - strcmp(action, "always_nxdomain")!=0) - { - yyerror("response-ip action: expected deny, redirect, " - "inform, inform_deny, always_transparent, " - "always_refuse or always_nxdomain"); - } -} - -static void -validate_acl_action(const char* action) -{ - if(strcmp(action, "deny")!=0 && - strcmp(action, "refuse")!=0 && - strcmp(action, "deny_non_local")!=0 && - strcmp(action, "refuse_non_local")!=0 && - strcmp(action, "allow_setrd")!=0 && - strcmp(action, "allow")!=0 && - strcmp(action, "allow_snoop")!=0 && - strcmp(action, "allow_cookie")!=0) - { - yyerror("expected deny, refuse, deny_non_local, " - "refuse_non_local, allow, allow_setrd, " - "allow_snoop or allow_cookie as access control action"); - } -} diff --git a/crates/libunbound-sys/unbound/util/configyyrename.h b/crates/libunbound-sys/unbound/util/configyyrename.h deleted file mode 100644 index 8c7ff5b5..00000000 --- a/crates/libunbound-sys/unbound/util/configyyrename.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * configyyrename.h -- renames for config file yy values to avoid conflicts. - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. - * - * See LICENSE for the license. - * - */ - -#ifndef UTIL_CONFIGYYRENAME_H -#define UTIL_CONFIGYYRENAME_H - -/* defines to change symbols so that no yacc/lex symbols clash */ -#define yymaxdepth ub_c_maxdepth -#define yyparse ub_c_parse -#define yylex ub_c_lex -#define yyerror ub_c_error -#define yylval ub_c_lval -#define yychar ub_c_char -#define yydebug ub_c_debug -#define yypact ub_c_pact -#define yyr1 ub_c_r1 -#define yyr2 ub_c_r2 -#define yydef ub_c_def -#define yychk ub_c_chk -#define yypgo ub_c_pgo -#define yyact ub_c_act -#define yyexca ub_c_exca -#define yyerrflag ub_c_errflag -#define yynerrs ub_c_nerrs -#define yyps ub_c_ps -#define yypv ub_c_pv -#define yys ub_c_s -#define yy_yys ub_c_yys -#define yystate ub_c_state -#define yytmp ub_c_tmp -#define yyv ub_c_v -#define yy_yyv ub_c_yyv -#define yyval ub_c_val -#define yylloc ub_c_lloc -#define yyreds ub_c_reds -#define yytoks ub_c_toks -#define yylhs ub_c_yylhs -#define yylen ub_c_yylen -#define yydefred ub_c_yydefred -#define yydgoto ub_c_yydgoto -#define yysindex ub_c_yysindex -#define yyrindex ub_c_yyrindex -#define yygindex ub_c_yygindex -#define yytable ub_c_yytable -#define yycheck ub_c_yycheck -#define yyname ub_c_yyname -#define yyrule ub_c_yyrule -#define yyin ub_c_in -#define yyout ub_c_out -#define yywrap ub_c_wrap -#define yy_load_buffer_state ub_c_load_buffer_state -#define yy_switch_to_buffer ub_c_switch_to_buffer -#define yy_flush_buffer ub_c_flush_buffer -#define yy_init_buffer ub_c_init_buffer -#define yy_scan_buffer ub_c_scan_buffer -#define yy_scan_bytes ub_c_scan_bytes -#define yy_scan_string ub_c_scan_string -#define yy_create_buffer ub_c_create_buffer -#define yyrestart ub_c_restart -#define yy_delete_buffer ub_c_delete_buffer -#define yypop_buffer_state ub_c_pop_buffer_state -#define yypush_buffer_state ub_c_push_buffer_state -#define yyunput ub_c_unput -#define yyset_in ub_c_set_in -#define yyget_in ub_c_get_in -#define yyset_out ub_c_set_out -#define yyget_out ub_c_get_out -#define yyget_lineno ub_c_get_lineno -#define yyset_lineno ub_c_set_lineno -#define yyset_debug ub_c_set_debug -#define yyget_debug ub_c_get_debug -#define yy_flex_debug ub_c_flex_debug -#define yylex_destroy ub_c_lex_destroy -#define yyfree ub_c_free -#define yyrealloc ub_c_realloc -#define yyalloc ub_c_alloc -#define yymalloc ub_c_malloc -#define yyget_leng ub_c_get_leng -#define yylineno ub_c_lineno -#define yyget_text ub_c_get_text -#define yyss ub_c_ss -#define yysslim ub_c_sslim -#define yyssp ub_c_ssp -#define yystacksize ub_c_stacksize -#define yyvs ub_c_vs -#define yyvsp ub_c_vsp - -#endif /* UTIL_CONFIGYYRENAME_H */ diff --git a/crates/libunbound-sys/unbound/util/data/dname.c b/crates/libunbound-sys/unbound/util/data/dname.c deleted file mode 100644 index 76b2ec7d..00000000 --- a/crates/libunbound-sys/unbound/util/data/dname.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * util/data/dname.h - domain name handling - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains domain name handling functions. - */ - -#include "config.h" -#include -#include "util/data/dname.h" -#include "util/data/msgparse.h" -#include "util/log.h" -#include "util/storage/lookup3.h" -#include "sldns/sbuffer.h" - -/* determine length of a dname in buffer, no compression pointers allowed */ -size_t -query_dname_len(sldns_buffer* query) -{ - size_t len = 0; - size_t labellen; - while(1) { - if(sldns_buffer_remaining(query) < 1) - return 0; /* parse error, need label len */ - labellen = sldns_buffer_read_u8(query); - if(labellen&0xc0) - return 0; /* no compression allowed in queries */ - len += labellen + 1; - if(len > LDNS_MAX_DOMAINLEN) - return 0; /* too long */ - if(labellen == 0) - return len; - if(sldns_buffer_remaining(query) < labellen) - return 0; /* parse error, need content */ - sldns_buffer_skip(query, (ssize_t)labellen); - } -} - -size_t -dname_valid(uint8_t* dname, size_t maxlen) -{ - size_t len = 0; - size_t labellen; - if(maxlen == 0) - return 0; /* too short, shortest is '0' root label */ - labellen = *dname++; - while(labellen) { - if(labellen&0xc0) - return 0; /* no compression ptrs allowed */ - len += labellen + 1; - if(len >= LDNS_MAX_DOMAINLEN) - return 0; /* too long */ - if(len > maxlen) - return 0; /* does not fit in memory allocation */ - dname += labellen; - labellen = *dname++; - } - len += 1; - if(len > maxlen) - return 0; /* does not fit in memory allocation */ - return len; -} - -/** compare uncompressed, noncanonical, registers are hints for speed */ -int -query_dname_compare(register uint8_t* d1, register uint8_t* d2) -{ - register uint8_t lab1, lab2; - log_assert(d1 && d2); - lab1 = *d1++; - lab2 = *d2++; - while( lab1 != 0 || lab2 != 0 ) { - /* compare label length */ - /* if one dname ends, it has labellength 0 */ - if(lab1 != lab2) { - if(lab1 < lab2) - return -1; - return 1; - } - log_assert(lab1 == lab2 && lab1 != 0); - /* compare lowercased labels. */ - while(lab1--) { - /* compare bytes first for speed */ - if(*d1 != *d2 && - tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { - if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) - return -1; - return 1; - } - d1++; - d2++; - } - /* next pair of labels. */ - lab1 = *d1++; - lab2 = *d2++; - } - return 0; -} - -void -query_dname_tolower(uint8_t* dname) -{ - /* the dname is stored uncompressed */ - uint8_t labellen; - labellen = *dname; - while(labellen) { - dname++; - while(labellen--) { - *dname = (uint8_t)tolower((unsigned char)*dname); - dname++; - } - labellen = *dname; - } -} - -void -pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname) -{ - uint8_t lablen; - int count = 0; - if(dname >= sldns_buffer_end(pkt)) - return; - lablen = *dname++; - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - if((size_t)PTR_OFFSET(lablen, *dname) - >= sldns_buffer_limit(pkt)) - return; - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - if(count++ > MAX_COMPRESS_PTRS) - return; - continue; - } - if(dname+lablen >= sldns_buffer_end(pkt)) - return; - while(lablen--) { - *dname = (uint8_t)tolower((unsigned char)*dname); - dname++; - } - if(dname >= sldns_buffer_end(pkt)) - return; - lablen = *dname++; - } -} - - -size_t -pkt_dname_len(sldns_buffer* pkt) -{ - size_t len = 0; - int ptrcount = 0; - uint8_t labellen; - size_t endpos = 0; - - /* read dname and determine length */ - /* check compression pointers, loops, out of bounds */ - while(1) { - /* read next label */ - if(sldns_buffer_remaining(pkt) < 1) - return 0; - labellen = sldns_buffer_read_u8(pkt); - if(LABEL_IS_PTR(labellen)) { - /* compression ptr */ - uint16_t ptr; - if(sldns_buffer_remaining(pkt) < 1) - return 0; - ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt)); - if(ptrcount++ > MAX_COMPRESS_PTRS) - return 0; /* loop! */ - if(sldns_buffer_limit(pkt) <= ptr) - return 0; /* out of bounds! */ - if(!endpos) - endpos = sldns_buffer_position(pkt); - sldns_buffer_set_position(pkt, ptr); - } else { - /* label contents */ - if(labellen > 0x3f) - return 0; /* label too long */ - len += 1 + labellen; - if(len > LDNS_MAX_DOMAINLEN) - return 0; - if(labellen == 0) { - /* end of dname */ - break; - } - if(sldns_buffer_remaining(pkt) < labellen) - return 0; - sldns_buffer_skip(pkt, (ssize_t)labellen); - } - } - if(endpos) - sldns_buffer_set_position(pkt, endpos); - - return len; -} - -int -dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) -{ - uint8_t len1, len2; - int count1 = 0, count2 = 0; - log_assert(pkt && d1 && d2); - len1 = *d1++; - len2 = *d2++; - while( len1 != 0 || len2 != 0 ) { - /* resolve ptrs */ - if(LABEL_IS_PTR(len1)) { - if((size_t)PTR_OFFSET(len1, *d1) - >= sldns_buffer_limit(pkt)) - return -1; - if(count1++ > MAX_COMPRESS_PTRS) - return -1; - d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); - len1 = *d1++; - continue; - } - if(LABEL_IS_PTR(len2)) { - if((size_t)PTR_OFFSET(len2, *d2) - >= sldns_buffer_limit(pkt)) - return 1; - if(count2++ > MAX_COMPRESS_PTRS) - return 1; - d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); - len2 = *d2++; - continue; - } - /* check label length */ - log_assert(len1 <= LDNS_MAX_LABELLEN); - log_assert(len2 <= LDNS_MAX_LABELLEN); - if(len1 != len2) { - if(len1 < len2) return -1; - return 1; - } - log_assert(len1 == len2 && len1 != 0); - /* compare labels */ - while(len1--) { - if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { - if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) - return -1; - return 1; - } - d1++; - d2++; - } - len1 = *d1++; - len2 = *d2++; - } - return 0; -} - -hashvalue_type -dname_query_hash(uint8_t* dname, hashvalue_type h) -{ - uint8_t labuf[LDNS_MAX_LABELLEN+1]; - uint8_t lablen; - int i; - - /* preserve case of query, make hash label by label */ - lablen = *dname++; - while(lablen) { - log_assert(lablen <= LDNS_MAX_LABELLEN); - labuf[0] = lablen; - i=0; - while(lablen--) { - labuf[++i] = (uint8_t)tolower((unsigned char)*dname); - dname++; - } - h = hashlittle(labuf, labuf[0] + 1, h); - lablen = *dname++; - } - - return h; -} - -hashvalue_type -dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h) -{ - uint8_t labuf[LDNS_MAX_LABELLEN+1]; - uint8_t lablen; - int i; - int count = 0; - - /* preserve case of query, make hash label by label */ - lablen = *dname++; - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - /* follow pointer */ - if((size_t)PTR_OFFSET(lablen, *dname) - >= sldns_buffer_limit(pkt)) - return h; - if(count++ > MAX_COMPRESS_PTRS) - return h; - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; - } - log_assert(lablen <= LDNS_MAX_LABELLEN); - labuf[0] = lablen; - i=0; - while(lablen--) { - labuf[++i] = (uint8_t)tolower((unsigned char)*dname); - dname++; - } - h = hashlittle(labuf, labuf[0] + 1, h); - lablen = *dname++; - } - - return h; -} - -void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) -{ - /* copy over the dname and decompress it at the same time */ - size_t comprcount = 0; - size_t len = 0; - uint8_t lablen; - lablen = *dname++; - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - if(comprcount++ > MAX_COMPRESS_PTRS) { - /* too many compression pointers */ - *to = 0; /* end the result prematurely */ - return; - } - /* follow pointer */ - if((size_t)PTR_OFFSET(lablen, *dname) - >= sldns_buffer_limit(pkt)) - return; - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; - } - if(lablen > LDNS_MAX_LABELLEN) { - *to = 0; /* end the result prematurely */ - return; - } - log_assert(lablen <= LDNS_MAX_LABELLEN); - len += (size_t)lablen+1; - if(len >= LDNS_MAX_DOMAINLEN) { - *to = 0; /* end the result prematurely */ - log_err("bad dname in dname_pkt_copy"); - return; - } - *to++ = lablen; - memmove(to, dname, lablen); - dname += lablen; - to += lablen; - lablen = *dname++; - } - /* copy last \0 */ - *to = 0; -} - -void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) -{ - uint8_t lablen; - int count = 0; - if(!out) out = stdout; - if(!dname) return; - - lablen = *dname++; - if(!lablen) - fputc('.', out); - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - /* follow pointer */ - if(!pkt) { - fputs("??compressionptr??", out); - return; - } - if((size_t)PTR_OFFSET(lablen, *dname) - >= sldns_buffer_limit(pkt)) { - fputs("??compressionptr??", out); - return; - } - if(count++ > MAX_COMPRESS_PTRS) { - fputs("??compressionptr??", out); - return; - } - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; - } - if(lablen > LDNS_MAX_LABELLEN) { - fputs("??extendedlabel??", out); - return; - } - while(lablen--) - fputc((int)*dname++, out); - fputc('.', out); - lablen = *dname++; - } -} - -int -dname_count_labels(uint8_t* dname) -{ - uint8_t lablen; - int labs = 1; - - lablen = *dname++; - while(lablen) { - labs++; - dname += lablen; - lablen = *dname++; - } - return labs; -} - -int -dname_count_size_labels(uint8_t* dname, size_t* size) -{ - uint8_t lablen; - int labs = 1; - size_t sz = 1; - - lablen = *dname++; - while(lablen) { - labs++; - sz += lablen+1; - dname += lablen; - lablen = *dname++; - } - *size = sz; - return labs; -} - -/** - * Compare labels in memory, lowercase while comparing. - * @param p1: label 1 - * @param p2: label 2 - * @param len: number of bytes to compare. - * @return: 0, -1, +1 comparison result. - */ -static int -memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len) -{ - while(len--) { - if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) { - if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2)) - return -1; - return 1; - } - p1++; - p2++; - } - return 0; -} - -int -dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) -{ - uint8_t len1, len2; - int atlabel = labs1; - int lastmlabs; - int lastdiff = 0; - /* first skip so that we compare same label. */ - if(labs1 > labs2) { - while(atlabel > labs2) { - len1 = *d1++; - d1 += len1; - atlabel--; - } - log_assert(atlabel == labs2); - } else if(labs1 < labs2) { - atlabel = labs2; - while(atlabel > labs1) { - len2 = *d2++; - d2 += len2; - atlabel--; - } - log_assert(atlabel == labs1); - } - lastmlabs = atlabel+1; - /* now at same label in d1 and d2, atlabel */ - /* www.example.com. */ - /* 4 3 2 1 atlabel number */ - /* repeat until at root label (which is always the same) */ - while(atlabel > 1) { - len1 = *d1++; - len2 = *d2++; - if(len1 != len2) { - log_assert(len1 != 0 && len2 != 0); - if(len1 com. */ - if(labs1 > labs2) - return 1; - else if(labs1 < labs2) - return -1; - } - return lastdiff; -} - -int -dname_lab_startswith(uint8_t* label, char* prefix, char** endptr) -{ - size_t plen = strlen(prefix); - size_t orig_plen = plen; - size_t lablen = (size_t)*label; - if(plen > lablen) - return 0; - label++; - while(plen--) { - if(*prefix != tolower((unsigned char)*label)) { - return 0; - } - prefix++; label++; - } - if(orig_plen < lablen) - *endptr = (char *)label; - else - /* prefix length == label length */ - *endptr = NULL; - return 1; -} - -int -dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label) -{ - size_t len; - - /* 1 byte needed for the label length */ - if(dnamelen < 1) - return 0; - - len = *dname; - while(len <= dnamelen) { - if(!(*dname)) { - if(*dname == *label) - return 1; /* empty label match */ - /* termination label found, stop iterating */ - return 0; - } - if(*dname == *label && *label && - memlowercmp(dname+1, label+1, *dname) == 0) - return 1; - len += *dname; - dname += *dname; - dname++; - len++; - } - return 0; -} - -int -dname_buffer_write(sldns_buffer* pkt, uint8_t* dname) -{ - uint8_t lablen; - - if(sldns_buffer_remaining(pkt) < 1) - return 0; - lablen = *dname++; - sldns_buffer_write_u8(pkt, lablen); - while(lablen) { - if(sldns_buffer_remaining(pkt) < (size_t)lablen+1) - return 0; - sldns_buffer_write(pkt, dname, lablen); - dname += lablen; - lablen = *dname++; - sldns_buffer_write_u8(pkt, lablen); - } - return 1; -} - -void dname_str(uint8_t* dname, char* str) -{ - size_t len = 0; - uint8_t lablen = 0; - char* s = str; - if(!dname || !*dname) { - *s++ = '.'; - *s = 0; - return; - } - lablen = *dname++; - while(lablen) { - if(lablen > LDNS_MAX_LABELLEN) { - *s++ = '#'; - *s = 0; - return; - } - len += lablen+1; - if(len >= LDNS_MAX_DOMAINLEN-1) { - *s++ = '&'; - *s = 0; - return; - } - while(lablen--) { - if(isalnum((unsigned char)*dname) - || *dname == '-' || *dname == '_' - || *dname == '*') - *s++ = *(char*)dname++; - else { - *s++ = '?'; - dname++; - } - } - *s++ = '.'; - lablen = *dname++; - } - *s = 0; -} - -int -dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2) -{ - int m; - /* check subdomain: d1: www.example.com. and d2: example.com. */ - if(labs2 >= labs1) - return 0; - if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) { - /* subdomain if all labels match */ - return (m == labs2); - } - return 0; -} - -int -dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2) -{ - return dname_strict_subdomain(d1, dname_count_labels(d1), d2, - dname_count_labels(d2)); -} - -int -dname_subdomain_c(uint8_t* d1, uint8_t* d2) -{ - int m; - /* check subdomain: d1: www.example.com. and d2: example.com. */ - /* or d1: example.com. and d2: example.com. */ - int labs1 = dname_count_labels(d1); - int labs2 = dname_count_labels(d2); - if(labs2 > labs1) - return 0; - if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) { - /* must have been example.com , www.example.com - wrong */ - /* or otherwise different dnames */ - return 0; - } - return (m == labs2); -} - -int -dname_is_root(uint8_t* dname) -{ - uint8_t len; - log_assert(dname); - len = dname[0]; - log_assert(!LABEL_IS_PTR(len)); - return (len == 0); -} - -void -dname_remove_label(uint8_t** dname, size_t* len) -{ - size_t lablen; - log_assert(dname && *dname && len); - lablen = (*dname)[0]; - log_assert(!LABEL_IS_PTR(lablen)); - log_assert(*len > lablen); - if(lablen == 0) - return; /* do not modify root label */ - *len -= lablen+1; - *dname += lablen+1; -} - -void -dname_remove_labels(uint8_t** dname, size_t* len, int n) -{ - int i; - for(i=0; i len2) - return 1; - return 0; -} - - -int -dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) -{ - /* like dname_lab_cmp, but with different label comparison, - * empty character sorts before \000. - * So ylyly is before z. */ - uint8_t len1, len2; - int atlabel = labs1; - int lastmlabs; - int lastdiff = 0; - int c; - /* first skip so that we compare same label. */ - if(labs1 > labs2) { - while(atlabel > labs2) { - len1 = *d1++; - d1 += len1; - atlabel--; - } - log_assert(atlabel == labs2); - } else if(labs1 < labs2) { - atlabel = labs2; - while(atlabel > labs1) { - len2 = *d2++; - d2 += len2; - atlabel--; - } - log_assert(atlabel == labs1); - } - lastmlabs = atlabel+1; - /* now at same label in d1 and d2, atlabel */ - /* www.example.com. */ - /* 4 3 2 1 atlabel number */ - /* repeat until at root label (which is always the same) */ - while(atlabel > 1) { - len1 = *d1++; - len2 = *d2++; - - if((c=memcanoncmp(d1, len1, d2, len2)) != 0) { - if(c<0) - lastdiff = -1; - else lastdiff = 1; - lastmlabs = atlabel; - } - - d1 += len1; - d2 += len2; - atlabel--; - } - /* last difference atlabel number, so number of labels matching, - * at the right side, is one less. */ - *mlabs = lastmlabs-1; - if(lastdiff == 0) { - /* all labels compared were equal, check if one has more - * labels, so that example.com. > com. */ - if(labs1 > labs2) - return 1; - else if(labs1 < labs2) - return -1; - } - return lastdiff; -} - -int -dname_canonical_compare(uint8_t* d1, uint8_t* d2) -{ - int labs1, labs2, m; - labs1 = dname_count_labels(d1); - labs2 = dname_count_labels(d2); - return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m); -} - -uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2) -{ - int labs1, labs2, m; - size_t len = LDNS_MAX_DOMAINLEN; - labs1 = dname_count_labels(d1); - labs2 = dname_count_labels(d2); - (void)dname_lab_cmp(d1, labs1, d2, labs2, &m); - dname_remove_labels(&d1, &len, labs1-m); - return d1; -} diff --git a/crates/libunbound-sys/unbound/util/data/dname.h b/crates/libunbound-sys/unbound/util/data/dname.h deleted file mode 100644 index cb0f6735..00000000 --- a/crates/libunbound-sys/unbound/util/data/dname.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - * util/data/dname.h - domain name routines - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to deal with domain names (dnames). - * - * Some of the functions deal with domain names as a wireformat buffer, - * with a length. - */ - -#ifndef UTIL_DATA_DNAME_H -#define UTIL_DATA_DNAME_H -#include "util/storage/lruhash.h" -struct sldns_buffer; - -/** max number of compression ptrs to follow */ -#define MAX_COMPRESS_PTRS 256 - -/** - * Determine length of dname in buffer, no compression ptrs allowed, - * @param query: the ldns buffer, current position at start of dname. - * at end, position is at end of the dname. - * @return: 0 on parse failure, or length including ending 0 of dname. - */ -size_t query_dname_len(struct sldns_buffer* query); - -/** - * Determine if dname in memory is correct. no compression ptrs allowed. - * @param dname: where dname starts in memory. - * @param len: dname is not allowed to exceed this length (i.e. of allocation). - * @return length of dname if dname is ok, 0 on a parse error. - */ -size_t dname_valid(uint8_t* dname, size_t len); - -/** lowercase query dname */ -void query_dname_tolower(uint8_t* dname); - -/** - * lowercase pkt dname (follows compression pointers) - * @param pkt: the packet, used to follow compression pointers. Position - * is unchanged. - * @param dname: start of dname in packet. - */ -void pkt_dname_tolower(struct sldns_buffer* pkt, uint8_t* dname); - -/** - * Compare query dnames (uncompressed storage). The Dnames passed do not - * have to be lowercased, comparison routine does this. - * - * This routine is special, in that the comparison that it does corresponds - * with the canonical comparison needed when comparing dnames inside rdata - * for RR types that need canonicalization. That means that the first byte - * that is smaller (possibly after lowercasing) makes an RR smaller, or the - * shortest name makes an RR smaller. - * - * This routine does not compute the canonical order needed for NSEC - * processing. - * - * Dnames have to be valid format. - * @param d1: dname to compare - * @param d2: dname to compare - * @return: -1, 0, or +1 depending on comparison results. - * Sort order is first difference found. not the canonical ordering. - */ -int query_dname_compare(uint8_t* d1, uint8_t* d2); - -/** - * Determine correct, compressed, dname present in packet. - * Checks for parse errors. - * @param pkt: packet to read from (from current start position). - * @return: 0 on parse error. - * At exit the position is right after the (compressed) dname. - * Compression pointers are followed and checked for loops. - * The uncompressed wireformat length is returned. - */ -size_t pkt_dname_len(struct sldns_buffer* pkt); - -/** - * Compare dnames in packet (compressed). Dnames must be valid. - * routine performs lowercasing, so the packet casing is preserved. - * @param pkt: packet, used to resolve compression pointers. - * @param d1: dname to compare - * @param d2: dname to compare - * @return: -1, 0, or +1 depending on comparison results. - * Sort order is first difference found. not the canonical ordering. - */ -int dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2); - -/** - * Hash dname, label by label, lowercasing, into hashvalue. - * Dname in query format (not compressed). - * @param dname: dname to hash. - * @param h: initial hash value. - * @return: result hash value. - */ -hashvalue_type dname_query_hash(uint8_t* dname, hashvalue_type h); - -/** - * Hash dname, label by label, lowercasing, into hashvalue. - * Dname in pkt format (compressed). - * @param pkt: packet, for resolving compression pointers. - * @param dname: dname to hash, pointer to the pkt buffer. - * Must be valid format. No loops, etc. - * @param h: initial hash value. - * @return: result hash value. - * Result is the same as dname_query_hash, even if compression is used. - */ -hashvalue_type dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname, - hashvalue_type h); - -/** - * Copy over a valid dname and decompress it. - * @param pkt: packet to resolve compression pointers. - * @param to: buffer of size from pkt_len function to hold result. - * @param dname: pointer into packet where dname starts. - */ -void dname_pkt_copy(struct sldns_buffer* pkt, uint8_t* to, uint8_t* dname); - -/** - * Copy over a valid dname to a packet. - * @param pkt: packet to copy to. - * @param dname: dname to copy. - * @return: 0 if not enough space in buffer. - */ -int dname_buffer_write(struct sldns_buffer* pkt, uint8_t* dname); - -/** - * Count the number of labels in an uncompressed dname in memory. - * @param dname: pointer to uncompressed dname. - * @return: count of labels, including root label, "com." has 2 labels. - */ -int dname_count_labels(uint8_t* dname); - -/** - * Count labels and dname length both, for uncompressed dname in memory. - * @param dname: pointer to uncompressed dname. - * @param size: length of dname, including root label. - * @return: count of labels, including root label, "com." has 2 labels. - */ -int dname_count_size_labels(uint8_t* dname, size_t* size); - -/** - * Compare dnames, sorted not canonical, but by label. - * Such that zone contents follows zone apex. - * @param d1: first dname. pointer to uncompressed wireformat. - * @param labs1: number of labels in first dname. - * @param d2: second dname. pointer to uncompressed wireformat. - * @param labs2: number of labels in second dname. - * @param mlabs: number of labels that matched exactly (the shared topdomain). - * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. - */ -int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs); - -/** - * Check if labels starts with given prefix - * @param label: dname label - * @param prefix: the string to match label with, null terminated. - * @param endptr: pointer to location in label after prefix, only if return - * value is 1. NULL if nothing in the label after the prefix, i.e. prefix - * and label are the same. - * @return: 1 if label starts with prefix, else 0 - */ -int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr); - -/** - * Check if dname contains label - * @param dname: dname - * @param dnamelen: length of dname - * @param label: label to be checked for presence in dname - * @return: 1 if dname has this label, 0 otherwise - */ -int dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label); - -/** - * See if domain name d1 is a strict subdomain of d2. - * That is a subdomain, but not equal. - * @param d1: domain name, uncompressed wireformat - * @param labs1: number of labels in d1, including root label. - * @param d2: domain name, uncompressed wireformat - * @param labs2: number of labels in d2, including root label. - * @return true if d1 is a subdomain of d2, but not equal to d2. - */ -int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2); - -/** - * Like dname_strict_subdomain but counts labels - * @param d1: domain name, uncompressed wireformat - * @param d2: domain name, uncompressed wireformat - * @return true if d1 is a subdomain of d2, but not equal to d2. - */ -int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2); - -/** - * Counts labels. Tests is d1 is a subdomain of d2. - * @param d1: domain name, uncompressed wireformat - * @param d2: domain name, uncompressed wireformat - * @return true if d1 is a subdomain of d2. - */ -int dname_subdomain_c(uint8_t* d1, uint8_t* d2); - -/** - * Debug helper. Print wireformat dname to output. - * @param out: like stdout or a file. - * @param pkt: if not NULL, the packet for resolving compression ptrs. - * @param dname: pointer to (start of) dname. - */ -void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname); - -/** - * Debug helper. Print dname to given string buffer (string buffer must - * be at least 255 chars + 1 for the 0, in printable form. - * This may lose information (? for nonprintable characters, or & if - * the name is too long, # for a bad label length). - * @param dname: uncompressed wireformat. - * @param str: buffer of 255+1 length. - */ -void dname_str(uint8_t* dname, char* str); - -/** - * Returns true if the uncompressed wireformat dname is the root "." - * @param dname: the dname to check - * @return true if ".", false if not. - */ -int dname_is_root(uint8_t* dname); - -/** - * Snip off first label from a dname, returning the parent zone. - * @param dname: from what to strip off. uncompressed wireformat. - * @param len: length, adjusted to become less. - * return stripped off, or "." if input was ".". - */ -void dname_remove_label(uint8_t** dname, size_t* len); - -/** - * Snip off first N labels from a dname, returning the parent zone. - * @param dname: from what to strip off. uncompressed wireformat. - * @param len: length, adjusted to become less. - * @param n: number of labels to strip off (from the left). - * if 0, nothing happens. - * return stripped off, or "." if input was ".". - */ -void dname_remove_labels(uint8_t** dname, size_t* len, int n); - -/** - * Count labels for the RRSIG signature label field. - * Like a normal labelcount, but "*" wildcard and "." root are not counted. - * @param dname: valid uncompressed wireformat. - * @return number of labels like in RRSIG; '*' and '.' are not counted. - */ -int dname_signame_label_count(uint8_t* dname); - -/** - * Return true if the label is a wildcard, *.example.com. - * @param dname: valid uncompressed wireformat. - * @return true if wildcard, or false. - */ -int dname_is_wild(uint8_t* dname); - -/** - * Compare dnames, Canonical in rfc4034 sense, but by label. - * Such that zone contents follows zone apex. - * - * @param d1: first dname. pointer to uncompressed wireformat. - * @param labs1: number of labels in first dname. - * @param d2: second dname. pointer to uncompressed wireformat. - * @param labs2: number of labels in second dname. - * @param mlabs: number of labels that matched exactly (the shared topdomain). - * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. - */ -int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, - int* mlabs); - -/** - * Canonical dname compare. Takes care of counting labels. - * Per rfc 4034 canonical order. - * - * @param d1: first dname. pointer to uncompressed wireformat. - * @param d2: second dname. pointer to uncompressed wireformat. - * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. - */ -int dname_canonical_compare(uint8_t* d1, uint8_t* d2); - -/** - * Get the shared topdomain between two names. Root "." or longer. - * @param d1: first dname. pointer to uncompressed wireformat. - * @param d2: second dname. pointer to uncompressed wireformat. - * @return pointer to shared topdomain. Ptr to a part of d1. - */ -uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2); - -#endif /* UTIL_DATA_DNAME_H */ diff --git a/crates/libunbound-sys/unbound/util/data/msgencode.c b/crates/libunbound-sys/unbound/util/data/msgencode.c deleted file mode 100644 index a170eb7b..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgencode.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * util/data/msgencode.c - Encode DNS messages, queries and replies. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a routines to encode DNS messages. - */ - -#include "config.h" -#include "util/data/msgencode.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -#include "util/data/dname.h" -#include "util/log.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "sldns/sbuffer.h" -#include "services/localzone.h" - -#ifdef HAVE_TIME_H -#include -#endif -#include - -/** return code that means the function ran out of memory. negative so it does - * not conflict with DNS rcodes. */ -#define RETVAL_OUTMEM -2 -/** return code that means the data did not fit (completely) in the packet */ -#define RETVAL_TRUNC -4 -/** return code that means all is peachy keen. Equal to DNS rcode NOERROR */ -#define RETVAL_OK 0 - -/** - * Data structure to help domain name compression in outgoing messages. - * A tree of dnames and their offsets in the packet is kept. - * It is kept sorted, not canonical, but by label at least, so that after - * a lookup of a name you know its closest match, and the parent from that - * closest match. These are possible compression targets. - * - * It is a binary tree, not a rbtree or balanced tree, as the effort - * of keeping it balanced probably outweighs usefulness (given typical - * DNS packet size). - */ -struct compress_tree_node { - /** left node in tree, all smaller to this */ - struct compress_tree_node* left; - /** right node in tree, all larger than this */ - struct compress_tree_node* right; - - /** the parent node - not for tree, but zone parent. One less label */ - struct compress_tree_node* parent; - /** the domain name for this node. Pointer to uncompressed memory. */ - uint8_t* dname; - /** number of labels in domain name, kept to help compare func. */ - int labs; - /** offset in packet that points to this dname */ - size_t offset; -}; - -/** - * Find domain name in tree, returns exact and closest match. - * @param tree: root of tree. - * @param dname: pointer to uncompressed dname. - * @param labs: number of labels in domain name. - * @param match: closest or exact match. - * guaranteed to be smaller or equal to the sought dname. - * can be null if the tree is empty. - * @param matchlabels: number of labels that match with closest match. - * can be zero is there is no match. - * @param insertpt: insert location for dname, if not found. - * @return: 0 if no exact match. - */ -static int -compress_tree_search(struct compress_tree_node** tree, uint8_t* dname, - int labs, struct compress_tree_node** match, int* matchlabels, - struct compress_tree_node*** insertpt) -{ - int c, n, closen=0; - struct compress_tree_node* p = *tree; - struct compress_tree_node* close = 0; - struct compress_tree_node** prev = tree; - while(p) { - if((c = dname_lab_cmp(dname, labs, p->dname, p->labs, &n)) - == 0) { - *matchlabels = n; - *match = p; - return 1; - } - if(c<0) { - prev = &p->left; - p = p->left; - } else { - closen = n; - close = p; /* p->dname is smaller than dname */ - prev = &p->right; - p = p->right; - } - } - *insertpt = prev; - *matchlabels = closen; - *match = close; - return 0; -} - -/** - * Lookup a domain name in compression tree. - * @param tree: root of tree (not the node with '.'). - * @param dname: pointer to uncompressed dname. - * @param labs: number of labels in domain name. - * @param insertpt: insert location for dname, if not found. - * @return: 0 if not found or compress treenode with best compression. - */ -static struct compress_tree_node* -compress_tree_lookup(struct compress_tree_node** tree, uint8_t* dname, - int labs, struct compress_tree_node*** insertpt) -{ - struct compress_tree_node* p; - int m; - if(labs <= 1) - return 0; /* do not compress root node */ - if(compress_tree_search(tree, dname, labs, &p, &m, insertpt)) { - /* exact match */ - return p; - } - /* return some ancestor of p that compresses well. */ - if(m>1) { - /* www.example.com. (labs=4) matched foo.example.com.(labs=4) - * then matchcount = 3. need to go up. */ - while(p && p->labs > m) - p = p->parent; - return p; - } - return 0; -} - -/** - * Create node for domain name compression tree. - * @param dname: pointer to uncompressed dname (stored in tree). - * @param labs: number of labels in dname. - * @param offset: offset into packet for dname. - * @param region: how to allocate memory for new node. - * @return new node or 0 on malloc failure. - */ -static struct compress_tree_node* -compress_tree_newnode(uint8_t* dname, int labs, size_t offset, - struct regional* region) -{ - struct compress_tree_node* n = (struct compress_tree_node*) - regional_alloc(region, sizeof(struct compress_tree_node)); - if(!n) return 0; - n->left = 0; - n->right = 0; - n->parent = 0; - n->dname = dname; - n->labs = labs; - n->offset = offset; - return n; -} - -/** - * Store domain name and ancestors into compression tree. - * @param dname: pointer to uncompressed dname (stored in tree). - * @param labs: number of labels in dname. - * @param offset: offset into packet for dname. - * @param region: how to allocate memory for new node. - * @param closest: match from previous lookup, used to compress dname. - * may be NULL if no previous match. - * if the tree has an ancestor of dname already, this must be it. - * @param insertpt: where to insert the dname in tree. - * @return: 0 on memory error. - */ -static int -compress_tree_store(uint8_t* dname, int labs, size_t offset, - struct regional* region, struct compress_tree_node* closest, - struct compress_tree_node** insertpt) -{ - uint8_t lablen; - struct compress_tree_node* newnode; - struct compress_tree_node* prevnode = NULL; - int uplabs = labs-1; /* does not store root in tree */ - if(closest) uplabs = labs - closest->labs; - log_assert(uplabs >= 0); - /* algorithms builds up a vine of dname-labels to hang into tree */ - while(uplabs--) { - if(offset > PTR_MAX_OFFSET) { - /* insertion failed, drop vine */ - return 1; /* compression pointer no longer useful */ - } - if(!(newnode = compress_tree_newnode(dname, labs, offset, - region))) { - /* insertion failed, drop vine */ - return 0; - } - - if(prevnode) { - /* chain nodes together, last one has one label more, - * so is larger than newnode, thus goes right. */ - newnode->right = prevnode; - prevnode->parent = newnode; - } - - /* next label */ - lablen = *dname++; - dname += lablen; - offset += lablen+1; - prevnode = newnode; - labs--; - } - /* if we have a vine, hang the vine into the tree */ - if(prevnode) { - *insertpt = prevnode; - prevnode->parent = closest; - } - return 1; -} - -/** compress a domain name */ -static int -write_compressed_dname(sldns_buffer* pkt, uint8_t* dname, int labs, - struct compress_tree_node* p) -{ - /* compress it */ - int labcopy = labs - p->labs; - uint8_t lablen; - uint16_t ptr; - - if(labs == 1) { - /* write root label */ - if(sldns_buffer_remaining(pkt) < 1) - return 0; - sldns_buffer_write_u8(pkt, 0); - return 1; - } - - /* copy the first couple of labels */ - while(labcopy--) { - lablen = *dname++; - if(sldns_buffer_remaining(pkt) < (size_t)lablen+1) - return 0; - sldns_buffer_write_u8(pkt, lablen); - sldns_buffer_write(pkt, dname, lablen); - dname += lablen; - } - /* insert compression ptr */ - if(sldns_buffer_remaining(pkt) < 2) - return 0; - ptr = PTR_CREATE(p->offset); - sldns_buffer_write_u16(pkt, ptr); - return 1; -} - -/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */ -static int -compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt, - struct regional* region, struct compress_tree_node** tree, - size_t owner_pos, uint16_t* owner_ptr, int owner_labs) -{ - struct compress_tree_node* p; - struct compress_tree_node** insertpt = NULL; - if(!*owner_ptr) { - /* compress first time dname */ - if((p = compress_tree_lookup(tree, key->rk.dname, - owner_labs, &insertpt))) { - if(p->labs == owner_labs) - /* avoid ptr chains, since some software is - * not capable of decoding ptr after a ptr. */ - *owner_ptr = htons(PTR_CREATE(p->offset)); - if(!write_compressed_dname(pkt, key->rk.dname, - owner_labs, p)) - return RETVAL_TRUNC; - /* check if typeclass+4 ttl + rdatalen is available */ - if(sldns_buffer_remaining(pkt) < 4+4+2) - return RETVAL_TRUNC; - } else { - /* no compress */ - if(sldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, key->rk.dname, - key->rk.dname_len); - if(owner_pos <= PTR_MAX_OFFSET) - *owner_ptr = htons(PTR_CREATE(owner_pos)); - } - if(!compress_tree_store(key->rk.dname, owner_labs, - owner_pos, region, p, insertpt)) - return RETVAL_OUTMEM; - } else { - /* always compress 2nd-further RRs in RRset */ - if(owner_labs == 1) { - if(sldns_buffer_remaining(pkt) < 1+4+4+2) - return RETVAL_TRUNC; - sldns_buffer_write_u8(pkt, 0); - } else { - if(sldns_buffer_remaining(pkt) < 2+4+4+2) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, owner_ptr, 2); - } - } - return RETVAL_OK; -} - -/** compress any domain name to the packet, return RETVAL_* */ -static int -compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs, - struct regional* region, struct compress_tree_node** tree) -{ - struct compress_tree_node* p; - struct compress_tree_node** insertpt = NULL; - size_t pos = sldns_buffer_position(pkt); - if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) { - if(!write_compressed_dname(pkt, dname, labs, p)) - return RETVAL_TRUNC; - } else { - if(!dname_buffer_write(pkt, dname)) - return RETVAL_TRUNC; - } - if(!compress_tree_store(dname, labs, pos, region, p, insertpt)) - return RETVAL_OUTMEM; - return RETVAL_OK; -} - -/** return true if type needs domain name compression in rdata */ -static const sldns_rr_descriptor* -type_rdata_compressable(struct ub_packed_rrset_key* key) -{ - uint16_t t = ntohs(key->rk.type); - if(sldns_rr_descript(t) && - sldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS) - return sldns_rr_descript(t); - return 0; -} - -/** compress domain names in rdata, return RETVAL_* */ -static int -compress_rdata(sldns_buffer* pkt, uint8_t* rdata, size_t todolen, - struct regional* region, struct compress_tree_node** tree, - const sldns_rr_descriptor* desc) -{ - int labs, r, rdf = 0; - size_t dname_len, len, pos = sldns_buffer_position(pkt); - uint8_t count = desc->_dname_count; - - sldns_buffer_skip(pkt, 2); /* rdata len fill in later */ - /* space for rdatalen checked for already */ - rdata += 2; - todolen -= 2; - while(todolen > 0 && count) { - switch(desc->_wireformat[rdf]) { - case LDNS_RDF_TYPE_DNAME: - labs = dname_count_size_labels(rdata, &dname_len); - if((r=compress_any_dname(rdata, pkt, labs, region, - tree)) != RETVAL_OK) - return r; - rdata += dname_len; - todolen -= dname_len; - count--; - len = 0; - break; - case LDNS_RDF_TYPE_STR: - len = *rdata + 1; - break; - default: - len = get_rdf_size(desc->_wireformat[rdf]); - } - if(len) { - /* copy over */ - if(sldns_buffer_remaining(pkt) < len) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, rdata, len); - todolen -= len; - rdata += len; - } - rdf++; - } - /* copy remainder */ - if(todolen > 0) { - if(sldns_buffer_remaining(pkt) < todolen) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, rdata, todolen); - } - - /* set rdata len */ - sldns_buffer_write_u16_at(pkt, pos, sldns_buffer_position(pkt)-pos-2); - return RETVAL_OK; -} - -/** Returns true if RR type should be included */ -static int -rrset_belongs_in_reply(sldns_pkt_section s, uint16_t rrtype, uint16_t qtype, - int dnssec) -{ - if(dnssec) - return 1; - /* skip non DNSSEC types, except if directly queried for */ - if(s == LDNS_SECTION_ANSWER) { - if(qtype == LDNS_RR_TYPE_ANY || qtype == rrtype) - return 1; - } - /* check DNSSEC-ness */ - switch(rrtype) { - case LDNS_RR_TYPE_SIG: - case LDNS_RR_TYPE_KEY: - case LDNS_RR_TYPE_NXT: - case LDNS_RR_TYPE_DS: - case LDNS_RR_TYPE_RRSIG: - case LDNS_RR_TYPE_NSEC: - case LDNS_RR_TYPE_DNSKEY: - case LDNS_RR_TYPE_NSEC3: - case LDNS_RR_TYPE_NSEC3PARAMS: - return 0; - } - return 1; -} - -/** store rrset in buffer in wireformat, return RETVAL_* */ -static int -packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt, - uint16_t* num_rrs, time_t timenow, struct regional* region, - int do_data, int do_sig, struct compress_tree_node** tree, - sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset) -{ - size_t i, j, owner_pos; - int r, owner_labs; - uint16_t owner_ptr = 0; - time_t adjust = 0; - struct packed_rrset_data* data = (struct packed_rrset_data*) - key->entry.data; - - /* does this RR type belong in the answer? */ - if(!rrset_belongs_in_reply(s, ntohs(key->rk.type), qtype, dnssec)) - return RETVAL_OK; - - owner_labs = dname_count_labels(key->rk.dname); - owner_pos = sldns_buffer_position(pkt); - - /** Determine relative time adjustment for TTL values. - * For an rrset with a fixed TTL, use the rrset's TTL as given. */ - if((key->rk.flags & PACKED_RRSET_FIXEDTTL) != 0) - adjust = 0; - else - adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : timenow; - - if(do_data) { - const sldns_rr_descriptor* c = type_rdata_compressable(key); - for(i=0; icount; i++) { - /* rrset roundrobin */ - j = (i + rr_offset) % data->count; - if((r=compress_owner(key, pkt, region, tree, - owner_pos, &owner_ptr, owner_labs)) - != RETVAL_OK) - return r; - sldns_buffer_write(pkt, &key->rk.type, 2); - sldns_buffer_write(pkt, &key->rk.rrset_class, 2); - if(data->rr_ttl[j] < adjust) - sldns_buffer_write_u32(pkt, - SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0); - else sldns_buffer_write_u32(pkt, data->rr_ttl[j]-adjust); - if(c) { - if((r=compress_rdata(pkt, data->rr_data[j], - data->rr_len[j], region, tree, c)) - != RETVAL_OK) - return r; - } else { - if(sldns_buffer_remaining(pkt) < data->rr_len[j]) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, data->rr_data[j], - data->rr_len[j]); - } - } - } - /* insert rrsigs */ - if(do_sig && dnssec) { - size_t total = data->count+data->rrsig_count; - for(i=data->count; irr_len[i]) - return RETVAL_TRUNC; - sldns_buffer_write(pkt, &owner_ptr, 2); - } else { - if((r=compress_any_dname(key->rk.dname, - pkt, owner_labs, region, tree)) - != RETVAL_OK) - return r; - if(sldns_buffer_remaining(pkt) < - 4+4+data->rr_len[i]) - return RETVAL_TRUNC; - } - sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG); - sldns_buffer_write(pkt, &key->rk.rrset_class, 2); - if(data->rr_ttl[i] < adjust) - sldns_buffer_write_u32(pkt, - SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0); - else sldns_buffer_write_u32(pkt, data->rr_ttl[i]-adjust); - /* rrsig rdata cannot be compressed, perform 100+ byte - * memcopy. */ - sldns_buffer_write(pkt, data->rr_data[i], - data->rr_len[i]); - } - } - /* change rrnum only after we are sure it fits */ - if(do_data) - *num_rrs += data->count; - if(do_sig && dnssec) - *num_rrs += data->rrsig_count; - - return RETVAL_OK; -} - -/** store msg section in wireformat buffer, return RETVAL_* */ -static int -insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs, - sldns_buffer* pkt, size_t rrsets_before, time_t timenow, - struct regional* region, struct compress_tree_node** tree, - sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset) -{ - int r; - size_t i, setstart; - /* we now allow this function to be called multiple times for the - * same section, incrementally updating num_rrs. The caller is - * responsible for initializing it (which is the case in the current - * implementation). */ - - if(s != LDNS_SECTION_ADDITIONAL) { - if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY) - dnssec = 1; /* include all types in ANY answer */ - for(i=0; irrsets[rrsets_before+i], - pkt, num_rrs, timenow, region, 1, 1, tree, - s, qtype, dnssec, rr_offset)) - != RETVAL_OK) { - /* Bad, but if due to size must set TC bit */ - /* trim off the rrset neatly. */ - sldns_buffer_set_position(pkt, setstart); - return r; - } - } - } else { - for(i=0; irrsets[rrsets_before+i], - pkt, num_rrs, timenow, region, 1, 0, tree, - s, qtype, dnssec, rr_offset)) - != RETVAL_OK) { - sldns_buffer_set_position(pkt, setstart); - return r; - } - } - if(dnssec) - for(i=0; irrsets[rrsets_before+i], - pkt, num_rrs, timenow, region, 0, 1, tree, - s, qtype, dnssec, rr_offset)) - != RETVAL_OK) { - sldns_buffer_set_position(pkt, setstart); - return r; - } - } - } - return RETVAL_OK; -} - -/** store query section in wireformat buffer, return RETVAL */ -static int -insert_query(struct query_info* qinfo, struct compress_tree_node** tree, - sldns_buffer* buffer, struct regional* region) -{ - uint8_t* qname = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname : qinfo->qname; - size_t qname_len = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len; - if(sldns_buffer_remaining(buffer) < - qinfo->qname_len+sizeof(uint16_t)*2) - return RETVAL_TRUNC; /* buffer too small */ - /* the query is the first name inserted into the tree */ - if(!compress_tree_store(qname, dname_count_labels(qname), - sldns_buffer_position(buffer), region, NULL, tree)) - return RETVAL_OUTMEM; - if(sldns_buffer_current(buffer) == qname) - sldns_buffer_skip(buffer, (ssize_t)qname_len); - else sldns_buffer_write(buffer, qname, qname_len); - sldns_buffer_write_u16(buffer, qinfo->qtype); - sldns_buffer_write_u16(buffer, qinfo->qclass); - return RETVAL_OK; -} - -static int -positive_answer(struct reply_info* rep, uint16_t qtype) { - size_t i; - if (FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR) - return 0; - - for(i=0;ian_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == qtype) { - /* for priming queries, type NS, include addresses */ - if(qtype == LDNS_RR_TYPE_NS) - return 0; - /* in case it is a wildcard with DNSSEC, there will - * be NSEC/NSEC3 records in the authority section - * that we cannot remove */ - for(i=rep->an_numrrsets; ian_numrrsets+ - rep->ns_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == - LDNS_RR_TYPE_NSEC || - ntohs(rep->rrsets[i]->rk.type) == - LDNS_RR_TYPE_NSEC3) - return 0; - } - return 1; - } - } - return 0; -} - -static int -negative_answer(struct reply_info* rep) { - size_t i; - int ns_seen = 0; - if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN) - return 1; - if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR && - rep->an_numrrsets != 0) - return 0; /* positive */ - if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN) - return 0; - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA) - return 1; - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS) - ns_seen = 1; - } - if(ns_seen) return 0; /* could be referral, NS, but no SOA */ - return 1; -} - -int -reply_info_encode(struct query_info* qinfo, struct reply_info* rep, - uint16_t id, uint16_t flags, sldns_buffer* buffer, time_t timenow, - struct regional* region, uint16_t udpsize, int dnssec, int minimise) -{ - uint16_t ancount=0, nscount=0, arcount=0; - struct compress_tree_node* tree = 0; - int r; - size_t rr_offset; - - sldns_buffer_clear(buffer); - if(udpsize < sldns_buffer_limit(buffer)) - sldns_buffer_set_limit(buffer, udpsize); - if(sldns_buffer_remaining(buffer) < LDNS_HEADER_SIZE) - return 0; - - sldns_buffer_write(buffer, &id, sizeof(uint16_t)); - sldns_buffer_write_u16(buffer, flags); - sldns_buffer_write_u16(buffer, rep->qdcount); - /* set an, ns, ar counts to zero in case of small packets */ - sldns_buffer_write(buffer, "\000\000\000\000\000\000", 6); - - /* insert query section */ - if(rep->qdcount) { - if((r=insert_query(qinfo, &tree, buffer, region)) != - RETVAL_OK) { - if(r == RETVAL_TRUNC) { - /* create truncated message */ - sldns_buffer_write_u16_at(buffer, 4, 0); - LDNS_TC_SET(sldns_buffer_begin(buffer)); - sldns_buffer_flip(buffer); - return 1; - } - return 0; - } - } - /* roundrobin offset. using query id for random number. With ntohs - * for different roundrobins for sequential id client senders. */ - rr_offset = RRSET_ROUNDROBIN?ntohs(id)+(timenow?timenow:time(NULL)):0; - - /* "prepend" any local alias records in the answer section if this - * response is supposed to be authoritative. Currently it should - * be a single CNAME record (sanity-checked in worker_handle_request()) - * but it can be extended if and when we support more variations of - * aliases. */ - if(qinfo->local_alias && (flags & BIT_AA)) { - struct reply_info arep; - time_t timezero = 0; /* to use the 'authoritative' TTL */ - memset(&arep, 0, sizeof(arep)); - arep.flags = rep->flags; - arep.an_numrrsets = 1; - arep.rrset_count = 1; - arep.rrsets = &qinfo->local_alias->rrset; - if((r=insert_section(&arep, 1, &ancount, buffer, 0, - timezero, region, &tree, LDNS_SECTION_ANSWER, - qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) { - if(r == RETVAL_TRUNC) { - /* create truncated message */ - sldns_buffer_write_u16_at(buffer, 6, ancount); - LDNS_TC_SET(sldns_buffer_begin(buffer)); - sldns_buffer_flip(buffer); - return 1; - } - return 0; - } - } - - /* insert answer section */ - if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer, - 0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype, - dnssec, rr_offset)) != RETVAL_OK) { - if(r == RETVAL_TRUNC) { - /* create truncated message */ - sldns_buffer_write_u16_at(buffer, 6, ancount); - LDNS_TC_SET(sldns_buffer_begin(buffer)); - sldns_buffer_flip(buffer); - return 1; - } - return 0; - } - sldns_buffer_write_u16_at(buffer, 6, ancount); - - /* if response is positive answer, auth/add sections are not required */ - if( ! (minimise && positive_answer(rep, qinfo->qtype)) ) { - /* insert auth section */ - if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer, - rep->an_numrrsets, timenow, region, &tree, - LDNS_SECTION_AUTHORITY, qinfo->qtype, - dnssec, rr_offset)) != RETVAL_OK) { - if(r == RETVAL_TRUNC) { - /* create truncated message */ - sldns_buffer_write_u16_at(buffer, 8, nscount); - LDNS_TC_SET(sldns_buffer_begin(buffer)); - sldns_buffer_flip(buffer); - return 1; - } - return 0; - } - sldns_buffer_write_u16_at(buffer, 8, nscount); - - if(! (minimise && negative_answer(rep))) { - /* insert add section */ - if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer, - rep->an_numrrsets + rep->ns_numrrsets, timenow, region, - &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype, - dnssec, rr_offset)) != RETVAL_OK) { - if(r == RETVAL_TRUNC) { - /* no need to set TC bit, this is the additional */ - sldns_buffer_write_u16_at(buffer, 10, arcount); - sldns_buffer_flip(buffer); - return 1; - } - return 0; - } - sldns_buffer_write_u16_at(buffer, 10, arcount); - } - } - sldns_buffer_flip(buffer); - return 1; -} - -uint16_t -calc_edns_field_size(struct edns_data* edns) -{ - size_t rdatalen = 0; - struct edns_option* opt; - if(!edns || !edns->edns_present) - return 0; - for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) { - rdatalen += 4 + opt->opt_len; - } - for(opt = edns->opt_list_out; opt; opt = opt->next) { - rdatalen += 4 + opt->opt_len; - } - /* domain root '.' + type + class + ttl + rdatalen */ - return 1 + 2 + 2 + 4 + 2 + rdatalen; -} - -uint16_t -calc_edns_option_size(struct edns_data* edns, uint16_t code) -{ - size_t rdatalen = 0; - struct edns_option* opt; - if(!edns || !edns->edns_present) - return 0; - for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) { - if(opt->opt_code == code) - rdatalen += 4 + opt->opt_len; - } - for(opt = edns->opt_list_out; opt; opt = opt->next) { - if(opt->opt_code == code) - rdatalen += 4 + opt->opt_len; - } - return rdatalen; -} - -uint16_t -calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size) -{ - size_t rdatalen = 0; - struct edns_option* opt; - *txt_size = 0; - if(!edns || !edns->edns_present) - return 0; - for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) { - if(opt->opt_code == LDNS_EDNS_EDE) { - rdatalen += 4 + opt->opt_len; - if(opt->opt_len > 2) *txt_size += opt->opt_len - 2; - if(opt->opt_len >= 2 && sldns_read_uint16( - opt->opt_data) == LDNS_EDE_OTHER) { - *txt_size += 4 + 2; - } - } - } - for(opt = edns->opt_list_out; opt; opt = opt->next) { - if(opt->opt_code == LDNS_EDNS_EDE) { - rdatalen += 4 + opt->opt_len; - if(opt->opt_len > 2) *txt_size += opt->opt_len - 2; - if(opt->opt_len >= 2 && sldns_read_uint16( - opt->opt_data) == LDNS_EDE_OTHER) { - *txt_size += 4 + 2; - } - } - } - return rdatalen; -} - -/* Trims the EDE OPTION-DATA to not include any EXTRA-TEXT data. - * Also removes any LDNS_EDE_OTHER options from the list since they are useless - * without the extra text. */ -static void -ede_trim_text(struct edns_option** list) -{ - struct edns_option* curr, *prev = NULL; - if(!list || !(*list)) return; - /* Unlink and repoint if LDNS_EDE_OTHER are first in list */ - while(list && *list && (*list)->opt_code == LDNS_EDNS_EDE - && (*list)->opt_len >= 2 - && sldns_read_uint16((*list)->opt_data) == LDNS_EDE_OTHER ) { - *list = (*list)->next; - } - if(!list || !(*list)) return; - curr = *list; - while(curr) { - if(curr->opt_code == LDNS_EDNS_EDE) { - if(curr->opt_len >= 2 && sldns_read_uint16( - curr->opt_data) == LDNS_EDE_OTHER) { - /* LDNS_EDE_OTHER cannot be the first option in - * this while, so prev is always initialized at - * this point from the other branches; - * cut this option off */ - prev->next = curr->next; - curr = curr->next; - } else if(curr->opt_len > 2) { - /* trim this option's EXTRA-TEXT */ - curr->opt_len = 2; - prev = curr; - curr = curr->next; - } - } else { - /* continue */ - prev = curr; - curr = curr->next; - } - } -} - -static void -attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, - uint16_t max_msg_sz) -{ - size_t len; - size_t rdatapos; - struct edns_option* opt; - struct edns_option* padding_option = NULL; - /* inc additional count */ - sldns_buffer_write_u16_at(pkt, 10, - sldns_buffer_read_u16_at(pkt, 10) + 1); - len = sldns_buffer_limit(pkt); - sldns_buffer_clear(pkt); - sldns_buffer_set_position(pkt, len); - /* write EDNS record */ - sldns_buffer_write_u8(pkt, 0); /* '.' label */ - sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_OPT); /* type */ - sldns_buffer_write_u16(pkt, edns->udp_size); /* class */ - sldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */ - sldns_buffer_write_u8(pkt, edns->edns_version); - sldns_buffer_write_u16(pkt, edns->bits); - rdatapos = sldns_buffer_position(pkt); - sldns_buffer_write_u16(pkt, 0); /* rdatalen */ - /* write rdata */ - for(opt=edns->opt_list_inplace_cb_out; opt; opt=opt->next) { - if (opt->opt_code == LDNS_EDNS_PADDING) { - padding_option = opt; - continue; - } - sldns_buffer_write_u16(pkt, opt->opt_code); - sldns_buffer_write_u16(pkt, opt->opt_len); - if(opt->opt_len != 0) - sldns_buffer_write(pkt, opt->opt_data, opt->opt_len); - } - for(opt=edns->opt_list_out; opt; opt=opt->next) { - if (opt->opt_code == LDNS_EDNS_PADDING) { - padding_option = opt; - continue; - } - sldns_buffer_write_u16(pkt, opt->opt_code); - sldns_buffer_write_u16(pkt, opt->opt_len); - if(opt->opt_len != 0) - sldns_buffer_write(pkt, opt->opt_data, opt->opt_len); - } - if (padding_option && edns->padding_block_size ) { - size_t pad_pos = sldns_buffer_position(pkt); - size_t msg_sz = ((pad_pos + 3) / edns->padding_block_size + 1) - * edns->padding_block_size; - size_t pad_sz; - - if (msg_sz > max_msg_sz) - msg_sz = max_msg_sz; - - /* By use of calc_edns_field_size, calling functions should - * have made sure that there is enough space for at least a - * zero sized padding option. - */ - log_assert(pad_pos + 4 <= msg_sz); - - pad_sz = msg_sz - pad_pos - 4; - sldns_buffer_write_u16(pkt, LDNS_EDNS_PADDING); - sldns_buffer_write_u16(pkt, pad_sz); - if (pad_sz) { - memset(sldns_buffer_current(pkt), 0, pad_sz); - sldns_buffer_skip(pkt, pad_sz); - } - } - sldns_buffer_write_u16_at(pkt, rdatapos, - sldns_buffer_position(pkt)-rdatapos-2); - sldns_buffer_flip(pkt); -} - -void -attach_edns_record(sldns_buffer* pkt, struct edns_data* edns) -{ - if(!edns || !edns->edns_present) - return; - attach_edns_record_max_msg_sz(pkt, edns, edns->udp_size); -} - -int -reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, - uint16_t id, uint16_t qflags, sldns_buffer* pkt, time_t timenow, - int cached, struct regional* region, uint16_t udpsize, - struct edns_data* edns, int dnssec, int secure) -{ - uint16_t flags; - unsigned int attach_edns = 0; - uint16_t edns_field_size, ede_size, ede_txt_size; - - if(!cached || rep->authoritative) { - /* original flags, copy RD and CD bits from query. */ - flags = rep->flags | (qflags & (BIT_RD|BIT_CD)); - } else { - /* remove AA bit, copy RD and CD bits from query. */ - flags = (rep->flags & ~BIT_AA) | (qflags & (BIT_RD|BIT_CD)); - } - if(secure && (dnssec || (qflags&BIT_AD))) - flags |= BIT_AD; - /* restore AA bit if we have a local alias and the response can be - * authoritative. Also clear AD bit if set as the local data is the - * primary answer. */ - if(qinf->local_alias && - (FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)) { - flags |= BIT_AA; - flags &= ~BIT_AD; - } - log_assert(flags & BIT_QR); /* QR bit must be on in our replies */ - if(udpsize < LDNS_HEADER_SIZE) - return 0; - /* currently edns does not change during calculations; - * calculate sizes once here */ - edns_field_size = calc_edns_field_size(edns); - ede_size = calc_ede_option_size(edns, &ede_txt_size); - if(sldns_buffer_capacity(pkt) < udpsize) - udpsize = sldns_buffer_capacity(pkt); - /* EDEs are optional, try to fit anything else before them */ - if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { - /* packet too small to contain edns, omit it. */ - attach_edns = 0; - } else { - /* reserve space for edns record */ - attach_edns = (unsigned int)edns_field_size - ede_size; - } - - if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region, - udpsize - attach_edns, dnssec, MINIMAL_RESPONSES)) { - log_err("reply encode: out of memory"); - return 0; - } - if(attach_edns) { - if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size) - attach_edns_record_max_msg_sz(pkt, edns, udpsize); - else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) { - ede_trim_text(&edns->opt_list_inplace_cb_out); - ede_trim_text(&edns->opt_list_out); - attach_edns_record_max_msg_sz(pkt, edns, udpsize); - } else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) { - edns_opt_list_remove(&edns->opt_list_inplace_cb_out, LDNS_EDNS_EDE); - edns_opt_list_remove(&edns->opt_list_out, LDNS_EDNS_EDE); - attach_edns_record_max_msg_sz(pkt, edns, udpsize); - } - } - return 1; -} - -void -qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo) -{ - uint16_t flags = 0; /* QUERY, NOERROR */ - const uint8_t* qname = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname : qinfo->qname; - size_t qname_len = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len; - sldns_buffer_clear(pkt); - log_assert(sldns_buffer_remaining(pkt) >= 12+255+4/*max query*/); - sldns_buffer_skip(pkt, 2); /* id done later */ - sldns_buffer_write_u16(pkt, flags); - sldns_buffer_write_u16(pkt, 1); /* query count */ - sldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */ - sldns_buffer_write(pkt, qname, qname_len); - sldns_buffer_write_u16(pkt, qinfo->qtype); - sldns_buffer_write_u16(pkt, qinfo->qclass); - sldns_buffer_flip(pkt); -} - -void -extended_error_encode(sldns_buffer* buf, uint16_t rcode, - struct query_info* qinfo, uint16_t qid, uint16_t qflags, - uint16_t xflags, struct edns_data* edns) -{ - uint16_t flags; - - sldns_buffer_clear(buf); - sldns_buffer_write(buf, &qid, sizeof(uint16_t)); - flags = (uint16_t)(BIT_QR | BIT_RA | (rcode & 0xF)); /* QR and retcode*/ - flags |= xflags; - flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */ - sldns_buffer_write_u16(buf, flags); - if(qinfo) flags = 1; - else flags = 0; - sldns_buffer_write_u16(buf, flags); - flags = 0; - sldns_buffer_write(buf, &flags, sizeof(uint16_t)); - sldns_buffer_write(buf, &flags, sizeof(uint16_t)); - sldns_buffer_write(buf, &flags, sizeof(uint16_t)); - if(qinfo) { - const uint8_t* qname = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname : qinfo->qname; - size_t qname_len = qinfo->local_alias ? - qinfo->local_alias->rrset->rk.dname_len : - qinfo->qname_len; - if(sldns_buffer_current(buf) == qname) - sldns_buffer_skip(buf, (ssize_t)qname_len); - else sldns_buffer_write(buf, qname, qname_len); - sldns_buffer_write_u16(buf, qinfo->qtype); - sldns_buffer_write_u16(buf, qinfo->qclass); - } - sldns_buffer_flip(buf); - if(edns) { - struct edns_data es = *edns; - es.edns_version = EDNS_ADVERTISED_VERSION; - es.udp_size = EDNS_ADVERTISED_SIZE; - es.ext_rcode = (uint8_t)(rcode >> 4); - es.bits &= EDNS_DO; - if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) > - edns->udp_size) { - edns_opt_list_remove(&es.opt_list_inplace_cb_out, LDNS_EDNS_EDE); - edns_opt_list_remove(&es.opt_list_out, LDNS_EDNS_EDE); - if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) > - edns->udp_size) { - return; - } - } - attach_edns_record(buf, &es); - } -} - -void -error_encode(sldns_buffer* buf, int r, struct query_info* qinfo, - uint16_t qid, uint16_t qflags, struct edns_data* edns) -{ - extended_error_encode(buf, (r & 0x000F), qinfo, qid, qflags, - (r & 0xFFF0), edns); -} diff --git a/crates/libunbound-sys/unbound/util/data/msgencode.h b/crates/libunbound-sys/unbound/util/data/msgencode.h deleted file mode 100644 index 6aff0609..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgencode.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * util/data/msgencode.h - encode compressed DNS messages. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains temporary data structures and routines to create - * compressed DNS messages. - */ - -#ifndef UTIL_DATA_MSGENCODE_H -#define UTIL_DATA_MSGENCODE_H -struct sldns_buffer; -struct query_info; -struct reply_info; -struct regional; -struct edns_data; - -/** - * Generate answer from reply_info. - * @param qinf: query information that provides query section in packet. - * @param rep: reply to fill in. - * @param id: id word from the query. - * @param qflags: flags word from the query. - * @param dest: buffer to put message into; will truncate if it does not fit. - * @param timenow: time to subtract. - * @param cached: set true if a cached reply (so no AA bit). - * set false for the first reply. - * @param region: where to allocate temp variables (for compression). - * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP. - * @param edns: EDNS data included in the answer, NULL for none. - * or if edns_present = 0, it is not included. - * @param dnssec: if 0 DNSSEC records are omitted from the answer. - * @param secure: if 1, the AD bit is set in the reply. - * @return: 0 on error (server failure). - */ -int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, - uint16_t id, uint16_t qflags, struct sldns_buffer* dest, time_t timenow, - int cached, struct regional* region, uint16_t udpsize, - struct edns_data* edns, int dnssec, int secure); - -/** - * Regenerate the wireformat from the stored msg reply. - * If the buffer is too small then the message is truncated at a whole - * rrset and the TC bit set, or whole rrsets are left out of the additional - * and the TC bit is not set. - * @param qinfo: query info to store. - * @param rep: reply to store. - * @param id: id value to store, network order. - * @param flags: flags value to store, host order. - * @param buffer: buffer to store the packet into. - * @param timenow: time now, to adjust ttl values. - * @param region: to store temporary data in. - * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP. - * @param dnssec: if 0 DNSSEC records are omitted from the answer. - * @param minimise: if true, the answer is a minimal response, with - * authority and additional removed if possible. - * @return: nonzero is success, or - * 0 on error: malloc failure (no log_err has been done). - */ -int reply_info_encode(struct query_info* qinfo, struct reply_info* rep, - uint16_t id, uint16_t flags, struct sldns_buffer* buffer, time_t timenow, - struct regional* region, uint16_t udpsize, int dnssec, int minimise); - -/** - * Encode query packet. Assumes the buffer is large enough. - * @param pkt: where to store the packet. - * @param qinfo: query info. - */ -void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo); - -/** - * Estimate size of EDNS record in packet. EDNS record will be no larger. - * @param edns: edns data or NULL. - * @return octets to reserve for EDNS. - */ -uint16_t calc_edns_field_size(struct edns_data* edns); - -/** - * Calculate the size of a specific EDNS option in packet. - * @param edns: edns data or NULL. - * @param code: the opt code to get the size of. - * @return octets the option will take up. - */ -uint16_t calc_edns_option_size(struct edns_data* edns, uint16_t code); - -/** - * Calculate the size of the EDE option(s) in packet. Also calculate seperately - * the size of the EXTRA-TEXT field(s) in case we can trim them to fit. - * In this case include any LDNS_EDE_OTHER options in their entirety since they - * are useless without extra text. - * @param edns: edns data or NULL. - * @param txt_size: the size of the EXTRA-TEXT field(s); this includes - * LDNS_EDE_OTHER in their entirety since they are useless without - * extra text. - * @return octets the option will take up. - */ -uint16_t calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size); - -/** - * Attach EDNS record to buffer. Buffer has complete packet. There must - * be enough room left for the EDNS record. - * @param pkt: packet added to. - * @param edns: if NULL or present=0, nothing is added to the packet. - */ -void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns); - -/** - * Encode an error. With QR and RA set. - * - * @param pkt: where to store the packet. - * @param r: RCODE value to encode (may contain extra flags). - * @param qinfo: if not NULL, the query is included. - * @param qid: query ID to set in packet. network order. - * @param qflags: original query flags (to copy RD and CD bits). host order. - * @param edns: if not NULL, this is the query edns info, - * and an edns reply is attached. Only attached if EDNS record fits reply. - */ -void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo, - uint16_t qid, uint16_t qflags, struct edns_data* edns); - -/** - * Encode an extended error. With QR and RA set. - * - * @param pkt: where to store the packet. - * @param rcode: Extended RCODE value to encode. - * @param qinfo: if not NULL, the query is included. - * @param qid: query ID to set in packet. network order. - * @param qflags: original query flags (to copy RD and CD bits). host order. - * @param xflags: extra flags to set (such as for example BIT_AA and/or BIT_TC) - * @param edns: if not NULL, this is the query edns info, - * and an edns reply is attached. Only attached if EDNS record fits reply. - * Without edns extended errors (i.e. > 15) will not be conveyed. - */ -void extended_error_encode(struct sldns_buffer* pkt, uint16_t rcode, - struct query_info* qinfo, uint16_t qid, uint16_t qflags, - uint16_t xflags, struct edns_data* edns); - -#endif /* UTIL_DATA_MSGENCODE_H */ diff --git a/crates/libunbound-sys/unbound/util/data/msgparse.c b/crates/libunbound-sys/unbound/util/data/msgparse.c deleted file mode 100644 index b5414c6d..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgparse.c +++ /dev/null @@ -1,1308 +0,0 @@ -/* - * util/data/msgparse.c - parse wireformat DNS messages. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Routines for message parsing a packet buffer to a descriptive structure. - */ -#include "config.h" -#include "util/config_file.h" -#include "util/data/msgparse.h" -#include "util/data/msgreply.h" -#include "util/data/dname.h" -#include "util/data/packed_rrset.h" -#include "util/netevent.h" -#include "util/storage/lookup3.h" -#include "util/regional.h" -#include "util/rfc_1982.h" -#include "util/edns.h" -#include "sldns/rrdef.h" -#include "sldns/sbuffer.h" -#include "sldns/parseutil.h" -#include "sldns/wire2str.h" - -/** smart comparison of (compressed, valid) dnames from packet */ -static int -smart_compare(sldns_buffer* pkt, uint8_t* dnow, - uint8_t* dprfirst, uint8_t* dprlast) -{ - if(LABEL_IS_PTR(*dnow)) { - /* ptr points to a previous dname */ - uint8_t* p; - if((size_t)PTR_OFFSET(dnow[0], dnow[1]) - >= sldns_buffer_limit(pkt)) - return -1; - p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); - if( p == dprfirst || p == dprlast ) - return 0; - /* prev dname is also a ptr, both ptrs are the same. */ - if(LABEL_IS_PTR(*dprlast) && - dprlast[0] == dnow[0] && dprlast[1] == dnow[1]) - return 0; - } - return dname_pkt_compare(pkt, dnow, dprlast); -} - -/** - * Allocate new rrset in region, fill with data. - */ -static struct rrset_parse* -new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen, - uint16_t type, uint16_t dclass, hashvalue_type hash, - uint32_t rrset_flags, sldns_pkt_section section, - struct regional* region) -{ - struct rrset_parse* p = regional_alloc(region, sizeof(*p)); - if(!p) return NULL; - p->rrset_bucket_next = msg->hashtable[hash & (PARSE_TABLE_SIZE-1)]; - msg->hashtable[hash & (PARSE_TABLE_SIZE-1)] = p; - p->rrset_all_next = 0; - if(msg->rrset_last) - msg->rrset_last->rrset_all_next = p; - else msg->rrset_first = p; - msg->rrset_last = p; - p->hash = hash; - p->section = section; - p->dname = dname; - p->dname_len = dnamelen; - p->type = type; - p->rrset_class = dclass; - p->flags = rrset_flags; - p->rr_count = 0; - p->size = 0; - p->rr_first = 0; - p->rr_last = 0; - p->rrsig_count = 0; - p->rrsig_first = 0; - p->rrsig_last = 0; - return p; -} - -/** See if next rrset is nsec at zone apex */ -static int -nsec_at_apex(sldns_buffer* pkt) -{ - /* we are at ttl position in packet. */ - size_t pos = sldns_buffer_position(pkt); - uint16_t rdatalen; - if(sldns_buffer_remaining(pkt) < 7) /* ttl+len+root */ - return 0; /* eek! */ - sldns_buffer_skip(pkt, 4); /* ttl */; - rdatalen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdatalen) { - sldns_buffer_set_position(pkt, pos); - return 0; /* parse error happens later */ - } - /* must validate the nsec next domain name format */ - if(pkt_dname_len(pkt) == 0) { - sldns_buffer_set_position(pkt, pos); - return 0; /* parse error */ - } - - /* see if SOA bit is set. */ - if(sldns_buffer_position(pkt) < pos+4+rdatalen) { - /* nsec type bitmap contains items */ - uint8_t win, blen, bits; - /* need: windownum, bitmap len, firstbyte */ - if(sldns_buffer_position(pkt)+3 > pos+4+rdatalen) { - sldns_buffer_set_position(pkt, pos); - return 0; /* malformed nsec */ - } - win = sldns_buffer_read_u8(pkt); - blen = sldns_buffer_read_u8(pkt); - bits = sldns_buffer_read_u8(pkt); - /* 0window always first window. bitlen >=1 or parse - error really. bit 0x2 is SOA. */ - if(win == 0 && blen >= 1 && (bits & 0x02)) { - sldns_buffer_set_position(pkt, pos); - return 1; - } - } - - sldns_buffer_set_position(pkt, pos); - return 0; -} - -/** Calculate rrset flags */ -static uint32_t -pkt_rrset_flags(sldns_buffer* pkt, uint16_t type, sldns_pkt_section sec) -{ - uint32_t f = 0; - if(type == LDNS_RR_TYPE_NSEC && nsec_at_apex(pkt)) { - f |= PACKED_RRSET_NSEC_AT_APEX; - } else if(type == LDNS_RR_TYPE_SOA && sec == LDNS_SECTION_AUTHORITY) { - f |= PACKED_RRSET_SOA_NEG; - } - return f; -} - -hashvalue_type -pkt_hash_rrset(sldns_buffer* pkt, uint8_t* dname, uint16_t type, - uint16_t dclass, uint32_t rrset_flags) -{ - /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ - /* this routine handles compressed names */ - hashvalue_type h = 0xab; - h = dname_pkt_hash(pkt, dname, h); - h = hashlittle(&type, sizeof(type), h); /* host order */ - h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ - h = hashlittle(&rrset_flags, sizeof(uint32_t), h); - return h; -} - -/** create partial dname hash for rrset hash */ -static hashvalue_type -pkt_hash_rrset_first(sldns_buffer* pkt, uint8_t* dname) -{ - /* works together with pkt_hash_rrset_rest */ - /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ - /* this routine handles compressed names */ - hashvalue_type h = 0xab; - h = dname_pkt_hash(pkt, dname, h); - return h; -} - -/** create a rrset hash from a partial dname hash */ -static hashvalue_type -pkt_hash_rrset_rest(hashvalue_type dname_h, uint16_t type, uint16_t dclass, - uint32_t rrset_flags) -{ - /* works together with pkt_hash_rrset_first */ - /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ - hashvalue_type h; - h = hashlittle(&type, sizeof(type), dname_h); /* host order */ - h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ - h = hashlittle(&rrset_flags, sizeof(uint32_t), h); - return h; -} - -/** compare rrset_parse with data */ -static int -rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_type h, - uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, - uint16_t type, uint16_t dclass) -{ - if(p->hash == h && p->dname_len == dnamelen && p->type == type && - p->rrset_class == dclass && p->flags == rrset_flags && - dname_pkt_compare(pkt, dname, p->dname) == 0) - return 1; - return 0; -} - - -struct rrset_parse* -msgparse_hashtable_lookup(struct msg_parse* msg, sldns_buffer* pkt, - hashvalue_type h, uint32_t rrset_flags, uint8_t* dname, - size_t dnamelen, uint16_t type, uint16_t dclass) -{ - struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)]; - while(p) { - if(rrset_parse_equals(p, pkt, h, rrset_flags, dname, dnamelen, - type, dclass)) - return p; - p = p->rrset_bucket_next; - } - return NULL; -} - -/** return type networkformat that rrsig in packet covers */ -static int -pkt_rrsig_covered(sldns_buffer* pkt, uint8_t* here, uint16_t* type) -{ - size_t pos = sldns_buffer_position(pkt); - sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt))); - /* ttl + len + size of small rrsig(rootlabel, no signature) */ - if(sldns_buffer_remaining(pkt) < 4+2+19) - return 0; - sldns_buffer_skip(pkt, 4); /* ttl */ - if(sldns_buffer_read_u16(pkt) < 19) /* too short */ { - sldns_buffer_set_position(pkt, pos); - return 0; - } - *type = sldns_buffer_read_u16(pkt); - sldns_buffer_set_position(pkt, pos); - return 1; -} - -/** true if covered type equals prevtype */ -static int -pkt_rrsig_covered_equals(sldns_buffer* pkt, uint8_t* here, uint16_t type) -{ - uint16_t t; - if(pkt_rrsig_covered(pkt, here, &t) && t == type) - return 1; - return 0; -} - -void -msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset) -{ - struct rrset_parse** p; - p = &msg->hashtable[ rrset->hash & (PARSE_TABLE_SIZE-1) ]; - while(*p) { - if(*p == rrset) { - *p = rrset->rrset_bucket_next; - return; - } - p = &( (*p)->rrset_bucket_next ); - } -} - -/** change section of rrset from previous to current section */ -static void -change_section(struct msg_parse* msg, struct rrset_parse* rrset, - sldns_pkt_section section) -{ - struct rrset_parse *p, *prev; - /* remove from list */ - if(section == rrset->section) - return; - p = msg->rrset_first; - prev = 0; - while(p) { - if(p == rrset) { - if(prev) prev->rrset_all_next = p->rrset_all_next; - else msg->rrset_first = p->rrset_all_next; - if(msg->rrset_last == rrset) - msg->rrset_last = prev; - break; - } - prev = p; - p = p->rrset_all_next; - } - /* remove from count */ - switch(rrset->section) { - case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; - case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break; - case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break; - default: log_assert(0); - } - /* insert at end of list */ - rrset->rrset_all_next = 0; - if(msg->rrset_last) - msg->rrset_last->rrset_all_next = rrset; - else msg->rrset_first = rrset; - msg->rrset_last = rrset; - /* up count of new section */ - switch(section) { - case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; - case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; - default: log_assert(0); - } - rrset->section = section; -} - -/** see if rrset of type RRSIG contains sig over given type */ -static int -rrset_has_sigover(sldns_buffer* pkt, struct rrset_parse* rrset, uint16_t type, - int* hasother) -{ - int res = 0; - struct rr_parse* rr = rrset->rr_first; - log_assert( rrset->type == LDNS_RR_TYPE_RRSIG ); - while(rr) { - if(pkt_rrsig_covered_equals(pkt, rr->ttl_data, type)) - res = 1; - else *hasother = 1; - rr = rr->next; - } - return res; -} - -/** move rrsigs from sigset to dataset */ -static int -moveover_rrsigs(sldns_buffer* pkt, struct regional* region, - struct rrset_parse* sigset, struct rrset_parse* dataset, int duplicate) -{ - struct rr_parse* sig = sigset->rr_first; - struct rr_parse* prev = NULL; - struct rr_parse* insert; - struct rr_parse* nextsig; - while(sig) { - nextsig = sig->next; - if(pkt_rrsig_covered_equals(pkt, sig->ttl_data, - dataset->type)) { - if(duplicate) { - /* new */ - insert = (struct rr_parse*)regional_alloc( - region, sizeof(struct rr_parse)); - if(!insert) return 0; - insert->outside_packet = 0; - insert->ttl_data = sig->ttl_data; - insert->size = sig->size; - /* prev not used */ - } else { - /* remove from sigset */ - if(prev) prev->next = sig->next; - else sigset->rr_first = sig->next; - if(sigset->rr_last == sig) - sigset->rr_last = prev; - sigset->rr_count--; - sigset->size -= sig->size; - insert = sig; - /* prev not changed */ - } - /* add to dataset */ - dataset->rrsig_count++; - insert->next = 0; - if(dataset->rrsig_last) - dataset->rrsig_last->next = insert; - else dataset->rrsig_first = insert; - dataset->rrsig_last = insert; - dataset->size += insert->size; - } else { - prev = sig; - } - sig = nextsig; - } - return 1; -} - -/** change an rrsig rrset for use as data rrset */ -static struct rrset_parse* -change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg, - sldns_buffer* pkt, uint16_t datatype, uint32_t rrset_flags, - int hasother, sldns_pkt_section section, struct regional* region) -{ - struct rrset_parse* dataset = sigset; - hashvalue_type hash = pkt_hash_rrset(pkt, sigset->dname, datatype, - sigset->rrset_class, rrset_flags); - log_assert( sigset->type == LDNS_RR_TYPE_RRSIG ); - log_assert( datatype != LDNS_RR_TYPE_RRSIG ); - if(hasother) { - /* need to make new rrset to hold data type */ - dataset = new_rrset(msg, sigset->dname, sigset->dname_len, - datatype, sigset->rrset_class, hash, rrset_flags, - section, region); - if(!dataset) - return NULL; - switch(section) { - case LDNS_SECTION_ANSWER: msg->an_rrsets++; break; - case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; - case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; - default: log_assert(0); - } - if(!moveover_rrsigs(pkt, region, sigset, dataset, - msg->qtype == LDNS_RR_TYPE_RRSIG || - (msg->qtype == LDNS_RR_TYPE_ANY && - section != LDNS_SECTION_ANSWER) )) - return NULL; - return dataset; - } - /* changeover the type of the rrset to data set */ - msgparse_bucket_remove(msg, dataset); - /* insert into new hash bucket */ - dataset->rrset_bucket_next = msg->hashtable[hash&(PARSE_TABLE_SIZE-1)]; - msg->hashtable[hash&(PARSE_TABLE_SIZE-1)] = dataset; - dataset->hash = hash; - /* use section of data item for result */ - change_section(msg, dataset, section); - dataset->type = datatype; - dataset->flags = rrset_flags; - dataset->rrsig_count += dataset->rr_count; - dataset->rr_count = 0; - /* move sigs to end of siglist */ - if(dataset->rrsig_last) - dataset->rrsig_last->next = dataset->rr_first; - else dataset->rrsig_first = dataset->rr_first; - dataset->rrsig_last = dataset->rr_last; - dataset->rr_first = 0; - dataset->rr_last = 0; - return dataset; -} - -/** Find rrset. If equal to previous it is fast. hash if not so. - * @param msg: the message with hash table. - * @param pkt: the packet in wireformat (needed for compression ptrs). - * @param dname: pointer to start of dname (compressed) in packet. - * @param dnamelen: uncompressed wirefmt length of dname. - * @param type: type of current rr. - * @param dclass: class of current rr. - * @param hash: hash value is returned if the rrset could not be found. - * @param rrset_flags: is returned if the rrset could not be found. - * @param prev_dname_first: dname of last seen RR. First seen dname. - * @param prev_dname_last: dname of last seen RR. Last seen dname. - * @param prev_dnamelen: dname len of last seen RR. - * @param prev_type: type of last seen RR. - * @param prev_dclass: class of last seen RR. - * @param rrset_prev: last seen RRset. - * @param section: the current section in the packet. - * @param region: used to allocate temporary parsing data. - * @return 0 on out of memory. - */ -static int -find_rrset(struct msg_parse* msg, sldns_buffer* pkt, uint8_t* dname, - size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type* hash, - uint32_t* rrset_flags, - uint8_t** prev_dname_first, uint8_t** prev_dname_last, - size_t* prev_dnamelen, uint16_t* prev_type, - uint16_t* prev_dclass, struct rrset_parse** rrset_prev, - sldns_pkt_section section, struct regional* region) -{ - hashvalue_type dname_h = pkt_hash_rrset_first(pkt, dname); - uint16_t covtype; - if(*rrset_prev) { - /* check if equal to previous item */ - if(type == *prev_type && dclass == *prev_dclass && - dnamelen == *prev_dnamelen && - smart_compare(pkt, dname, *prev_dname_first, - *prev_dname_last) == 0 && - type != LDNS_RR_TYPE_RRSIG) { - /* same as previous */ - *prev_dname_last = dname; - return 1; - } - /* check if rrsig over previous item */ - if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass && - pkt_rrsig_covered_equals(pkt, sldns_buffer_current(pkt), - *prev_type) && - smart_compare(pkt, dname, *prev_dname_first, - *prev_dname_last) == 0) { - /* covers previous */ - *prev_dname_last = dname; - return 1; - } - } - /* find by hashing and lookup in hashtable */ - *rrset_flags = pkt_rrset_flags(pkt, type, section); - - /* if rrsig - try to lookup matching data set first */ - if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt, - sldns_buffer_current(pkt), &covtype)) { - *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, - *rrset_flags); - *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, - *rrset_flags, dname, dnamelen, covtype, dclass); - if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) { - /* if NSEC try with NSEC apex bit twiddled */ - *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; - *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, - *rrset_flags); - *rrset_prev = msgparse_hashtable_lookup(msg, pkt, - *hash, *rrset_flags, dname, dnamelen, covtype, - dclass); - if(!*rrset_prev) /* untwiddle if not found */ - *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; - } - if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) { - /* if SOA try with SOA neg flag twiddled */ - *rrset_flags ^= PACKED_RRSET_SOA_NEG; - *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, - *rrset_flags); - *rrset_prev = msgparse_hashtable_lookup(msg, pkt, - *hash, *rrset_flags, dname, dnamelen, covtype, - dclass); - if(!*rrset_prev) /* untwiddle if not found */ - *rrset_flags ^= PACKED_RRSET_SOA_NEG; - } - if(*rrset_prev) { - *prev_dname_first = (*rrset_prev)->dname; - *prev_dname_last = dname; - *prev_dnamelen = dnamelen; - *prev_type = covtype; - *prev_dclass = dclass; - return 1; - } - } - if(type != LDNS_RR_TYPE_RRSIG) { - int hasother = 0; - /* find matching rrsig */ - *hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG, - dclass, 0); - *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, - 0, dname, dnamelen, LDNS_RR_TYPE_RRSIG, - dclass); - if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type, - &hasother)) { - /* yes! */ - *prev_dname_first = (*rrset_prev)->dname; - *prev_dname_last = dname; - *prev_dnamelen = dnamelen; - *prev_type = type; - *prev_dclass = dclass; - *rrset_prev = change_rrsig_rrset(*rrset_prev, msg, - pkt, type, *rrset_flags, hasother, section, - region); - if(!*rrset_prev) return 0; - return 1; - } - } - - *hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags); - *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags, - dname, dnamelen, type, dclass); - if(*rrset_prev) - *prev_dname_first = (*rrset_prev)->dname; - else *prev_dname_first = dname; - *prev_dname_last = dname; - *prev_dnamelen = dnamelen; - *prev_type = type; - *prev_dclass = dclass; - return 1; -} - -/** - * Parse query section. - * @param pkt: packet, position at call must be at start of query section. - * at end position is after query section. - * @param msg: store results here. - * @return: 0 if OK, or rcode on error. - */ -static int -parse_query_section(sldns_buffer* pkt, struct msg_parse* msg) -{ - if(msg->qdcount == 0) - return 0; - if(msg->qdcount > 1) - return LDNS_RCODE_FORMERR; - log_assert(msg->qdcount == 1); - if(sldns_buffer_remaining(pkt) <= 0) - return LDNS_RCODE_FORMERR; - msg->qname = sldns_buffer_current(pkt); - if((msg->qname_len = pkt_dname_len(pkt)) == 0) - return LDNS_RCODE_FORMERR; - if(sldns_buffer_remaining(pkt) < sizeof(uint16_t)*2) - return LDNS_RCODE_FORMERR; - msg->qtype = sldns_buffer_read_u16(pkt); - msg->qclass = sldns_buffer_read_u16(pkt); - return 0; -} - -size_t -get_rdf_size(sldns_rdf_type rdf) -{ - switch(rdf) { - case LDNS_RDF_TYPE_CLASS: - case LDNS_RDF_TYPE_ALG: - case LDNS_RDF_TYPE_INT8: - return 1; - break; - case LDNS_RDF_TYPE_INT16: - case LDNS_RDF_TYPE_TYPE: - case LDNS_RDF_TYPE_CERT_ALG: - return 2; - break; - case LDNS_RDF_TYPE_INT32: - case LDNS_RDF_TYPE_TIME: - case LDNS_RDF_TYPE_A: - case LDNS_RDF_TYPE_PERIOD: - return 4; - break; - case LDNS_RDF_TYPE_TSIGTIME: - return 6; - break; - case LDNS_RDF_TYPE_AAAA: - return 16; - break; - default: - log_assert(0); /* add type above */ - /* only types that appear before a domain * - * name are needed. rest is simply copied. */ - } - return 0; -} - -/** calculate the size of one rr */ -static int -calc_size(sldns_buffer* pkt, uint16_t type, struct rr_parse* rr) -{ - const sldns_rr_descriptor* desc; - uint16_t pkt_len; /* length of rr inside the packet */ - rr->size = sizeof(uint16_t); /* the rdatalen */ - sldns_buffer_skip(pkt, 4); /* skip ttl */ - pkt_len = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < pkt_len) - return 0; - desc = sldns_rr_descript(type); - if(pkt_len > 0 && desc && desc->_dname_count > 0) { - int count = (int)desc->_dname_count; - int rdf = 0; - size_t len; - size_t oldpos; - /* skip first part. */ - while(pkt_len > 0 && count) { - switch(desc->_wireformat[rdf]) { - case LDNS_RDF_TYPE_DNAME: - /* decompress every domain name */ - oldpos = sldns_buffer_position(pkt); - if((len = pkt_dname_len(pkt)) == 0) - return 0; /* malformed dname */ - if(sldns_buffer_position(pkt)-oldpos > pkt_len) - return 0; /* dname exceeds rdata */ - pkt_len -= sldns_buffer_position(pkt)-oldpos; - rr->size += len; - count--; - len = 0; - break; - case LDNS_RDF_TYPE_STR: - if(pkt_len < 1) { - /* NOTREACHED, due to 'while(>0)' */ - return 0; /* len byte exceeds rdata */ - } - len = sldns_buffer_current(pkt)[0] + 1; - break; - default: - len = get_rdf_size(desc->_wireformat[rdf]); - } - if(len) { - if(pkt_len < len) - return 0; /* exceeds rdata */ - pkt_len -= len; - sldns_buffer_skip(pkt, (ssize_t)len); - rr->size += len; - } - rdf++; - } - } - /* remaining rdata */ - rr->size += pkt_len; - sldns_buffer_skip(pkt, (ssize_t)pkt_len); - return 1; -} - -/** skip rr ttl and rdata */ -static int -skip_ttl_rdata(sldns_buffer* pkt) -{ - uint16_t rdatalen; - if(sldns_buffer_remaining(pkt) < 6) /* ttl + rdatalen */ - return 0; - sldns_buffer_skip(pkt, 4); /* ttl */ - rdatalen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdatalen) - return 0; - sldns_buffer_skip(pkt, (ssize_t)rdatalen); - return 1; -} - -/** see if RRSIG is a duplicate of another */ -static int -sig_is_double(sldns_buffer* pkt, struct rrset_parse* rrset, uint8_t* ttldata) -{ - uint16_t rlen, siglen; - size_t pos = sldns_buffer_position(pkt); - struct rr_parse* sig; - if(sldns_buffer_remaining(pkt) < 6) - return 0; - sldns_buffer_skip(pkt, 4); /* ttl */ - rlen = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rlen) { - sldns_buffer_set_position(pkt, pos); - return 0; - } - sldns_buffer_set_position(pkt, pos); - - sig = rrset->rrsig_first; - while(sig) { - /* check if rdatalen is same */ - memmove(&siglen, sig->ttl_data+4, sizeof(siglen)); - siglen = ntohs(siglen); - /* checks if data in packet is exactly the same, this means - * also dname in rdata is the same, but rrsig is not allowed - * to have compressed dnames anyway. If it is compressed anyway - * it will lead to duplicate rrs for qtype=RRSIG. (or ANY). - * - * Cannot use sig->size because size of the other one is not - * calculated yet. - */ - if(siglen == rlen) { - if(siglen>0 && memcmp(sig->ttl_data+6, ttldata+6, - siglen) == 0) { - /* same! */ - return 1; - } - } - sig = sig->next; - } - return 0; -} - -/** Add rr (from packet here) to rrset, skips rr */ -static int -add_rr_to_rrset(struct rrset_parse* rrset, sldns_buffer* pkt, - struct msg_parse* msg, struct regional* region, - sldns_pkt_section section, uint16_t type) -{ - struct rr_parse* rr; - /* check section of rrset. */ - if(rrset->section != section && type != LDNS_RR_TYPE_RRSIG && - rrset->type != LDNS_RR_TYPE_RRSIG) { - /* silently drop it - we drop the last part, since - * trust in rr data depends on the section it is in. - * the less trustworthy part is discarded. - * also the last part is more likely to be incomplete. - * RFC 2181: must put RRset only once in response. */ - /* - verbose(VERB_QUERY, "Packet contains rrset data in " - "multiple sections, dropped last part."); - log_buf(VERB_QUERY, "packet was", pkt); - */ - /* forwards */ - if(!skip_ttl_rdata(pkt)) - return LDNS_RCODE_FORMERR; - return 0; - } - - if( (msg->qtype == LDNS_RR_TYPE_RRSIG || - msg->qtype == LDNS_RR_TYPE_ANY) - && sig_is_double(pkt, rrset, sldns_buffer_current(pkt))) { - if(!skip_ttl_rdata(pkt)) - return LDNS_RCODE_FORMERR; - return 0; - } - - /* create rr */ - if(!(rr = (struct rr_parse*)regional_alloc(region, sizeof(*rr)))) - return LDNS_RCODE_SERVFAIL; - rr->outside_packet = 0; - rr->ttl_data = sldns_buffer_current(pkt); - rr->next = 0; - if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) { - if(rrset->rrsig_last) - rrset->rrsig_last->next = rr; - else rrset->rrsig_first = rr; - rrset->rrsig_last = rr; - rrset->rrsig_count++; - } else { - if(rrset->rr_last) - rrset->rr_last->next = rr; - else rrset->rr_first = rr; - rrset->rr_last = rr; - rrset->rr_count++; - } - - /* calc decompressed size */ - if(!calc_size(pkt, type, rr)) - return LDNS_RCODE_FORMERR; - rrset->size += rr->size; - - return 0; -} - -/** - * Parse packet RR section, for answer, authority and additional sections. - * @param pkt: packet, position at call must be at start of section. - * at end position is after section. - * @param msg: store results here. - * @param region: how to alloc results. - * @param section: section enum. - * @param num_rrs: how many rrs are in the section. - * @param num_rrsets: returns number of rrsets in the section. - * @return: 0 if OK, or rcode on error. - */ -static int -parse_section(sldns_buffer* pkt, struct msg_parse* msg, - struct regional* region, sldns_pkt_section section, - uint16_t num_rrs, size_t* num_rrsets) -{ - uint16_t i; - uint8_t* dname, *prev_dname_f = NULL, *prev_dname_l = NULL; - size_t dnamelen, prev_dnamelen = 0; - uint16_t type, prev_type = 0; - uint16_t dclass, prev_dclass = 0; - uint32_t rrset_flags = 0; - hashvalue_type hash = 0; - struct rrset_parse* rrset = NULL; - int r; - - if(num_rrs == 0) - return 0; - if(sldns_buffer_remaining(pkt) <= 0) - return LDNS_RCODE_FORMERR; - for(i=0; i_name: "??", - (int)type, - sldns_rr_descript(t)? - sldns_rr_descript(t)->_name: "??", - (int)t); - } else - fprintf(stderr, "parse of %s(%d)", - sldns_rr_descript(type)? - sldns_rr_descript(type)->_name: "??", - (int)type); - fprintf(stderr, " %s(%d) ", - sldns_lookup_by_id(sldns_rr_classes, - (int)ntohs(dclass))?sldns_lookup_by_id( - sldns_rr_classes, (int)ntohs(dclass))->name: - "??", (int)ntohs(dclass)); - dname_print(stderr, pkt, dname); - fprintf(stderr, "\n"); - } - - /* see if it is part of an existing RR set */ - if(!find_rrset(msg, pkt, dname, dnamelen, type, dclass, &hash, - &rrset_flags, &prev_dname_f, &prev_dname_l, - &prev_dnamelen, &prev_type, &prev_dclass, &rrset, - section, region)) - return LDNS_RCODE_SERVFAIL; - if(!rrset) { - /* it is a new RR set. hash&flags already calculated.*/ - (*num_rrsets)++; - rrset = new_rrset(msg, dname, dnamelen, type, dclass, - hash, rrset_flags, section, region); - if(!rrset) - return LDNS_RCODE_SERVFAIL; - } - else if(0) { - fprintf(stderr, "is part of existing: "); - dname_print(stderr, pkt, rrset->dname); - fprintf(stderr, " type %s(%d)\n", - sldns_rr_descript(rrset->type)? - sldns_rr_descript(rrset->type)->_name: "??", - (int)rrset->type); - } - /* add to rrset. */ - if((r=add_rr_to_rrset(rrset, pkt, msg, region, section, - type)) != 0) - return r; - } - return 0; -} - -int -parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region) -{ - int ret; - if(sldns_buffer_remaining(pkt) < LDNS_HEADER_SIZE) - return LDNS_RCODE_FORMERR; - /* read the header */ - sldns_buffer_read(pkt, &msg->id, sizeof(uint16_t)); - msg->flags = sldns_buffer_read_u16(pkt); - msg->qdcount = sldns_buffer_read_u16(pkt); - msg->ancount = sldns_buffer_read_u16(pkt); - msg->nscount = sldns_buffer_read_u16(pkt); - msg->arcount = sldns_buffer_read_u16(pkt); - if(msg->qdcount > 1) - return LDNS_RCODE_FORMERR; - if((ret = parse_query_section(pkt, msg)) != 0) - return ret; - if((ret = parse_section(pkt, msg, region, LDNS_SECTION_ANSWER, - msg->ancount, &msg->an_rrsets)) != 0) - return ret; - if((ret = parse_section(pkt, msg, region, LDNS_SECTION_AUTHORITY, - msg->nscount, &msg->ns_rrsets)) != 0) - return ret; - if(sldns_buffer_remaining(pkt) == 0 && msg->arcount == 1) { - /* BIND accepts leniently that an EDNS record is missing. - * so, we do too. */ - } else if((ret = parse_section(pkt, msg, region, - LDNS_SECTION_ADDITIONAL, msg->arcount, &msg->ar_rrsets)) != 0) - return ret; - /* if(sldns_buffer_remaining(pkt) > 0) { */ - /* there is spurious data at end of packet. ignore */ - /* } */ - msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets; - return 0; -} - -/** parse EDNS options from EDNS wireformat rdata */ -static int -parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, - struct edns_data* edns, struct config_file* cfg, struct comm_point* c, - struct comm_reply* repinfo, uint32_t now, struct regional* region) -{ - /* To respond with a Keepalive option, the client connection must have - * received one message with a TCP Keepalive EDNS option, and that - * option must have 0 length data. Subsequent messages sent on that - * connection will have a TCP Keepalive option. - * - * In the if-statement below, the option is added unsolicited. This - * means that the client has sent an KEEPALIVE option earlier. We know - * here this is true, because c->tcp_keepalive is set. - */ - if (cfg && cfg->do_tcp_keepalive && c && c->type != comm_udp && c->tcp_keepalive) { - if(!edns_opt_list_append_keepalive(&edns->opt_list_out, - c->tcp_timeout_msec / 100, region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - } - - /* while still more options, and have code+len to read */ - /* ignores partial content (i.e. rdata len 3) */ - while(rdata_len >= 4) { - uint16_t opt_code = sldns_read_uint16(rdata_ptr); - uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); - uint8_t server_cookie[40]; - enum edns_cookie_val_status cookie_val_status; - int cookie_is_v4 = 1; - - rdata_ptr += 4; - rdata_len -= 4; - if(opt_len > rdata_len) - break; /* option code partial */ - - /* handle parse time edns options here */ - switch(opt_code) { - case LDNS_EDNS_NSID: - if (!cfg || !cfg->nsid) - break; - if(!edns_opt_list_append(&edns->opt_list_out, - LDNS_EDNS_NSID, cfg->nsid_len, - cfg->nsid, region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - break; - - case LDNS_EDNS_KEEPALIVE: - /* To respond with a Keepalive option, the client - * connection must have received one message with a TCP - * Keepalive EDNS option, and that option must have 0 - * length data. Subsequent messages sent on that - * connection will have a TCP Keepalive option. - * - * This should be the first time the client sends this - * option, so c->tcp_keepalive is not set. - * Besides adding the reply KEEPALIVE option, - * c->tcp_keepalive will be set so that the - * option will be added unsolicited in subsequent - * responses (see the comment above the if-statement - * at the start of this function). - */ - if (!cfg || !cfg->do_tcp_keepalive || !c || - c->type == comm_udp || c->tcp_keepalive) - break; - if(opt_len) { - verbose(VERB_ALGO, "query with bad edns keepalive."); - return LDNS_RCODE_FORMERR; - } - if(!edns_opt_list_append_keepalive(&edns->opt_list_out, - c->tcp_timeout_msec / 100, - region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - c->tcp_keepalive = 1; - break; - - case LDNS_EDNS_PADDING: - if(!cfg || !cfg->pad_responses || - !c || c->type != comm_tcp ||!c->ssl) - break; - if(!edns_opt_list_append(&edns->opt_list_out, - LDNS_EDNS_PADDING, - 0, NULL, region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - edns->padding_block_size = cfg->pad_responses_block_size; - break; - - case LDNS_EDNS_COOKIE: - if(!cfg || !cfg->do_answer_cookie || !repinfo) - break; - if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) { - verbose(VERB_ALGO, "worker request: " - "badly formatted cookie"); - return LDNS_RCODE_FORMERR; - } - edns->cookie_present = 1; - - /* Copy client cookie, version and timestamp for - * validation and creation purposes. - */ - if(opt_len >= 16) { - memmove(server_cookie, rdata_ptr, 16); - } else { - memset(server_cookie, 0, 16); - memmove(server_cookie, rdata_ptr, opt_len); - } - - /* Copy client ip for validation and creation - * purposes. It will be overwritten if (re)creation - * is needed. - */ - if(repinfo->remote_addr.ss_family == AF_INET) { - memcpy(server_cookie + 16, - &((struct sockaddr_in*)&repinfo->remote_addr)->sin_addr, 4); - } else { - cookie_is_v4 = 0; - memcpy(server_cookie + 16, - &((struct sockaddr_in6*)&repinfo->remote_addr)->sin6_addr, 16); - } - - cookie_val_status = edns_cookie_server_validate( - rdata_ptr, opt_len, cfg->cookie_secret, - cfg->cookie_secret_len, cookie_is_v4, - server_cookie, now); - switch(cookie_val_status) { - case COOKIE_STATUS_VALID: - case COOKIE_STATUS_VALID_RENEW: - edns->cookie_valid = 1; - /* Reuse cookie */ - if(!edns_opt_list_append( - &edns->opt_list_out, LDNS_EDNS_COOKIE, - opt_len, rdata_ptr, region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - /* Cookie to be reused added to outgoing - * options. Done! - */ - break; - case COOKIE_STATUS_CLIENT_ONLY: - edns->cookie_client = 1; - /* fallthrough */ - case COOKIE_STATUS_FUTURE: - case COOKIE_STATUS_EXPIRED: - case COOKIE_STATUS_INVALID: - default: - edns_cookie_server_write(server_cookie, - cfg->cookie_secret, cookie_is_v4, now); - if(!edns_opt_list_append(&edns->opt_list_out, - LDNS_EDNS_COOKIE, 24, server_cookie, - region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - break; - } - break; - default: - break; - } - if(!edns_opt_list_append(&edns->opt_list_in, - opt_code, opt_len, rdata_ptr, region)) { - log_err("out of memory"); - return LDNS_RCODE_SERVFAIL; - } - rdata_ptr += opt_len; - rdata_len -= opt_len; - } - return LDNS_RCODE_NOERROR; -} - -int -parse_extract_edns_from_response_msg(struct msg_parse* msg, - struct edns_data* edns, struct regional* region) -{ - struct rrset_parse* rrset = msg->rrset_first; - struct rrset_parse* prev = 0; - struct rrset_parse* found = 0; - struct rrset_parse* found_prev = 0; - size_t rdata_len; - uint8_t* rdata_ptr; - /* since the class encodes the UDP size, we cannot use hash table to - * find the EDNS OPT record. Scan the packet. */ - while(rrset) { - if(rrset->type == LDNS_RR_TYPE_OPT) { - /* only one OPT RR allowed. */ - if(found) return LDNS_RCODE_FORMERR; - /* found it! */ - found_prev = prev; - found = rrset; - } - prev = rrset; - rrset = rrset->rrset_all_next; - } - if(!found) { - memset(edns, 0, sizeof(*edns)); - edns->udp_size = 512; - return 0; - } - /* check the found RRset */ - /* most lenient check possible. ignore dname, use last opt */ - if(found->section != LDNS_SECTION_ADDITIONAL) - return LDNS_RCODE_FORMERR; - if(found->rr_count == 0) - return LDNS_RCODE_FORMERR; - if(0) { /* strict checking of dname and RRcount */ - if(found->dname_len != 1 || !found->dname - || found->dname[0] != 0) return LDNS_RCODE_FORMERR; - if(found->rr_count != 1) return LDNS_RCODE_FORMERR; - } - log_assert(found->rr_first && found->rr_last); - - /* remove from packet */ - if(found_prev) found_prev->rrset_all_next = found->rrset_all_next; - else msg->rrset_first = found->rrset_all_next; - if(found == msg->rrset_last) - msg->rrset_last = found_prev; - msg->arcount --; - msg->ar_rrsets --; - msg->rrset_count --; - - /* take the data ! */ - edns->edns_present = 1; - edns->ext_rcode = found->rr_last->ttl_data[0]; - edns->edns_version = found->rr_last->ttl_data[1]; - edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]); - edns->udp_size = ntohs(found->rrset_class); - edns->opt_list_in = NULL; - edns->opt_list_out = NULL; - edns->opt_list_inplace_cb_out = NULL; - edns->padding_block_size = 0; - edns->cookie_present = 0; - edns->cookie_valid = 0; - - /* take the options */ - rdata_len = found->rr_first->size-2; - rdata_ptr = found->rr_first->ttl_data+6; - - /* while still more options, and have code+len to read */ - /* ignores partial content (i.e. rdata len 3) */ - while(rdata_len >= 4) { - uint16_t opt_code = sldns_read_uint16(rdata_ptr); - uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); - rdata_ptr += 4; - rdata_len -= 4; - if(opt_len > rdata_len) - break; /* option code partial */ - - if(!edns_opt_list_append(&edns->opt_list_in, - opt_code, opt_len, rdata_ptr, region)) { - log_err("out of memory"); - break; - } - rdata_ptr += opt_len; - rdata_len -= opt_len; - } - /* ignore rrsigs */ - return LDNS_RCODE_NOERROR; -} - -/** skip RR in packet */ -static int -skip_pkt_rr(sldns_buffer* pkt) -{ - if(sldns_buffer_remaining(pkt) < 1) return 0; - if(!pkt_dname_len(pkt)) - return 0; - if(sldns_buffer_remaining(pkt) < 4) return 0; - sldns_buffer_skip(pkt, 4); /* type and class */ - if(!skip_ttl_rdata(pkt)) - return 0; - return 1; -} - -/** skip RRs from packet */ -int -skip_pkt_rrs(sldns_buffer* pkt, int num) -{ - int i; - for(i=0; i 1) { - return LDNS_RCODE_FORMERR; - } - if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) == 0) { - edns->udp_size = 512; - return 0; - } - /* domain name must be the root of length 1. */ - if(pkt_dname_len(pkt) != 1) - return LDNS_RCODE_FORMERR; - if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */ - return LDNS_RCODE_FORMERR; - if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT) - return LDNS_RCODE_FORMERR; - edns->edns_present = 1; - edns->udp_size = sldns_buffer_read_u16(pkt); /* class is udp size */ - edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */ - edns->edns_version = sldns_buffer_read_u8(pkt); - edns->bits = sldns_buffer_read_u16(pkt); - edns->opt_list_in = NULL; - edns->opt_list_out = NULL; - edns->opt_list_inplace_cb_out = NULL; - edns->padding_block_size = 0; - edns->cookie_present = 0; - edns->cookie_valid = 0; - - /* take the options */ - rdata_len = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < rdata_len) - return LDNS_RCODE_FORMERR; - rdata_ptr = sldns_buffer_current(pkt); - /* ignore rrsigs */ - return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg, - c, repinfo, now, region); -} - -void -log_edns_opt_list(enum verbosity_value level, const char* info_str, - struct edns_option* list) -{ - if(verbosity >= level && list) { - char str[128], *s; - size_t slen; - verbose(level, "%s", info_str); - while(list) { - s = str; - slen = sizeof(str); - (void)sldns_wire2str_edns_option_print(&s, &slen, list->opt_code, - list->opt_data, list->opt_len); - verbose(level, " %s", str); - list = list->next; - } - } -} - diff --git a/crates/libunbound-sys/unbound/util/data/msgparse.h b/crates/libunbound-sys/unbound/util/data/msgparse.h deleted file mode 100644 index b7dc235d..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgparse.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * util/data/msgparse.h - parse wireformat DNS messages. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Contains message parsing data structures. - * These point back into the packet buffer. - * - * During parsing RRSIGS are put together with the rrsets they (claim to) sign. - * This process works as follows: - * o if RRSIG follows the data rrset, it is added to the rrset rrsig list. - * o if no matching data rrset is found, the RRSIG becomes a new rrset. - * o If the data rrset later follows the RRSIG - * o See if the RRSIG rrset contains multiple types, and needs to - * have the rrsig(s) for that data type split off. - * o Put the data rr as data type in the rrset and rrsig in list. - * o RRSIGs are allowed to move to a different section. The section of - * the data item is used for the final rrset. - * o multiple signatures over an RRset are possible. - * - * For queries of qtype=RRSIG, some special handling is needed, to avoid - * splitting the RRSIG in the answer section. - * o duplicate, not split, RRSIGs from the answer section, if qtype=RRSIG. - * o check for doubles in the rrsig list when adding an RRSIG to data, - * so that a data rrset is signed by RRSIGs with different rdata. - * when qtype=RRSIG. - * This will move the RRSIG from the answer section to sign the data further - * in the packet (if possible). If then after that, more RRSIGs are found - * that sign the data as well, doubles are removed. - */ - -#ifndef UTIL_DATA_MSGPARSE_H -#define UTIL_DATA_MSGPARSE_H -#include "util/storage/lruhash.h" -#include "sldns/pkthdr.h" -#include "sldns/rrdef.h" -struct sldns_buffer; -struct rrset_parse; -struct rr_parse; -struct regional; -struct edns_option; -struct config_file; -struct comm_point; -struct comm_reply; - -/** number of buckets in parse rrset hash table. Must be power of 2. */ -#define PARSE_TABLE_SIZE 32 -/** Maximum TTL that is allowed. */ -extern time_t MAX_TTL; -/** Minimum TTL that is allowed. */ -extern time_t MIN_TTL; -/** Maximum Negative TTL that is allowed */ -extern time_t MAX_NEG_TTL; -/** If we serve expired entries and prefetch them */ -extern int SERVE_EXPIRED; -/** Time to serve records after expiration */ -extern time_t SERVE_EXPIRED_TTL; -/** TTL to use for expired records */ -extern time_t SERVE_EXPIRED_REPLY_TTL; -/** Negative cache time (for entries without any RRs.) */ -#define NORR_TTL 5 /* seconds */ -/** If we serve the original TTL or decrementing TTLs */ -extern int SERVE_ORIGINAL_TTL; - -/** - * Data stored in scratch pad memory during parsing. - * Stores the data that will enter into the msgreply and packet result. - */ -struct msg_parse { - /** id from message, network format. */ - uint16_t id; - /** flags from message, host format. */ - uint16_t flags; - /** count of RRs, host format */ - uint16_t qdcount; - /** count of RRs, host format */ - uint16_t ancount; - /** count of RRs, host format */ - uint16_t nscount; - /** count of RRs, host format */ - uint16_t arcount; - /** count of RRsets per section. */ - size_t an_rrsets; - /** count of RRsets per section. */ - size_t ns_rrsets; - /** count of RRsets per section. */ - size_t ar_rrsets; - /** total number of rrsets found. */ - size_t rrset_count; - - /** query dname (pointer to start location in packet, NULL if none */ - uint8_t* qname; - /** length of query dname in octets, 0 if none */ - size_t qname_len; - /** query type, host order. 0 if qdcount=0 */ - uint16_t qtype; - /** query class, host order. 0 if qdcount=0 */ - uint16_t qclass; - - /** - * Hash table array used during parsing to lookup rrset types. - * Based on name, type, class. Same hash value as in rrset cache. - */ - struct rrset_parse* hashtable[PARSE_TABLE_SIZE]; - - /** linked list of rrsets that have been found (in order). */ - struct rrset_parse* rrset_first; - /** last element of rrset list. */ - struct rrset_parse* rrset_last; -}; - -/** - * Data stored for an rrset during parsing. - */ -struct rrset_parse { - /** next in hash bucket */ - struct rrset_parse* rrset_bucket_next; - /** next in list of all rrsets */ - struct rrset_parse* rrset_all_next; - /** hash value of rrset */ - hashvalue_type hash; - /** which section was it found in: one of - * LDNS_SECTION_ANSWER, LDNS_SECTION_AUTHORITY, LDNS_SECTION_ADDITIONAL - */ - sldns_pkt_section section; - /** start of (possibly compressed) dname in packet */ - uint8_t* dname; - /** length of the dname uncompressed wireformat */ - size_t dname_len; - /** type, host order. */ - uint16_t type; - /** class, network order. var name so that it is not a c++ keyword. */ - uint16_t rrset_class; - /** the flags for the rrset, like for packedrrset */ - uint32_t flags; - /** number of RRs in the rr list */ - size_t rr_count; - /** sum of RR rdata sizes */ - size_t size; - /** linked list of RRs in this rrset. */ - struct rr_parse* rr_first; - /** last in list of RRs in this rrset. */ - struct rr_parse* rr_last; - /** number of RRSIGs over this rrset. */ - size_t rrsig_count; - /** linked list of RRsig RRs over this rrset. */ - struct rr_parse* rrsig_first; - /** last in list of RRSIG RRs over this rrset. */ - struct rr_parse* rrsig_last; -}; - -/** - * Data stored for an RR during parsing. - */ -struct rr_parse { - /** - * Pointer to the RR. Points to start of TTL value in the packet. - * Rdata length and rdata follow it. - * its dname, type and class are the same and stored for the rrset. - */ - uint8_t* ttl_data; - /** true if ttl_data is not part of the packet, but elsewhere in mem. - * Set for generated CNAMEs for DNAMEs. */ - int outside_packet; - /** the length of the rdata if allocated (with no dname compression)*/ - size_t size; - /** next in list of RRs. */ - struct rr_parse* next; -}; - -/** Check if label length is first octet of a compression pointer, pass u8. */ -#define LABEL_IS_PTR(x) ( ((x)&0xc0) == 0xc0 ) -/** Calculate destination offset of a compression pointer. pass first and - * second octets of the compression pointer. */ -#define PTR_OFFSET(x, y) ( ((x)&0x3f)<<8 | (y) ) -/** create a compression pointer to the given offset. */ -#define PTR_CREATE(offset) ((uint16_t)(0xc000 | (offset))) - -/** error codes, extended with EDNS, so > 15. */ -#define EDNS_RCODE_BADVERS 16 /** bad EDNS version */ -/** largest valid compression offset */ -#define PTR_MAX_OFFSET 0x3fff - -/** - * EDNS data storage - * rdata is parsed in a list (has accessor functions). allocated in a - * region. - */ -struct edns_data { - /** Extended RCODE */ - uint8_t ext_rcode; - /** The EDNS version number */ - uint8_t edns_version; - /** the EDNS bits field from ttl (host order): Z */ - uint16_t bits; - /** UDP reassembly size. */ - uint16_t udp_size; - /** rdata element list of options of an incoming packet created at - * parse time, or NULL if none */ - struct edns_option* opt_list_in; - /** rdata element list of options to encode for outgoing packets, - * or NULL if none */ - struct edns_option* opt_list_out; - /** rdata element list of outgoing edns options from modules - * or NULL if none */ - struct edns_option* opt_list_inplace_cb_out; - /** block size to pad */ - uint16_t padding_block_size; - /** if EDNS OPT record was present */ - unsigned int edns_present : 1; - /** if a cookie was present */ - unsigned int cookie_present : 1; - /** if the cookie validated */ - unsigned int cookie_valid : 1; - /** if the cookie holds only the client part */ - unsigned int cookie_client : 1; -}; - -/** - * EDNS option - */ -struct edns_option { - /** next item in list */ - struct edns_option* next; - /** type of this edns option */ - uint16_t opt_code; - /** length of this edns option (cannot exceed uint16 in encoding) */ - size_t opt_len; - /** data of this edns option; allocated in region, or NULL if len=0 */ - uint8_t* opt_data; -}; - -/** - * Obtain size in the packet of an rr type, that is before dname type. - * Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types. - * @param rdf: the rdf type from the descriptor. - * @return: size in octets. 0 on failure. - */ -size_t get_rdf_size(sldns_rdf_type rdf); - -/** - * Parse the packet. - * @param pkt: packet, position at call must be at start of packet. - * at end position is after packet. - * @param msg: where to store results. - * @param region: how to alloc results. - * @return: 0 if OK, or rcode on error. - */ -int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg, - struct regional* region); - -/** - * After parsing the packet, extract EDNS data from packet. - * If not present this is noted in the data structure. - * If a parse error happens, an error code is returned. - * - * Quirks: - * o ignores OPT rdata. - * o ignores OPT owner name. - * o ignores extra OPT records, except the last one in the packet. - * - * @param msg: parsed message structure. Modified on exit, if EDNS was present - * it is removed from the additional section. - * @param edns: the edns data is stored here. Does not have to be initialised. - * @param region: region to alloc results in (edns option contents) - * @return: 0 on success. or an RCODE on an error. - * RCODE formerr if OPT in wrong section, and so on. - */ -int parse_extract_edns_from_response_msg(struct msg_parse* msg, - struct edns_data* edns, struct regional* region); - -/** - * Skip RRs from packet - * @param pkt: the packet. position at start must be right after the query - * section. At end, right after EDNS data or no movement if failed. - * @param num: Limit of the number of records we want to parse. - * @return: 0 on success, 1 on failure. - */ -int skip_pkt_rrs(struct sldns_buffer* pkt, int num); - -/** - * If EDNS data follows a query section, extract it and initialize edns struct. - * @param pkt: the packet. position at start must be right after the query - * section. At end, right after EDNS data or no movement if failed. - * @param edns: the edns data allocated by the caller. Does not have to be - * initialised. - * @param cfg: the configuration (with nsid value etc.) - * @param c: commpoint to determine transport (if needed) - * @param repinfo: commreply to determine the client address - * @param now: current time - * @param region: region to alloc results in (edns option contents) - * @return: 0 on success, or an RCODE on error. - * RCODE formerr if OPT is badly formatted and so on. - */ -int parse_edns_from_query_pkt(struct sldns_buffer* pkt, struct edns_data* edns, - struct config_file* cfg, struct comm_point* c, - struct comm_reply* repinfo, time_t now, struct regional* region); - -/** - * Calculate hash value for rrset in packet. - * @param pkt: the packet. - * @param dname: pointer to uncompressed dname, or compressed dname in packet. - * @param type: rrset type in host order. - * @param dclass: rrset class in network order. - * @param rrset_flags: rrset flags (same as packed_rrset flags). - * @return hash value - */ -hashvalue_type pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname, - uint16_t type, uint16_t dclass, uint32_t rrset_flags); - -/** - * Lookup in msg hashtable to find a rrset. - * @param msg: with the hashtable. - * @param pkt: packet for compressed names. - * @param h: hash value - * @param rrset_flags: flags of rrset sought for. - * @param dname: name of rrset sought for. - * @param dnamelen: len of dname. - * @param type: rrset type, host order. - * @param dclass: rrset class, network order. - * @return NULL or the rrset_parse if found. - */ -struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg, - struct sldns_buffer* pkt, hashvalue_type h, uint32_t rrset_flags, - uint8_t* dname, size_t dnamelen, uint16_t type, uint16_t dclass); - -/** - * Remove rrset from hash table. - * @param msg: with hashtable. - * @param rrset: with hash value and id info. - */ -void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset); - -/** - * Log the edns options in the edns option list. - * @param level: the verbosity level. - * @param info_str: the informational string to be printed before the options. - * @param list: the edns option list. - */ -void log_edns_opt_list(enum verbosity_value level, const char* info_str, - struct edns_option* list); - -#endif /* UTIL_DATA_MSGPARSE_H */ diff --git a/crates/libunbound-sys/unbound/util/data/msgreply.c b/crates/libunbound-sys/unbound/util/data/msgreply.c deleted file mode 100644 index 920a0a93..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgreply.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* - * util/data/msgreply.c - store message and reply data. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a data structure to store a message and its reply. - */ - -#include "config.h" -#include "util/data/msgreply.h" -#include "util/storage/lookup3.h" -#include "util/log.h" -#include "util/alloc.h" -#include "util/netevent.h" -#include "util/net_help.h" -#include "util/data/dname.h" -#include "util/regional.h" -#include "util/data/msgparse.h" -#include "util/data/msgencode.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "util/module.h" -#include "util/fptr_wlist.h" - -/** MAX TTL default for messages and rrsets */ -time_t MAX_TTL = 3600 * 24 * 10; /* ten days */ -/** MIN TTL default for messages and rrsets */ -time_t MIN_TTL = 0; -/** MAX Negative TTL, for SOA records in authority section */ -time_t MAX_NEG_TTL = 3600; /* one hour */ -/** If we serve expired entries and prefetch them */ -int SERVE_EXPIRED = 0; -/** Time to serve records after expiration */ -time_t SERVE_EXPIRED_TTL = 0; -/** TTL to use for expired records */ -time_t SERVE_EXPIRED_REPLY_TTL = 30; -/** If we serve the original TTL or decrementing TTLs */ -int SERVE_ORIGINAL_TTL = 0; - -/** allocate qinfo, return 0 on error */ -static int -parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg, - struct query_info* qinf, struct regional* region) -{ - if(msg->qname) { - if(region) - qinf->qname = (uint8_t*)regional_alloc(region, - msg->qname_len); - else qinf->qname = (uint8_t*)malloc(msg->qname_len); - if(!qinf->qname) return 0; - dname_pkt_copy(pkt, qinf->qname, msg->qname); - } else qinf->qname = 0; - qinf->qname_len = msg->qname_len; - qinf->qtype = msg->qtype; - qinf->qclass = msg->qclass; - qinf->local_alias = NULL; - return 1; -} - -/** constructor for replyinfo */ -struct reply_info* -construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, - time_t ttl, time_t prettl, time_t expttl, size_t an, size_t ns, - size_t ar, size_t total, enum sec_status sec, sldns_ede_code reason_bogus) -{ - struct reply_info* rep; - /* rrset_count-1 because the first ref is part of the struct. */ - size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) + - sizeof(struct ub_packed_rrset_key*) * total; - if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/ - if(region) - rep = (struct reply_info*)regional_alloc(region, s); - else rep = (struct reply_info*)malloc(s + - sizeof(struct rrset_ref) * (total)); - if(!rep) - return NULL; - rep->flags = flags; - rep->qdcount = qd; - rep->ttl = ttl; - rep->prefetch_ttl = prettl; - rep->serve_expired_ttl = expttl; - rep->an_numrrsets = an; - rep->ns_numrrsets = ns; - rep->ar_numrrsets = ar; - rep->rrset_count = total; - rep->security = sec; - rep->reason_bogus = reason_bogus; - /* this is only allocated and used for caching on copy */ - rep->reason_bogus_str = NULL; - rep->authoritative = 0; - /* array starts after the refs */ - if(region) - rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]); - else rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]); - /* zero the arrays to assist cleanup in case of malloc failure */ - memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total); - if(!region) - memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total); - return rep; -} - -/** allocate replyinfo, return 0 on error */ -static int -parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep, - struct regional* region) -{ - *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0, - 0, 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets, - msg->rrset_count, sec_status_unchecked, LDNS_EDE_NONE); - if(!*rep) - return 0; - return 1; -} - -int -reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, - struct regional* region) -{ - size_t i; - for(i=0; irrset_count; i++) { - if(region) { - rep->rrsets[i] = (struct ub_packed_rrset_key*) - regional_alloc(region, - sizeof(struct ub_packed_rrset_key)); - if(rep->rrsets[i]) { - memset(rep->rrsets[i], 0, - sizeof(struct ub_packed_rrset_key)); - rep->rrsets[i]->entry.key = rep->rrsets[i]; - } - } - else rep->rrsets[i] = alloc_special_obtain(alloc); - if(!rep->rrsets[i]) - return 0; - rep->rrsets[i]->entry.data = NULL; - } - return 1; -} - -struct reply_info * -make_new_reply_info(const struct reply_info* rep, struct regional* region, - size_t an_numrrsets, size_t copy_rrsets) -{ - struct reply_info* new_rep; - size_t i; - - /* create a base struct. we specify 'insecure' security status as - * the modified response won't be DNSSEC-valid. In our faked response - * the authority and additional sections will be empty (except possible - * EDNS0 OPT RR in the additional section appended on sending it out), - * so the total number of RRsets is an_numrrsets. */ - new_rep = construct_reply_info_base(region, rep->flags, - rep->qdcount, rep->ttl, rep->prefetch_ttl, - rep->serve_expired_ttl, an_numrrsets, 0, 0, an_numrrsets, - sec_status_insecure, LDNS_EDE_NONE); - if(!new_rep) - return NULL; - if(!reply_info_alloc_rrset_keys(new_rep, NULL, region)) - return NULL; - for(i=0; irrsets[i] = rep->rrsets[i]; - - return new_rep; -} - -/** find the minimumttl in the rdata of SOA record */ -static time_t -soa_find_minttl(struct rr_parse* rr) -{ - uint16_t rlen = sldns_read_uint16(rr->ttl_data+4); - if(rlen < 20) - return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */ - /* minimum TTL is the last 32bit value in the rdata of the record */ - /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/ - return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4); -} - -/** do the rdata copy */ -static int -rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, - struct rr_parse* rr, time_t* rr_ttl, uint16_t type, - sldns_pkt_section section) -{ - uint16_t pkt_len; - const sldns_rr_descriptor* desc; - - *rr_ttl = sldns_read_uint32(rr->ttl_data); - /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ - if(*rr_ttl & 0x80000000U) - *rr_ttl = 0; - if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { - /* negative response. see if TTL of SOA record larger than the - * minimum-ttl in the rdata of the SOA record */ - if(*rr_ttl > soa_find_minttl(rr)) - *rr_ttl = soa_find_minttl(rr); - } - if(!SERVE_ORIGINAL_TTL && (*rr_ttl < MIN_TTL)) - *rr_ttl = MIN_TTL; - if(!SERVE_ORIGINAL_TTL && (*rr_ttl > MAX_TTL)) - *rr_ttl = MAX_TTL; - if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { - /* max neg ttl overrides the min and max ttl of everything - * else, it is for a more specific record */ - if(*rr_ttl > MAX_NEG_TTL) - *rr_ttl = MAX_NEG_TTL; - } - if(*rr_ttl < data->ttl) - data->ttl = *rr_ttl; - - if(rr->outside_packet) { - /* uncompressed already, only needs copy */ - memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); - return 1; - } - - sldns_buffer_set_position(pkt, (size_t) - (rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t))); - /* insert decompressed size into rdata len stored in memory */ - /* -2 because rdatalen bytes are not included. */ - pkt_len = htons(rr->size - 2); - memmove(to, &pkt_len, sizeof(uint16_t)); - to += 2; - /* read packet rdata len */ - pkt_len = sldns_buffer_read_u16(pkt); - if(sldns_buffer_remaining(pkt) < pkt_len) - return 0; - desc = sldns_rr_descript(type); - if(pkt_len > 0 && desc && desc->_dname_count > 0) { - int count = (int)desc->_dname_count; - int rdf = 0; - size_t len; - size_t oldpos; - /* decompress dnames. */ - while(pkt_len > 0 && count) { - switch(desc->_wireformat[rdf]) { - case LDNS_RDF_TYPE_DNAME: - oldpos = sldns_buffer_position(pkt); - dname_pkt_copy(pkt, to, - sldns_buffer_current(pkt)); - to += pkt_dname_len(pkt); - pkt_len -= sldns_buffer_position(pkt)-oldpos; - count--; - len = 0; - break; - case LDNS_RDF_TYPE_STR: - len = sldns_buffer_current(pkt)[0] + 1; - break; - default: - len = get_rdf_size(desc->_wireformat[rdf]); - break; - } - if(len) { - log_assert(len <= pkt_len); - memmove(to, sldns_buffer_current(pkt), len); - to += len; - sldns_buffer_skip(pkt, (ssize_t)len); - pkt_len -= len; - } - rdf++; - } - } - /* copy remaining rdata */ - if(pkt_len > 0) - memmove(to, sldns_buffer_current(pkt), pkt_len); - - return 1; -} - -/** copy over the data into packed rrset */ -static int -parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, - struct packed_rrset_data* data) -{ - size_t i; - struct rr_parse* rr = pset->rr_first; - uint8_t* nextrdata; - size_t total = pset->rr_count + pset->rrsig_count; - data->ttl = MAX_TTL; - data->count = pset->rr_count; - data->rrsig_count = pset->rrsig_count; - data->trust = rrset_trust_none; - data->security = sec_status_unchecked; - /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */ - data->rr_len = (size_t*)((uint8_t*)data + - sizeof(struct packed_rrset_data)); - data->rr_data = (uint8_t**)&(data->rr_len[total]); - data->rr_ttl = (time_t*)&(data->rr_data[total]); - nextrdata = (uint8_t*)&(data->rr_ttl[total]); - for(i=0; icount; i++) { - data->rr_len[i] = rr->size; - data->rr_data[i] = nextrdata; - nextrdata += rr->size; - if(!rdata_copy(pkt, data, data->rr_data[i], rr, - &data->rr_ttl[i], pset->type, pset->section)) - return 0; - rr = rr->next; - } - /* if rrsig, its rdata is at nextrdata */ - rr = pset->rrsig_first; - for(i=data->count; irr_len[i] = rr->size; - data->rr_data[i] = nextrdata; - nextrdata += rr->size; - if(!rdata_copy(pkt, data, data->rr_data[i], rr, - &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section)) - return 0; - rr = rr->next; - } - return 1; -} - -/** create rrset return 0 on failure */ -static int -parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset, - struct packed_rrset_data** data, struct regional* region) -{ - /* allocate */ - size_t s; - if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX || - pset->size > RR_COUNT_MAX) - return 0; /* protect against integer overflow */ - s = sizeof(struct packed_rrset_data) + - (pset->rr_count + pset->rrsig_count) * - (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) + - pset->size; - if(region) - *data = regional_alloc_zero(region, s); - else *data = calloc(1, s); - if(!*data) - return 0; - /* copy & decompress */ - if(!parse_rr_copy(pkt, pset, *data)) { - if(!region) { - free(*data); - *data = NULL; - } - return 0; - } - return 1; -} - -/** get trust value for rrset */ -static enum rrset_trust -get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset) -{ - uint16_t AA = msg->flags & BIT_AA; - if(rrset->section == LDNS_SECTION_ANSWER) { - if(AA) { - /* RFC2181 says remainder of CNAME chain is nonauth*/ - if(msg->rrset_first && - msg->rrset_first->section==LDNS_SECTION_ANSWER - && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){ - if(rrset == msg->rrset_first) - return rrset_trust_ans_AA; - else return rrset_trust_ans_noAA; - } - if(msg->rrset_first && - msg->rrset_first->section==LDNS_SECTION_ANSWER - && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){ - if(rrset == msg->rrset_first || - rrset == msg->rrset_first->rrset_all_next) - return rrset_trust_ans_AA; - else return rrset_trust_ans_noAA; - } - return rrset_trust_ans_AA; - } - else return rrset_trust_ans_noAA; - } else if(rrset->section == LDNS_SECTION_AUTHORITY) { - if(AA) return rrset_trust_auth_AA; - else return rrset_trust_auth_noAA; - } else { - /* addit section */ - if(AA) return rrset_trust_add_AA; - else return rrset_trust_add_noAA; - } - /* NOTREACHED */ - return rrset_trust_none; -} - -int -parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg, - struct rrset_parse *pset, struct regional* region, - struct ub_packed_rrset_key* pk) -{ - struct packed_rrset_data* data; - pk->rk.flags = pset->flags; - pk->rk.dname_len = pset->dname_len; - if(region) - pk->rk.dname = (uint8_t*)regional_alloc( - region, pset->dname_len); - else pk->rk.dname = - (uint8_t*)malloc(pset->dname_len); - if(!pk->rk.dname) - return 0; - /** copy & decompress dname */ - dname_pkt_copy(pkt, pk->rk.dname, pset->dname); - /** copy over type and class */ - pk->rk.type = htons(pset->type); - pk->rk.rrset_class = pset->rrset_class; - /** read data part. */ - if(!parse_create_rrset(pkt, pset, &data, region)) { - if(!region) { - free(pk->rk.dname); - pk->rk.dname = NULL; - } - return 0; - } - pk->entry.data = (void*)data; - pk->entry.key = (void*)pk; - pk->entry.hash = pset->hash; - data->trust = get_rrset_trust(msg, pset); - return 1; -} - -/** - * Copy and decompress rrs - * @param pkt: the packet for compression pointer resolution. - * @param msg: the parsed message - * @param rep: reply info to put rrs into. - * @param region: if not NULL, used for allocation. - * @return 0 on failure. - */ -static int -parse_copy_decompress(sldns_buffer* pkt, struct msg_parse* msg, - struct reply_info* rep, struct regional* region) -{ - size_t i; - struct rrset_parse *pset = msg->rrset_first; - struct packed_rrset_data* data; - log_assert(rep); - rep->ttl = MAX_TTL; - rep->security = sec_status_unchecked; - if(rep->rrset_count == 0) - rep->ttl = NORR_TTL; - - for(i=0; irrset_count; i++) { - if(!parse_copy_decompress_rrset(pkt, msg, pset, region, - rep->rrsets[i])) - return 0; - data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; - if(data->ttl < rep->ttl) - rep->ttl = data->ttl; - - pset = pset->rrset_all_next; - } - rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl); - rep->serve_expired_ttl = rep->ttl + SERVE_EXPIRED_TTL; - return 1; -} - -int -parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg, - struct alloc_cache* alloc, struct query_info* qinf, - struct reply_info** rep, struct regional* region) -{ - log_assert(pkt && msg); - if(!parse_create_qinfo(pkt, msg, qinf, region)) - return 0; - if(!parse_create_repinfo(msg, rep, region)) - return 0; - if(!reply_info_alloc_rrset_keys(*rep, alloc, region)) { - if(!region) reply_info_parsedelete(*rep, alloc); - return 0; - } - if(!parse_copy_decompress(pkt, msg, *rep, region)) { - if(!region) reply_info_parsedelete(*rep, alloc); - return 0; - } - return 1; -} - -int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc, - struct query_info* qinf, struct reply_info** rep, - struct regional* region, struct edns_data* edns) -{ - /* use scratch pad region-allocator during parsing. */ - struct msg_parse* msg; - int ret; - - qinf->qname = NULL; - qinf->local_alias = NULL; - *rep = NULL; - if(!(msg = regional_alloc(region, sizeof(*msg)))) { - return LDNS_RCODE_SERVFAIL; - } - memset(msg, 0, sizeof(*msg)); - - sldns_buffer_set_position(pkt, 0); - if((ret = parse_packet(pkt, msg, region)) != 0) { - return ret; - } - if((ret = parse_extract_edns_from_response_msg(msg, edns, region)) != 0) - return ret; - - /* parse OK, allocate return structures */ - /* this also performs dname decompression */ - if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { - query_info_clear(qinf); - *rep = NULL; - return LDNS_RCODE_SERVFAIL; - } - return 0; -} - -/** helper compare function to sort in lock order */ -static int -reply_info_sortref_cmp(const void* a, const void* b) -{ - struct rrset_ref* x = (struct rrset_ref*)a; - struct rrset_ref* y = (struct rrset_ref*)b; - if(x->key < y->key) return -1; - if(x->key > y->key) return 1; - return 0; -} - -void -reply_info_sortref(struct reply_info* rep) -{ - qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref), - reply_info_sortref_cmp); -} - -void -reply_info_set_ttls(struct reply_info* rep, time_t timenow) -{ - size_t i, j; - rep->ttl += timenow; - rep->prefetch_ttl += timenow; - rep->serve_expired_ttl += timenow; - for(i=0; irrset_count; i++) { - struct packed_rrset_data* data = (struct packed_rrset_data*) - rep->ref[i].key->entry.data; - if(i>0 && rep->ref[i].key == rep->ref[i-1].key) - continue; - data->ttl += timenow; - for(j=0; jcount + data->rrsig_count; j++) { - data->rr_ttl[j] += timenow; - } - data->ttl_add = timenow; - } -} - -void -reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc) -{ - size_t i; - if(!rep) - return; - /* no need to lock, since not shared in hashtables. */ - for(i=0; irrset_count; i++) { - ub_packed_rrset_parsedelete(rep->rrsets[i], alloc); - } - if(rep->reason_bogus_str) { - free(rep->reason_bogus_str); - rep->reason_bogus_str = NULL; - } - free(rep); -} - -int -query_info_parse(struct query_info* m, sldns_buffer* query) -{ - uint8_t* q = sldns_buffer_begin(query); - /* minimum size: header + \0 + qtype + qclass */ - if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5) - return 0; - if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && LDNS_OPCODE_WIRE(q) != - LDNS_PACKET_NOTIFY) || LDNS_QDCOUNT(q) != 1 || - sldns_buffer_position(query) != 0) - return 0; - sldns_buffer_skip(query, LDNS_HEADER_SIZE); - m->qname = sldns_buffer_current(query); - if((m->qname_len = query_dname_len(query)) == 0) - return 0; /* parse error */ - if(sldns_buffer_remaining(query) < 4) - return 0; /* need qtype, qclass */ - m->qtype = sldns_buffer_read_u16(query); - m->qclass = sldns_buffer_read_u16(query); - m->local_alias = NULL; - return 1; -} - -/** tiny subroutine for msgreply_compare */ -#define COMPARE_IT(x, y) \ - if( (x) < (y) ) return -1; \ - else if( (x) > (y) ) return +1; \ - log_assert( (x) == (y) ); - -int -query_info_compare(void* m1, void* m2) -{ - struct query_info* msg1 = (struct query_info*)m1; - struct query_info* msg2 = (struct query_info*)m2; - int mc; - /* from most different to least different for speed */ - COMPARE_IT(msg1->qtype, msg2->qtype); - if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0) - return mc; - log_assert(msg1->qname_len == msg2->qname_len); - COMPARE_IT(msg1->qclass, msg2->qclass); - return 0; -#undef COMPARE_IT -} - -void -query_info_clear(struct query_info* m) -{ - free(m->qname); - m->qname = NULL; -} - -size_t -msgreply_sizefunc(void* k, void* d) -{ - struct msgreply_entry* q = (struct msgreply_entry*)k; - struct reply_info* r = (struct reply_info*)d; - size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info) - + q->key.qname_len + lock_get_mem(&q->entry.lock) - - sizeof(struct rrset_ref); - s += r->rrset_count * sizeof(struct rrset_ref); - s += r->rrset_count * sizeof(struct ub_packed_rrset_key*); - return s; -} - -void -query_entry_delete(void *k, void* ATTR_UNUSED(arg)) -{ - struct msgreply_entry* q = (struct msgreply_entry*)k; - lock_rw_destroy(&q->entry.lock); - query_info_clear(&q->key); - free(q); -} - -void -reply_info_delete(void* d, void* ATTR_UNUSED(arg)) -{ - struct reply_info* r = (struct reply_info*)d; - if(r->reason_bogus_str) { - free(r->reason_bogus_str); - r->reason_bogus_str = NULL; - } - free(r); -} - -hashvalue_type -query_info_hash(struct query_info *q, uint16_t flags) -{ - hashvalue_type h = 0xab; - h = hashlittle(&q->qtype, sizeof(q->qtype), h); - if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD)) - h++; - h = hashlittle(&q->qclass, sizeof(q->qclass), h); - h = dname_query_hash(q->qname, h); - return h; -} - -struct msgreply_entry* -query_info_entrysetup(struct query_info* q, struct reply_info* r, - hashvalue_type h) -{ - struct msgreply_entry* e = (struct msgreply_entry*)malloc( - sizeof(struct msgreply_entry)); - if(!e) return NULL; - memcpy(&e->key, q, sizeof(*q)); - e->entry.hash = h; - e->entry.key = e; - e->entry.data = r; - lock_rw_init(&e->entry.lock); - lock_protect(&e->entry.lock, &e->key.qname, sizeof(e->key.qname)); - lock_protect(&e->entry.lock, &e->key.qname_len, sizeof(e->key.qname_len)); - lock_protect(&e->entry.lock, &e->key.qtype, sizeof(e->key.qtype)); - lock_protect(&e->entry.lock, &e->key.qclass, sizeof(e->key.qclass)); - lock_protect(&e->entry.lock, &e->key.local_alias, sizeof(e->key.local_alias)); - lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash)); - lock_protect(&e->entry.lock, &e->entry.key, sizeof(e->entry.key)); - lock_protect(&e->entry.lock, &e->entry.data, sizeof(e->entry.data)); - lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len); - q->qname = NULL; - return e; -} - -/** copy rrsets from replyinfo to dest replyinfo */ -static int -repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from, - struct regional* region) -{ - size_t i, s; - struct packed_rrset_data* fd, *dd; - struct ub_packed_rrset_key* fk, *dk; - for(i=0; irrset_count; i++) { - fk = from->rrsets[i]; - dk = dest->rrsets[i]; - fd = (struct packed_rrset_data*)fk->entry.data; - dk->entry.hash = fk->entry.hash; - dk->rk = fk->rk; - if(region) { - dk->id = fk->id; - dk->rk.dname = (uint8_t*)regional_alloc_init(region, - fk->rk.dname, fk->rk.dname_len); - } else - dk->rk.dname = (uint8_t*)memdup(fk->rk.dname, - fk->rk.dname_len); - if(!dk->rk.dname) - return 0; - s = packed_rrset_sizeof(fd); - if(region) - dd = (struct packed_rrset_data*)regional_alloc_init( - region, fd, s); - else dd = (struct packed_rrset_data*)memdup(fd, s); - if(!dd) - return 0; - packed_rrset_ptr_fixup(dd); - dk->entry.data = (void*)dd; - } - return 1; -} - -struct reply_info* -reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, - struct regional* region) -{ - struct reply_info* cp; - cp = construct_reply_info_base(region, rep->flags, rep->qdcount, - rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl, - rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets, - rep->rrset_count, rep->security, rep->reason_bogus); - if(!cp) - return NULL; - - if(rep->reason_bogus_str && *rep->reason_bogus_str != 0) { - if(region) { - cp->reason_bogus_str = (char*)regional_alloc(region, - sizeof(char) - * (strlen(rep->reason_bogus_str)+1)); - } else { - cp->reason_bogus_str = malloc(sizeof(char) - * (strlen(rep->reason_bogus_str)+1)); - } - if(!cp->reason_bogus_str) { - if(!region) - reply_info_parsedelete(cp, alloc); - return NULL; - } - memcpy(cp->reason_bogus_str, rep->reason_bogus_str, - strlen(rep->reason_bogus_str)+1); - } - - /* allocate ub_key structures special or not */ - if(!reply_info_alloc_rrset_keys(cp, alloc, region)) { - if(!region) - reply_info_parsedelete(cp, alloc); - return NULL; - } - if(!repinfo_copy_rrsets(cp, rep, region)) { - if(!region) - reply_info_parsedelete(cp, alloc); - return NULL; - } - return cp; -} - -uint8_t* -reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep) -{ - uint8_t* sname = qinfo->qname; - size_t snamelen = qinfo->qname_len; - size_t i; - for(i=0; ian_numrrsets; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - /* follow CNAME chain (if any) */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - ntohs(s->rk.rrset_class) == qinfo->qclass && - snamelen == s->rk.dname_len && - query_dname_compare(sname, s->rk.dname) == 0) { - get_cname_target(s, &sname, &snamelen); - } - } - if(sname != qinfo->qname) - return sname; - return NULL; -} - -struct ub_packed_rrset_key* -reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep) -{ - uint8_t* sname = qinfo->qname; - size_t snamelen = qinfo->qname_len; - size_t i; - for(i=0; ian_numrrsets; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - /* first match type, for query of qtype cname */ - if(ntohs(s->rk.type) == qinfo->qtype && - ntohs(s->rk.rrset_class) == qinfo->qclass && - snamelen == s->rk.dname_len && - query_dname_compare(sname, s->rk.dname) == 0) { - return s; - } - /* follow CNAME chain (if any) */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && - ntohs(s->rk.rrset_class) == qinfo->qclass && - snamelen == s->rk.dname_len && - query_dname_compare(sname, s->rk.dname) == 0) { - get_cname_target(s, &sname, &snamelen); - } - } - return NULL; -} - -struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) -{ - size_t i; - for(i=0; ian_numrrsets; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - if(ntohs(s->rk.type) == type && - ntohs(s->rk.rrset_class) == dclass && - namelen == s->rk.dname_len && - query_dname_compare(name, s->rk.dname) == 0) { - return s; - } - } - return NULL; -} - -struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) -{ - size_t i; - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - if(ntohs(s->rk.type) == type && - ntohs(s->rk.rrset_class) == dclass && - namelen == s->rk.dname_len && - query_dname_compare(name, s->rk.dname) == 0) { - return s; - } - } - return NULL; -} - -struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) -{ - size_t i; - for(i=0; irrset_count; i++) { - struct ub_packed_rrset_key* s = rep->rrsets[i]; - if(ntohs(s->rk.type) == type && - ntohs(s->rk.rrset_class) == dclass && - namelen == s->rk.dname_len && - query_dname_compare(name, s->rk.dname) == 0) { - return s; - } - } - return NULL; -} - -void -log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) -{ - /* not particularly fast but flexible, make wireformat and print */ - sldns_buffer* buf = sldns_buffer_new(65535); - struct regional* region = regional_create(); - if(!(buf && region)) { - log_err("%s: log_dns_msg: out of memory", str); - sldns_buffer_free(buf); - regional_destroy(region); - return; - } - if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, - region, 65535, 1, 0)) { - log_err("%s: log_dns_msg: out of memory", str); - } else { - char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf), - sldns_buffer_limit(buf)); - if(!s) { - log_info("%s: log_dns_msg: ldns tostr failed", str); - } else { - log_info("%s %s", str, s); - } - free(s); - } - sldns_buffer_free(buf); - regional_destroy(region); -} - -void -log_reply_info(enum verbosity_value v, struct query_info *qinf, - struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur, - int cached, struct sldns_buffer *rmsg) -{ - char qname_buf[LDNS_MAX_DOMAINLEN+1]; - char clientip_buf[128]; - char rcode_buf[16]; - char type_buf[16]; - char class_buf[16]; - size_t pktlen; - uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2)); - - if(verbosity < v) - return; - - sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf)); - addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf)); - if(rcode == LDNS_RCODE_FORMERR) - { - if(LOG_TAG_QUERYREPLY) - log_reply("%s - - - %s - - - ", clientip_buf, rcode_buf); - else log_info("%s - - - %s - - - ", clientip_buf, rcode_buf); - } else { - if(qinf->qname) - dname_str(qinf->qname, qname_buf); - else snprintf(qname_buf, sizeof(qname_buf), "null"); - pktlen = sldns_buffer_limit(rmsg); - sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf)); - sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf)); - if(LOG_TAG_QUERYREPLY) - log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d", - clientip_buf, qname_buf, type_buf, class_buf, - rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen); - else log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d", - clientip_buf, qname_buf, type_buf, class_buf, - rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen); - } -} - -void -log_query_info(enum verbosity_value v, const char* str, - struct query_info* qinf) -{ - log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass); -} - -int -reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep) -{ - /* check only answer section rrs for matching cname chain. - * the cache may return changed rdata, but owner names are untouched.*/ - size_t i; - uint8_t* sname = qinfo->qname; - size_t snamelen = qinfo->qname_len; - for(i=0; ian_numrrsets; i++) { - uint16_t t = ntohs(rep->rrsets[i]->rk.type); - if(t == LDNS_RR_TYPE_DNAME) - continue; /* skip dnames; note TTL 0 not cached */ - /* verify that owner matches current sname */ - if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){ - /* cname chain broken */ - return 0; - } - /* if this is a cname; move on */ - if(t == LDNS_RR_TYPE_CNAME) { - get_cname_target(rep->rrsets[i], &sname, &snamelen); - } - } - return 1; -} - -int -reply_all_rrsets_secure(struct reply_info* rep) -{ - size_t i; - for(i=0; irrset_count; i++) { - if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) - ->security != sec_status_secure ) - return 0; - } - return 1; -} - -struct reply_info* -parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region, - struct query_info* qi) -{ - struct reply_info* rep; - struct msg_parse* msg; - if(!(msg = regional_alloc(region, sizeof(*msg)))) { - return NULL; - } - memset(msg, 0, sizeof(*msg)); - sldns_buffer_set_position(pkt, 0); - if(parse_packet(pkt, msg, region) != 0){ - return 0; - } - if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { - return 0; - } - return rep; -} - -int edns_opt_list_append_ede(struct edns_option** list, struct regional* region, - sldns_ede_code code, const char *txt) -{ - struct edns_option** prevp; - struct edns_option* opt; - size_t txt_len = txt ? strlen(txt) : 0; - - /* allocate new element */ - opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); - if(!opt) - return 0; - opt->next = NULL; - opt->opt_code = LDNS_EDNS_EDE; - opt->opt_len = txt_len + sizeof(uint16_t); - opt->opt_data = regional_alloc(region, txt_len + sizeof(uint16_t)); - if(!opt->opt_data) - return 0; - sldns_write_uint16(opt->opt_data, (uint16_t)code); - if (txt_len) - memmove(opt->opt_data + 2, txt, txt_len); - - /* append at end of list */ - prevp = list; - while(*prevp != NULL) - prevp = &((*prevp)->next); - verbose(VERB_ALGO, "attached EDE code: %d with message: %s", code, (txt?txt:"\"\"")); - *prevp = opt; - return 1; -} - -int edns_opt_list_append_keepalive(struct edns_option** list, int msec, - struct regional* region) -{ - uint8_t data[2]; /* For keepalive value */ - data[0] = (uint8_t)((msec >> 8) & 0xff); - data[1] = (uint8_t)(msec & 0xff); - return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data), - data, region); -} - -int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, - uint8_t* data, struct regional* region) -{ - struct edns_option** prevp; - struct edns_option* opt; - - /* allocate new element */ - opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); - if(!opt) - return 0; - opt->next = NULL; - opt->opt_code = code; - opt->opt_len = len; - opt->opt_data = NULL; - if(len > 0) { - opt->opt_data = regional_alloc_init(region, data, len); - if(!opt->opt_data) - return 0; - } - - /* append at end of list */ - prevp = list; - while(*prevp != NULL) { - prevp = &((*prevp)->next); - } - *prevp = opt; - return 1; -} - -int edns_opt_list_remove(struct edns_option** list, uint16_t code) -{ - /* The list should already be allocated in a region. Freeing the - * allocated space in a region is not possible. We just unlink the - * required elements and they will be freed together with the region. */ - - struct edns_option* prev; - struct edns_option* curr; - if(!list || !(*list)) return 0; - - /* Unlink and repoint if the element(s) are first in list */ - while(list && *list && (*list)->opt_code == code) { - *list = (*list)->next; - } - - if(!list || !(*list)) return 1; - /* Unlink elements and reattach the list */ - prev = *list; - curr = (*list)->next; - while(curr != NULL) { - if(curr->opt_code == code) { - prev->next = curr->next; - curr = curr->next; - } else { - prev = curr; - curr = curr->next; - } - } - return 1; -} - -static int inplace_cb_reply_call_generic( - struct inplace_cb* callback_list, enum inplace_cb_list_type type, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time) -{ - struct inplace_cb* cb; - struct edns_option* opt_list_out = NULL; -#if defined(EXPORT_ALL_SYMBOLS) - (void)type; /* param not used when fptr_ok disabled */ -#endif - if(qstate) - opt_list_out = qstate->edns_opts_front_out; - for(cb=callback_list; cb; cb=cb->next) { - fptr_ok(fptr_whitelist_inplace_cb_reply_generic( - (inplace_cb_reply_func_type*)cb->cb, type)); - (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep, - rcode, edns, &opt_list_out, repinfo, region, start_time, cb->id, cb->cb_arg); - } - edns->opt_list_inplace_cb_out = opt_list_out; - return 1; -} - -int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time) -{ - return inplace_cb_reply_call_generic( - env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo, - qstate, rep, rcode, edns, repinfo, region, start_time); -} - -int inplace_cb_reply_cache_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time) -{ - return inplace_cb_reply_call_generic( - env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache, - qinfo, qstate, rep, rcode, edns, repinfo, region, start_time); -} - -int inplace_cb_reply_local_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time) -{ - return inplace_cb_reply_call_generic( - env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local, - qinfo, qstate, rep, rcode, edns, repinfo, region, start_time); -} - -int inplace_cb_reply_servfail_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time) -{ - /* We are going to servfail. Remove any potential edns options. */ - if(qstate) - qstate->edns_opts_front_out = NULL; - return inplace_cb_reply_call_generic( - env->inplace_cb_lists[inplace_cb_reply_servfail], - inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, repinfo, - region, start_time); -} - -int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo, - uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* qstate, - struct regional* region) -{ - struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query]; - for(; cb; cb=cb->next) { - fptr_ok(fptr_whitelist_inplace_cb_query( - (inplace_cb_query_func_type*)cb->cb)); - (void)(*(inplace_cb_query_func_type*)cb->cb)(qinfo, flags, - qstate, addr, addrlen, zone, zonelen, region, - cb->id, cb->cb_arg); - } - return 1; -} - -int inplace_cb_edns_back_parsed_call(struct module_env* env, - struct module_qstate* qstate) -{ - struct inplace_cb* cb = - env->inplace_cb_lists[inplace_cb_edns_back_parsed]; - for(; cb; cb=cb->next) { - fptr_ok(fptr_whitelist_inplace_cb_edns_back_parsed( - (inplace_cb_edns_back_parsed_func_type*)cb->cb)); - (void)(*(inplace_cb_edns_back_parsed_func_type*)cb->cb)(qstate, - cb->id, cb->cb_arg); - } - return 1; -} - -int inplace_cb_query_response_call(struct module_env* env, - struct module_qstate* qstate, struct dns_msg* response) { - struct inplace_cb* cb = - env->inplace_cb_lists[inplace_cb_query_response]; - for(; cb; cb=cb->next) { - fptr_ok(fptr_whitelist_inplace_cb_query_response( - (inplace_cb_query_response_func_type*)cb->cb)); - (void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate, - response, cb->id, cb->cb_arg); - } - return 1; -} - -struct edns_option* edns_opt_copy_region(struct edns_option* list, - struct regional* region) -{ - struct edns_option* result = NULL, *cur = NULL, *s; - while(list) { - /* copy edns option structure */ - s = regional_alloc_init(region, list, sizeof(*list)); - if(!s) return NULL; - s->next = NULL; - - /* copy option data */ - if(s->opt_data) { - s->opt_data = regional_alloc_init(region, s->opt_data, - s->opt_len); - if(!s->opt_data) - return NULL; - } - - /* link into list */ - if(cur) - cur->next = s; - else result = s; - cur = s; - - /* examine next element */ - list = list->next; - } - return result; -} - -struct edns_option* edns_opt_copy_filter_region(struct edns_option* list, - uint16_t* filter_list, size_t filter_list_len, struct regional* region) -{ - struct edns_option* result = NULL, *cur = NULL, *s; - size_t i; - while(list) { - for(i=0; iopt_code) goto found; - if(i == filter_list_len) goto next; -found: - /* copy edns option structure */ - s = regional_alloc_init(region, list, sizeof(*list)); - if(!s) return NULL; - s->next = NULL; - - /* copy option data */ - if(s->opt_data) { - s->opt_data = regional_alloc_init(region, s->opt_data, - s->opt_len); - if(!s->opt_data) - return NULL; - } - - /* link into list */ - if(cur) - cur->next = s; - else result = s; - cur = s; - -next: - /* examine next element */ - list = list->next; - } - return result; -} - -int edns_opt_compare(struct edns_option* p, struct edns_option* q) -{ - if(!p && !q) return 0; - if(!p) return -1; - if(!q) return 1; - log_assert(p && q); - if(p->opt_code != q->opt_code) - return (int)q->opt_code - (int)p->opt_code; - if(p->opt_len != q->opt_len) - return (int)q->opt_len - (int)p->opt_len; - if(p->opt_len != 0) - return memcmp(p->opt_data, q->opt_data, p->opt_len); - return 0; -} - -int edns_opt_list_compare(struct edns_option* p, struct edns_option* q) -{ - int r; - while(p && q) { - r = edns_opt_compare(p, q); - if(r != 0) - return r; - p = p->next; - q = q->next; - } - if(p || q) { - /* uneven length lists */ - if(p) return 1; - if(q) return -1; - } - return 0; -} - -void edns_opt_list_free(struct edns_option* list) -{ - struct edns_option* n; - while(list) { - free(list->opt_data); - n = list->next; - free(list); - list = n; - } -} - -struct edns_option* edns_opt_copy_alloc(struct edns_option* list) -{ - struct edns_option* result = NULL, *cur = NULL, *s; - while(list) { - /* copy edns option structure */ - s = memdup(list, sizeof(*list)); - if(!s) { - edns_opt_list_free(result); - return NULL; - } - s->next = NULL; - - /* copy option data */ - if(s->opt_data) { - s->opt_data = memdup(s->opt_data, s->opt_len); - if(!s->opt_data) { - free(s); - edns_opt_list_free(result); - return NULL; - } - } - - /* link into list */ - if(cur) - cur->next = s; - else result = s; - cur = s; - - /* examine next element */ - list = list->next; - } - return result; -} - -struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code) -{ - struct edns_option* p; - for(p=list; p; p=p->next) { - if(p->opt_code == code) - return p; - } - return NULL; -} diff --git a/crates/libunbound-sys/unbound/util/data/msgreply.h b/crates/libunbound-sys/unbound/util/data/msgreply.h deleted file mode 100644 index a9af3d7e..00000000 --- a/crates/libunbound-sys/unbound/util/data/msgreply.h +++ /dev/null @@ -1,767 +0,0 @@ -/* - * util/data/msgreply.h - store message and reply data. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a data structure to store a message and its reply. - */ - -#ifndef UTIL_DATA_MSGREPLY_H -#define UTIL_DATA_MSGREPLY_H -#include "util/storage/lruhash.h" -#include "util/data/packed_rrset.h" -#include "sldns/rrdef.h" -struct sldns_buffer; -struct comm_reply; -struct alloc_cache; -struct iovec; -struct regional; -struct edns_data; -struct edns_option; -struct inplace_cb; -struct module_qstate; -struct module_env; -struct msg_parse; -struct rrset_parse; -struct local_rrset; -struct dns_msg; - -/** calculate the prefetch TTL as 90% of original. Calculation - * without numerical overflow (uin32_t) */ -#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) - -/** - * Structure to store query information that makes answers to queries - * different. - */ -struct query_info { - /** - * Salient data on the query: qname, in wireformat. - * can be allocated or a pointer to outside buffer. - * User has to keep track on the status of this. - */ - uint8_t* qname; - /** length of qname (including last 0 octet) */ - size_t qname_len; - /** qtype, host byte order */ - uint16_t qtype; - /** qclass, host byte order */ - uint16_t qclass; - /** - * Alias local answer(s) for the qname. If 'qname' is an alias defined - * in a local zone, this field will be set to the corresponding local - * RRset when the alias is determined. - * In the initial implementation this can only be a single CNAME RR - * (or NULL), but it could possibly be extended to be a DNAME or a - * chain of aliases. - * Users of this structure are responsible to initialize this field - * to be NULL; otherwise other part of query handling code may be - * confused. - * Users also have to be careful about the lifetime of data. On return - * from local zone lookup, it may point to data derived from - * configuration that may be dynamically invalidated or data allocated - * in an ephemeral regional allocator. A deep copy of the data may - * have to be generated if it has to be kept during iterative - * resolution. */ - struct local_rrset* local_alias; -}; - -/** - * Information to reference an rrset - */ -struct rrset_ref { - /** the key with lock, and ptr to packed data. */ - struct ub_packed_rrset_key* key; - /** id needed */ - rrset_id_type id; -}; - -/** - * Structure to store DNS query and the reply packet. - * To use it, copy over the flags from reply and modify using flags from - * the query (RD,CD if not AA). prepend ID. - * - * Memory layout is: - * o struct - * o rrset_ref array - * o packed_rrset_key* array. - * - * Memory layout is sometimes not packed, when the message is synthesized, - * for easy of the generation. It is allocated packed when it is copied - * from the region allocation to the malloc allocation. - */ -struct reply_info { - /** the flags for the answer, host byte order. */ - uint16_t flags; - - /** - * This flag informs unbound the answer is authoritative and - * the AA flag should be preserved. - */ - uint8_t authoritative; - - /** - * Number of RRs in the query section. - * If qdcount is not 0, then it is 1, and the data that appears - * in the reply is the same as the query_info. - * Host byte order. - */ - uint8_t qdcount; - - /** 32 bit padding to pad struct member alignment to 64 bits. */ - uint32_t padding; - - /** - * TTL of the entire reply (for negative caching). - * only for use when there are 0 RRsets in this message. - * if there are RRsets, check those instead. - */ - time_t ttl; - - /** - * TTL for prefetch. After it has expired, a prefetch is suitable. - * Smaller than the TTL, otherwise the prefetch would not happen. - */ - time_t prefetch_ttl; - - /** - * Reply TTL extended with serve expired TTL, to limit time to serve - * expired message. - */ - time_t serve_expired_ttl; - - /** - * The security status from DNSSEC validation of this message. - */ - enum sec_status security; - - /** - * EDE (rfc8914) code with reason for DNSSEC bogus status. - * Used for caching the EDE. - */ - sldns_ede_code reason_bogus; - - /** - * EDE (rfc8914) NULL-terminated string with human-readable reason - * for DNSSEC bogus status. - * Used for caching the EDE. - */ - char* reason_bogus_str; - - /** - * Number of RRsets in each section. - * The answer section. Add up the RRs in every RRset to calculate - * the number of RRs, and the count for the dns packet. - * The number of RRs in RRsets can change due to RRset updates. - */ - size_t an_numrrsets; - - /** Count of authority section RRsets */ - size_t ns_numrrsets; - /** Count of additional section RRsets */ - size_t ar_numrrsets; - - /** number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets */ - size_t rrset_count; - - /** - * List of pointers (only) to the rrsets in the order in which - * they appear in the reply message. - * Number of elements is ancount+nscount+arcount RRsets. - * This is a pointer to that array. - * Use the accessor function for access. - */ - struct ub_packed_rrset_key** rrsets; - - /** - * Packed array of ids (see counts) and pointers to packed_rrset_key. - * The number equals ancount+nscount+arcount RRsets. - * These are sorted in ascending pointer, the locking order. So - * this list can be locked (and id, ttl checked), to see if - * all the data is available and recent enough. - * - * This is defined as an array of size 1, so that the compiler - * associates the identifier with this position in the structure. - * Array bound overflow on this array then gives access to the further - * elements of the array, which are allocated after the main structure. - * - * It could be more pure to define as array of size 0, ref[0]. - * But ref[1] may be less confusing for compilers. - * Use the accessor function for access. - */ - struct rrset_ref ref[1]; -}; - -/** - * Structure to keep hash table entry for message replies. - */ -struct msgreply_entry { - /** the hash table key */ - struct query_info key; - /** the hash table entry, data is struct reply_info* */ - struct lruhash_entry entry; -}; - -/** - * Constructor for replyinfo. - * @param region: where to allocate the results, pass NULL to use malloc. - * @param flags: flags for the replyinfo. - * @param qd: qd count - * @param ttl: TTL of replyinfo - * @param prettl: prefetch ttl - * @param expttl: serve expired ttl - * @param an: an count - * @param ns: ns count - * @param ar: ar count - * @param total: total rrset count (presumably an+ns+ar). - * @param sec: security status of the reply info. - * @param reason_bogus: the Extended DNS Error for DNSSEC bogus status - * @return the reply_info base struct with the array for putting the rrsets - * in. The array has been zeroed. Returns NULL on malloc failure. - */ -struct reply_info* -construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, - time_t ttl, time_t prettl, time_t expttl, size_t an, size_t ns, - size_t ar, size_t total, enum sec_status sec, - sldns_ede_code reason_bogus); - -/** - * Parse wire query into a queryinfo structure, return 0 on parse error. - * initialises the (prealloced) queryinfo structure as well. - * This query structure contains a pointer back info the buffer! - * This pointer avoids memory allocation. allocqname does memory allocation. - * @param m: the prealloced queryinfo structure to put query into. - * must be unused, or _clear()ed. - * @param query: the wireformat packet query. starts with ID. - * @return: 0 on format error. - */ -int query_info_parse(struct query_info* m, struct sldns_buffer* query); - -/** - * Parse query reply. - * Fills in preallocated query_info structure (with ptr into buffer). - * Allocates reply_info and packed_rrsets. These are not yet added to any - * caches or anything, this is only parsing. Returns formerror on qdcount > 1. - * @param pkt: the packet buffer. Must be positioned after the query section. - * @param alloc: creates packed rrset key structures. - * @param rep: allocated reply_info is returned (only on no error). - * @param qinf: query_info is returned (only on no error). - * @param region: where to store temporary data (for parsing). - * @param edns: where to store edns information, does not need to be inited. - * @return: zero is OK, or DNS error code in case of error - * o FORMERR for parse errors. - * o SERVFAIL for memory allocation errors. - */ -int reply_info_parse(struct sldns_buffer* pkt, struct alloc_cache* alloc, - struct query_info* qinf, struct reply_info** rep, - struct regional* region, struct edns_data* edns); - -/** - * Allocate and decompress parsed message and rrsets. - * @param pkt: for name decompression. - * @param msg: parsed message in scratch region. - * @param alloc: alloc cache for special rrset key structures. - * Not used if region!=NULL, it can be NULL in that case. - * @param qinf: where to store query info. - * qinf itself is allocated by the caller. - * @param rep: reply info is allocated and returned. - * @param region: if this parameter is NULL then malloc and the alloc is used. - * otherwise, everything is allocated in this region. - * In a region, no special rrset key structures are needed (not shared), - * and no rrset_ref array in the reply is built up. - * @return 0 if allocation failed. - */ -int parse_create_msg(struct sldns_buffer* pkt, struct msg_parse* msg, - struct alloc_cache* alloc, struct query_info* qinf, - struct reply_info** rep, struct regional* region); - -/** get msg reply struct (in temp region) */ -struct reply_info* parse_reply_in_temp_region(struct sldns_buffer* pkt, - struct regional* region, struct query_info* qi); - -/** - * Sorts the ref array. - * @param rep: reply info. rrsets must be filled in. - */ -void reply_info_sortref(struct reply_info* rep); - -/** - * Set TTLs inside the replyinfo to absolute values. - * @param rep: reply info. rrsets must be filled in. - * Also refs must be filled in. - * @param timenow: the current time. - */ -void reply_info_set_ttls(struct reply_info* rep, time_t timenow); - -/** - * Delete reply_info and packed_rrsets (while they are not yet added to the - * hashtables.). Returns rrsets to the alloc cache. - * @param rep: reply_info to delete. - * @param alloc: where to return rrset structures to. - */ -void reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc); - -/** - * Compare two queryinfo structures, on query and type, class. - * It is _not_ sorted in canonical ordering. - * @param m1: struct query_info* , void* here to ease use as function pointer. - * @param m2: struct query_info* , void* here to ease use as function pointer. - * @return: 0 = same, -1 m1 is smaller, +1 m1 is larger. - */ -int query_info_compare(void* m1, void* m2); - -/** clear out query info structure */ -void query_info_clear(struct query_info* m); - -/** calculate size of struct query_info + reply_info */ -size_t msgreply_sizefunc(void* k, void* d); - -/** delete msgreply_entry key structure */ -void query_entry_delete(void *q, void* arg); - -/** delete reply_info data structure */ -void reply_info_delete(void* d, void* arg); - -/** calculate hash value of query_info, lowercases the qname, - * uses CD flag for AAAA qtype */ -hashvalue_type query_info_hash(struct query_info *q, uint16_t flags); - -/** - * Setup query info entry - * @param q: query info to copy. Emptied as if clear is called. - * @param r: reply to init data. - * @param h: hash value. - * @return: newly allocated message reply cache item. - */ -struct msgreply_entry* query_info_entrysetup(struct query_info* q, - struct reply_info* r, hashvalue_type h); - -/** - * Copy reply_info and all rrsets in it and allocate. - * @param rep: what to copy, probably inside region, no ref[] array in it. - * @param alloc: how to allocate rrset keys. - * Not used if region!=NULL, it can be NULL in that case. - * @param region: if this parameter is NULL then malloc and the alloc is used. - * otherwise, everything is allocated in this region. - * In a region, no special rrset key structures are needed (not shared), - * and no rrset_ref array in the reply is built up. - * @return new reply info or NULL on memory error. - */ -struct reply_info* reply_info_copy(struct reply_info* rep, - struct alloc_cache* alloc, struct regional* region); - -/** - * Allocate (special) rrset keys. - * @param rep: reply info in which the rrset keys to be allocated, rrset[] - * array should have bee allocated with NULL pointers. - * @param alloc: how to allocate rrset keys. - * Not used if region!=NULL, it can be NULL in that case. - * @param region: if this parameter is NULL then the alloc is used. - * otherwise, rrset keys are allocated in this region. - * In a region, no special rrset key structures are needed (not shared). - * and no rrset_ref array in the reply needs to be built up. - * @return 1 on success, 0 on error - */ -int reply_info_alloc_rrset_keys(struct reply_info* rep, - struct alloc_cache* alloc, struct regional* region); - -/* - * Create a new reply_info based on 'rep'. The new info is based on - * the passed 'rep', but ignores any rrsets except for the first 'an_numrrsets' - * RRsets in the answer section. These answer rrsets are copied to the - * new info, up to 'copy_rrsets' rrsets (which must not be larger than - * 'an_numrrsets'). If an_numrrsets > copy_rrsets, the remaining rrsets array - * entries will be kept empty so the caller can fill them later. When rrsets - * are copied, they are shallow copied. The caller must ensure that the - * copied rrsets are valid throughout its lifetime and must provide appropriate - * mutex if it can be shared by multiple threads. - */ -struct reply_info * -make_new_reply_info(const struct reply_info* rep, struct regional* region, - size_t an_numrrsets, size_t copy_rrsets); - -/** - * Copy a parsed rrset into given key, decompressing and allocating rdata. - * @param pkt: packet for decompression - * @param msg: the parser message (for flags for trust). - * @param pset: the parsed rrset to copy. - * @param region: if NULL - malloc, else data is allocated in this region. - * @param pk: a freshly obtained rrsetkey structure. No dname is set yet, - * will be set on return. - * Note that TTL will still be relative on return. - * @return false on alloc failure. - */ -int parse_copy_decompress_rrset(struct sldns_buffer* pkt, struct msg_parse* msg, - struct rrset_parse *pset, struct regional* region, - struct ub_packed_rrset_key* pk); - -/** - * Find final cname target in reply, the one matching qinfo. Follows CNAMEs. - * @param qinfo: what to start with. - * @param rep: looks in answer section of this message. - * @return: pointer dname, or NULL if not found. - */ -uint8_t* reply_find_final_cname_target(struct query_info* qinfo, - struct reply_info* rep); - -/** - * Check if cname chain in cached reply is still valid. - * @param qinfo: query info with query name. - * @param rep: reply to check. - * @return: true if valid, false if invalid. - */ -int reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep); - -/** - * Check security status of all RRs in the message. - * @param rep: reply to check - * @return: true if all RRs are secure. False if not. - * True if there are zero RRs. - */ -int reply_all_rrsets_secure(struct reply_info* rep); - -/** - * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the - * result may have a different owner name. - * @param qinfo: what to look for. - * @param rep: looks in answer section of this message. - * @return: pointer to rrset, or NULL if not found. - */ -struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo, - struct reply_info* rep); - -/** - * Find rrset in reply, inside the answer section. Does not follow CNAMEs. - * @param rep: looks in answer section of this message. - * @param name: what to look for. - * @param namelen: length of name. - * @param type: looks for (host order). - * @param dclass: looks for (host order). - * @return: pointer to rrset, or NULL if not found. - */ -struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); - -/** - * Find rrset in reply, inside the authority section. Does not follow CNAMEs. - * @param rep: looks in authority section of this message. - * @param name: what to look for. - * @param namelen: length of name. - * @param type: looks for (host order). - * @param dclass: looks for (host order). - * @return: pointer to rrset, or NULL if not found. - */ -struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); - -/** - * Find rrset in reply, inside any section. Does not follow CNAMEs. - * @param rep: looks in answer,authority and additional section of this message. - * @param name: what to look for. - * @param namelen: length of name. - * @param type: looks for (host order). - * @param dclass: looks for (host order). - * @return: pointer to rrset, or NULL if not found. - */ -struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, - uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); - -/** - * Debug send the query info and reply info to the log in readable form. - * @param str: descriptive string printed with packet content. - * @param qinfo: query section. - * @param rep: rest of message. - */ -void log_dns_msg(const char* str, struct query_info* qinfo, - struct reply_info* rep); - -/** - * Print string with neat domain name, type, class, - * status code from, and size of a query response. - * - * @param v: at what verbosity level to print this. - * @param qinf: query section. - * @param addr: address of the client. - * @param addrlen: length of the client address. - * @param dur: how long it took to complete the query. - * @param cached: whether or not the reply is coming from - * the cache, or an outside network. - * @param rmsg: sldns buffer packet. - */ -void log_reply_info(enum verbosity_value v, struct query_info *qinf, - struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur, - int cached, struct sldns_buffer *rmsg); - -/** - * Print string with neat domain name, type, class from query info. - * @param v: at what verbosity level to print this. - * @param str: string of message. - * @param qinf: query info structure with name, type and class. - */ -void log_query_info(enum verbosity_value v, const char* str, - struct query_info* qinf); - -/** - * Append edns option to edns option list - * @param list: the edns option list to append the edns option to. - * @param code: the edns option's code. - * @param len: the edns option's length. - * @param data: the edns option's data. - * @param region: region to allocate the new edns option. - * @return false on failure. - */ -int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, - uint8_t* data, struct regional* region); - -/** - * Append edns EDE option to edns options list - * @param LIST: the edns option list to append the edns option to. - * @param REGION: region to allocate the new edns option. - * @param CODE: the EDE code. - * @param TXT: Additional text for the option - */ -#define EDNS_OPT_LIST_APPEND_EDE(LIST, REGION, CODE, TXT) \ - do { \ - struct { \ - uint16_t code; \ - char text[sizeof(TXT) - 1]; \ - } ede = { htons(CODE), TXT }; \ - verbose(VERB_ALGO, "attached EDE code: %d with" \ - " message: %s", CODE, TXT); \ - edns_opt_list_append((LIST), LDNS_EDNS_EDE, \ - sizeof(uint16_t) + sizeof(TXT) - 1, \ - (void *)&ede, (REGION)); \ - } while(0) - -/** - * Append edns EDE option to edns options list - * @param list: the edns option list to append the edns option to. - * @param region: region to allocate the new edns option. - * @param code: the EDE code. - * @param txt: Additional text for the option - * @return false on failure. - */ -int edns_opt_list_append_ede(struct edns_option** list, struct regional* region, - sldns_ede_code code, const char *txt); - -/** - * Append edns keep alive option to edns options list - * @param list: the edns option list to append the edns option to. - * @param msec: the duration in msecs for the keep alive. - * @param region: region to allocate the new edns option. - * @return false on failure. - */ -int edns_opt_list_append_keepalive(struct edns_option** list, int msec, - struct regional* region); - -/** - * Remove any option found on the edns option list that matches the code. - * @param list: the list of edns options. - * @param code: the opt code to remove. - * @return true when at least one edns option was removed, false otherwise. - */ -int edns_opt_list_remove(struct edns_option** list, uint16_t code); - -/** - * Find edns option in edns list - * @param list: list of edns options (eg. edns.opt_list) - * @param code: opt code to find. - * @return NULL or the edns_option element. - */ -struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code); - -/** - * Call the registered functions in the inplace_cb_reply linked list. - * This function is going to get called while answering with a resolved query. - * @param env: module environment. - * @param qinfo: query info. - * @param qstate: module qstate. - * @param rep: Reply info. Could be NULL. - * @param rcode: return code. - * @param edns: edns data of the reply. - * @param repinfo: comm_reply. Reply information for a communication point. - * @param region: region to store data. - * @param start_time: the start time of recursion, when the packet arrived, - * or the current time for cache responses. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time); - -/** - * Call the registered functions in the inplace_cb_reply_cache linked list. - * This function is going to get called while answering from cache. - * @param env: module environment. - * @param qinfo: query info. - * @param qstate: module qstate. NULL when replying from cache. - * @param rep: Reply info. - * @param rcode: return code. - * @param edns: edns data of the reply. Edns input can be found here. - * @param repinfo: comm_reply. Reply information for a communication point. - * @param region: region to store data. - * @param start_time: the start time of recursion, when the packet arrived, - * or the current time for cache responses. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_reply_cache_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time); - -/** - * Call the registered functions in the inplace_cb_reply_local linked list. - * This function is going to get called while answering with local data. - * @param env: module environment. - * @param qinfo: query info. - * @param qstate: module qstate. NULL when replying from cache. - * @param rep: Reply info. - * @param rcode: return code. - * @param edns: edns data of the reply. Edns input can be found here. - * @param repinfo: comm_reply. Reply information for a communication point. - * @param region: region to store data. - * @param start_time: the start time of recursion, when the packet arrived, - * or the current time for cache responses. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_reply_local_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time); - -/** - * Call the registered functions in the inplace_cb_reply linked list. - * This function is going to get called while answering with a servfail. - * @param env: module environment. - * @param qinfo: query info. - * @param qstate: module qstate. Contains the edns option lists. Could be NULL. - * @param rep: Reply info. NULL when servfail. - * @param rcode: return code. LDNS_RCODE_SERVFAIL. - * @param edns: edns data of the reply. Edns input can be found here if qstate - * is NULL. - * @param repinfo: comm_reply. Reply information for a communication point. - * @param region: region to store data. - * @param start_time: the start time of recursion, when the packet arrived, - * or the current time for cache responses. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_reply_servfail_call(struct module_env* env, - struct query_info* qinfo, struct module_qstate* qstate, - struct reply_info* rep, int rcode, struct edns_data* edns, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time); - -/** - * Call the registered functions in the inplace_cb_query linked list. - * This function is going to get called just before sending a query to a - * nameserver. - * @param env: module environment. - * @param qinfo: query info. - * @param flags: flags of the query. - * @param addr: to which server to send the query. - * @param addrlen: length of addr. - * @param zone: name of the zone of the delegation point. wireformat dname. - * This is the delegation point name for which the server is deemed - * authoritative. - * @param zonelen: length of zone. - * @param qstate: module qstate. - * @param region: region to store data. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo, - uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* qstate, - struct regional* region); - -/** - * Call the registered functions in the inplace_cb_edns_back_parsed linked list. - * This function is going to get called after parsing the EDNS data on the - * reply from a nameserver. - * @param env: module environment. - * @param qstate: module qstate. - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_edns_back_parsed_call(struct module_env* env, - struct module_qstate* qstate); - -/** - * Call the registered functions in the inplace_cb_query_response linked list. - * This function is going to get called after receiving a reply from a - * nameserver. - * @param env: module environment. - * @param qstate: module qstate. - * @param response: received response - * @return false on failure (a callback function returned an error). - */ -int inplace_cb_query_response_call(struct module_env* env, - struct module_qstate* qstate, struct dns_msg* response); - -/** - * Copy edns option list allocated to the new region - */ -struct edns_option* edns_opt_copy_region(struct edns_option* list, - struct regional* region); - -/** - * Copy a filtered edns option list allocated to the new region - */ -struct edns_option* edns_opt_copy_filter_region(struct edns_option* list, - uint16_t* filter_list, size_t filter_list_len, struct regional* region); - -/** - * Copy edns option list allocated with malloc - */ -struct edns_option* edns_opt_copy_alloc(struct edns_option* list); - -/** - * Free edns option list allocated with malloc - */ -void edns_opt_list_free(struct edns_option* list); - -/** - * Compare an edns option. (not entire list). Also compares contents. - */ -int edns_opt_compare(struct edns_option* p, struct edns_option* q); - -/** - * Compare edns option lists, also the order and contents of edns-options. - */ -int edns_opt_list_compare(struct edns_option* p, struct edns_option* q); - -#endif /* UTIL_DATA_MSGREPLY_H */ diff --git a/crates/libunbound-sys/unbound/util/data/packed_rrset.c b/crates/libunbound-sys/unbound/util/data/packed_rrset.c deleted file mode 100644 index e1a0833a..00000000 --- a/crates/libunbound-sys/unbound/util/data/packed_rrset.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * util/data/packed_rrset.c - data storage for a set of resource records. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the data storage for RRsets. - */ - -#include "config.h" -#include "util/data/msgparse.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/storage/lookup3.h" -#include "util/log.h" -#include "util/alloc.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "sldns/rrdef.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" - -void -ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, - struct alloc_cache* alloc) -{ - if(!pkey) - return; - free(pkey->entry.data); - pkey->entry.data = NULL; - free(pkey->rk.dname); - pkey->rk.dname = NULL; - pkey->id = 0; - alloc_special_release(alloc, pkey); -} - -size_t -ub_rrset_sizefunc(void* key, void* data) -{ - struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; - struct packed_rrset_data* d = (struct packed_rrset_data*)data; - size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; - s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); - return s; -} - -size_t -packed_rrset_sizeof(struct packed_rrset_data* d) -{ - size_t s; - if(d->rrsig_count > 0) { - s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - - (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; - } else { - log_assert(d->count > 0); - s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + - d->rr_len[d->count-1]; - } - return s; -} - -int -ub_rrset_compare(void* k1, void* k2) -{ - struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; - struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; - int c; - if(key1 == key2) - return 0; - if(key1->rk.type != key2->rk.type) { - if(key1->rk.type < key2->rk.type) - return -1; - return 1; - } - if(key1->rk.dname_len != key2->rk.dname_len) { - if(key1->rk.dname_len < key2->rk.dname_len) - return -1; - return 1; - } - if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) - return c; - if(key1->rk.rrset_class != key2->rk.rrset_class) { - if(key1->rk.rrset_class < key2->rk.rrset_class) - return -1; - return 1; - } - if(key1->rk.flags != key2->rk.flags) { - if(key1->rk.flags < key2->rk.flags) - return -1; - return 1; - } - return 0; -} - -void -ub_rrset_key_delete(void* key, void* userdata) -{ - struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; - struct alloc_cache* a = (struct alloc_cache*)userdata; - k->id = 0; - free(k->rk.dname); - k->rk.dname = NULL; - alloc_special_release(a, k); -} - -void -rrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)data; - free(d); -} - -int -rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) -{ - size_t i; - size_t total; - if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) - return 0; - total = d1->count + d1->rrsig_count; - for(i=0; irr_len[i] != d2->rr_len[i]) - return 0; - if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) - return 0; - } - return 1; -} - -hashvalue_type -rrset_key_hash(struct packed_rrset_key* key) -{ - /* type is hashed in host order */ - uint16_t t = ntohs(key->type); - /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ - /* this routine does not have a compressed name */ - hashvalue_type h = 0xab; - h = dname_query_hash(key->dname, h); - h = hashlittle(&t, sizeof(t), h); - h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); - h = hashlittle(&key->flags, sizeof(uint32_t), h); - return h; -} - -void -packed_rrset_ptr_fixup(struct packed_rrset_data* data) -{ - size_t i; - size_t total = data->count + data->rrsig_count; - uint8_t* nextrdata; - /* fixup pointers in packed rrset data */ - data->rr_len = (size_t*)((uint8_t*)data + - sizeof(struct packed_rrset_data)); - data->rr_data = (uint8_t**)&(data->rr_len[total]); - data->rr_ttl = (time_t*)&(data->rr_data[total]); - nextrdata = (uint8_t*)&(data->rr_ttl[total]); - for(i=0; irr_data[i] = nextrdata; - nextrdata += data->rr_len[i]; - } -} - -void -get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, - size_t* dname_len) -{ - struct packed_rrset_data* d; - size_t len; - if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && - ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) - return; - d = (struct packed_rrset_data*)rrset->entry.data; - if(d->count < 1) - return; - if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ - return; - len = sldns_read_uint16(d->rr_data[0]); - if(len != d->rr_len[0] - sizeof(uint16_t)) - return; - if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) - return; - *dname = d->rr_data[0]+sizeof(uint16_t); - *dname_len = len; -} - -void -packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add) -{ - size_t i; - size_t total = data->count + data->rrsig_count; - data->ttl_add = add; - data->ttl += add; - for(i=0; irr_ttl[i] += add; -} - -const char* -rrset_trust_to_string(enum rrset_trust s) -{ - switch(s) { - case rrset_trust_none: return "rrset_trust_none"; - case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; - case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; - case rrset_trust_add_AA: return "rrset_trust_add_AA"; - case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; - case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; - case rrset_trust_glue: return "rrset_trust_glue"; - case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; - case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; - case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; - case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; - case rrset_trust_validated: return "rrset_trust_validated"; - case rrset_trust_ultimate: return "rrset_trust_ultimate"; - } - return "unknown_rrset_trust_value"; -} - -const char* -sec_status_to_string(enum sec_status s) -{ - switch(s) { - case sec_status_unchecked: return "sec_status_unchecked"; - case sec_status_bogus: return "sec_status_bogus"; - case sec_status_indeterminate: return "sec_status_indeterminate"; - case sec_status_insecure: return "sec_status_insecure"; - case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail"; - case sec_status_secure: return "sec_status_secure"; - } - return "unknown_sec_status_value"; -} - -void log_rrset_key(enum verbosity_value v, const char* str, - struct ub_packed_rrset_key* rrset) -{ - if(verbosity >= v) - log_nametypeclass(v, str, rrset->rk.dname, - ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); -} - -int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, - time_t now, char* dest, size_t dest_len) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> - entry.data; - uint8_t rr[65535]; - size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i]; - time_t adjust = 0; - log_assert(dest_len > 0 && dest); - if(rlen > dest_len) { - dest[0] = 0; - return 0; - } - memmove(rr, rrset->rk.dname, rrset->rk.dname_len); - if(i < d->count) - memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2); - else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG); - memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2); - adjust = SERVE_ORIGINAL_TTL ? d->ttl_add : now; - if (d->rr_ttl[i] < adjust) adjust = d->rr_ttl[i]; /* Prevent negative TTL overflow */ - sldns_write_uint32(rr+rrset->rk.dname_len+4, - (uint32_t)(d->rr_ttl[i]-adjust)); - memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]); - if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) { - log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest); - dest[0] = 0; - return 0; - } - return 1; -} - -void log_packed_rrset(enum verbosity_value v, const char* str, - struct ub_packed_rrset_key* rrset) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> - entry.data; - char buf[65535]; - size_t i; - if(verbosity < v) - return; - for(i=0; icount+d->rrsig_count; i++) { - if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) { - log_info("%s: rr %d wire2str-error", str, (int)i); - } else { - log_info("%s: %s", str, buf); - } - } -} - -time_t -ub_packed_rrset_ttl(struct ub_packed_rrset_key* key) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)key-> - entry.data; - return d->ttl; -} - -struct ub_packed_rrset_key* -packed_rrset_copy_region(struct ub_packed_rrset_key* key, - struct regional* region, time_t now) -{ - struct ub_packed_rrset_key* ck = regional_alloc(region, - sizeof(struct ub_packed_rrset_key)); - struct packed_rrset_data* d; - struct packed_rrset_data* data = (struct packed_rrset_data*) - key->entry.data; - size_t dsize, i; - time_t adjust = 0; - if(!ck) - return NULL; - ck->id = key->id; - memset(&ck->entry, 0, sizeof(ck->entry)); - ck->entry.hash = key->entry.hash; - ck->entry.key = ck; - ck->rk = key->rk; - ck->rk.dname = regional_alloc_init(region, key->rk.dname, - key->rk.dname_len); - if(!ck->rk.dname) - return NULL; - dsize = packed_rrset_sizeof(data); - d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); - if(!d) - return NULL; - ck->entry.data = d; - packed_rrset_ptr_fixup(d); - /* make TTLs relative - once per rrset */ - adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : now; - for(i=0; icount + d->rrsig_count; i++) { - if(d->rr_ttl[i] < adjust) - d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; - else d->rr_ttl[i] -= adjust; - } - if(d->ttl < adjust) - d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; - else d->ttl -= adjust; - d->ttl_add = 0; /* TTLs have been made relative */ - return ck; -} - -struct ub_packed_rrset_key* -packed_rrset_copy_alloc(struct ub_packed_rrset_key* key, - struct alloc_cache* alloc, time_t now) -{ - struct packed_rrset_data* fd, *dd; - struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); - if(!dk) return NULL; - fd = (struct packed_rrset_data*)key->entry.data; - dk->entry.hash = key->entry.hash; - dk->rk = key->rk; - dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); - if(!dk->rk.dname) { - alloc_special_release(alloc, dk); - return NULL; - } - dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); - if(!dd) { - free(dk->rk.dname); - alloc_special_release(alloc, dk); - return NULL; - } - packed_rrset_ptr_fixup(dd); - dk->entry.data = (void*)dd; - packed_rrset_ttl_add(dd, now); - return dk; -} - -int -packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len, - size_t* index) -{ - size_t i; - for(i=0; icount; i++) { - if(d->rr_len[i] != len) - continue; - if(memcmp(d->rr_data[i], rdata, len) == 0) { - *index = i; - return 1; - } - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/util/data/packed_rrset.h b/crates/libunbound-sys/unbound/util/data/packed_rrset.h deleted file mode 100644 index e1feb22b..00000000 --- a/crates/libunbound-sys/unbound/util/data/packed_rrset.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - * util/data/packed_rrset.h - data storage for a set of resource records. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the data storage for RRsets. - */ - -#ifndef UTIL_DATA_PACKED_RRSET_H -#define UTIL_DATA_PACKED_RRSET_H -#include "util/storage/lruhash.h" -struct alloc_cache; -struct regional; - -/** type used to uniquely identify rrsets. Cannot be reused without - * clearing the cache. */ -typedef uint64_t rrset_id_type; - -/** this rrset is NSEC and is at zone apex (at child side of zonecut) */ -#define PACKED_RRSET_NSEC_AT_APEX 0x1 -/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */ -#define PACKED_RRSET_PARENT_SIDE 0x2 -/** this rrset is SOA and has the negative ttl (from nxdomain or nodata), - * this is set on SOA rrsets in the authority section, to keep its TTL separate - * from the SOA in the answer section from a direct SOA query or ANY query. */ -#define PACKED_RRSET_SOA_NEG 0x4 -/** This rrset is considered to have a fixed TTL; its TTL doesn't have to be - * updated on encoding in a reply. This flag is not expected to be set in - * cached data. */ -#define PACKED_RRSET_FIXEDTTL 0x80000000 -/** This rrset is from RPZ. It is not real, it is synthesized data to block - * access. The flag makes lookups, from cache in iterator, ignore the fake - * items and only use actual data. Eg. when the iterator looksup NS, CNAME, - * A and AAAA types, it then gets items without this flag that are the - * actual network. But messages with these records in it can be stored in - * the cache and retrieved for a reply. */ -#define PACKED_RRSET_RPZ 0x8 - -/** number of rrs and rrsets for integer overflow protection. More than - * this is not really possible (64K packet has much less RRs and RRsets) in - * a message. And this is small enough that also multiplied there is no - * integer overflow. */ -#define RR_COUNT_MAX 0xffffff - -/** - * The identifying information for an RRset. - */ -struct packed_rrset_key { - /** - * The domain name. If not null (for id=0) it is allocated, and - * contains the wireformat domain name. - * This dname is not canonicalized. - */ - uint8_t* dname; - /** - * Length of the domain name, including last 0 root octet. - */ - size_t dname_len; - /** - * Flags. 32bit to be easy for hashing: - * o PACKED_RRSET_NSEC_AT_APEX - * o PACKED_RRSET_PARENT_SIDE - * o PACKED_RRSET_SOA_NEG - * o PACKED_RRSET_FIXEDTTL (not supposed to be cached) - * o PACKED_RRSET_RPZ - */ - uint32_t flags; - /** the rrset type in network format */ - uint16_t type; - /** the rrset class in network format */ - uint16_t rrset_class; -}; - -/** - * This structure contains an RRset. A set of resource records that - * share the same domain name, type and class. - * - * Due to memory management and threading, the key structure cannot be - * deleted, although the data can be. The id can be set to 0 to store and the - * structure can be recycled with a new id. - */ -struct ub_packed_rrset_key { - /** - * entry into hashtable. Note the lock is never destroyed, - * even when this key is retired to the cache. - * the data pointer (if not null) points to a struct packed_rrset. - */ - struct lruhash_entry entry; - /** - * the ID of this rrset. unique, based on threadid + sequenceno. - * ids are not reused, except after flushing the cache. - * zero is an unused entry, and never a valid id. - * Check this value after getting entry.lock. - * The other values in this struct may only be altered after changing - * the id (which needs a writelock on entry.lock). - */ - rrset_id_type id; - /** key data: dname, type and class */ - struct packed_rrset_key rk; -}; - -/** - * RRset trustworthiness. Bigger value is more trust. RFC 2181. - * The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA, - * are mentioned as the same trustworthiness in 2181, but split up here - * for ease of processing. - * - * rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA - * are also mentioned as the same trustworthiness in 2181, but split up here - * for ease of processing. - * - * Added trust_none for a sane initial value, smaller than anything else. - * Added validated and ultimate trust for keys and rrsig validated content. - */ -enum rrset_trust { - /** initial value for trust */ - rrset_trust_none = 0, - /** Additional information from non-authoritative answers */ - rrset_trust_add_noAA, - /** Data from the authority section of a non-authoritative answer */ - rrset_trust_auth_noAA, - /** Additional information from an authoritative answer */ - rrset_trust_add_AA, - /** non-authoritative data from the answer section of authoritative - * answers */ - rrset_trust_nonauth_ans_AA, - /** Data from the answer section of a non-authoritative answer */ - rrset_trust_ans_noAA, - /** Glue from a primary zone, or glue from a zone transfer */ - rrset_trust_glue, - /** Data from the authority section of an authoritative answer */ - rrset_trust_auth_AA, - /** The authoritative data included in the answer section of an - * authoritative reply */ - rrset_trust_ans_AA, - /** Data from a zone transfer, other than glue */ - rrset_trust_sec_noglue, - /** Data from a primary zone file, other than glue data */ - rrset_trust_prim_noglue, - /** DNSSEC(rfc4034) validated with trusted keys */ - rrset_trust_validated, - /** ultimately trusted, no more trust is possible; - * trusted keys from the unbound configuration setup. */ - rrset_trust_ultimate -}; - -/** - * Security status from validation for data. - * The order is significant; more secure, more proven later. - */ -enum sec_status { - /** UNCHECKED means that object has yet to be validated. */ - sec_status_unchecked = 0, - /** BOGUS means that the object (RRset or message) failed to validate - * (according to local policy), but should have validated. */ - sec_status_bogus, - /** INDETERMINATE means that the object is insecure, but not - * authoritatively so. Generally this means that the RRset is not - * below a configured trust anchor. */ - sec_status_indeterminate, - /** INSECURE means that the object is authoritatively known to be - * insecure. Generally this means that this RRset is below a trust - * anchor, but also below a verified, insecure delegation. */ - sec_status_insecure, - /** SECURE_SENTINEL_FAIL means that the object (RRset or message) - * validated according to local policy but did not succeed in the root - * KSK sentinel test (draft-ietf-dnsop-kskroll-sentinel). */ - sec_status_secure_sentinel_fail, - /** SECURE means that the object (RRset or message) validated - * according to local policy. */ - sec_status_secure -}; - -/** - * RRset data. - * - * The data is packed, stored contiguously in memory. - * - * It is not always stored contiguously, in that case, an unpacked-packed - * rrset has the arrays separate. A bunch of routines work on that, but - * the packed rrset that is contiguous is for the rrset-cache and the - * cache-response routines in daemon/worker.c. - * - * memory layout: - * o base struct - * o rr_len size_t array - * o rr_data uint8_t* array - * o rr_ttl time_t array (after size_t and ptrs because those may be - * 64bit and this array before those would make them unaligned). - * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned. - * o rr_data rdata wireformats - * o rrsig_data rdata wireformat(s) - * - * Rdata is stored in wireformat. The dname is stored in wireformat. - * TTLs are stored as absolute values (and could be expired). - * - * RRSIGs are stored in the arrays after the regular rrs. - * - * You need the packed_rrset_key to know dname, type, class of the - * resource records in this RRset. (if signed the rrsig gives the type too). - * - * On the wire an RR is: - * name, type, class, ttl, rdlength, rdata. - * So we need to send the following per RR: - * key.dname, ttl, rr_data[i]. - * since key.dname ends with type and class. - * and rr_data starts with the rdlength. - * the ttl value to send changes due to time. - */ -struct packed_rrset_data { - /** Timestamp added to TTLs in the packed data. - * Needed to support serving original TTLs. */ - time_t ttl_add; - /** TTL (in seconds like time()) of the rrset. - * Same for all RRs see rfc2181(5.2). */ - time_t ttl; - /** number of rrs. */ - size_t count; - /** number of rrsigs, if 0 no rrsigs */ - size_t rrsig_count; - /** the trustworthiness of the rrset data */ - enum rrset_trust trust; - /** security status of the rrset data */ - enum sec_status security; - /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */ - size_t* rr_len; - /** ttl of every rr. rr_ttl[i] ttl of rr i. */ - time_t *rr_ttl; - /** - * Array of pointers to every rr's rdata. - * The rr_data[i] rdata is stored in uncompressed wireformat. - * The first uint16_t of rr_data[i] is network format rdlength. - * - * rr_data[count] to rr_data[count+rrsig_count] contain the rrsig data. - */ - uint8_t** rr_data; -}; - -/** - * An RRset can be represented using both key and data together. - * Split into key and data structures to simplify implementation of - * caching schemes. - */ -struct packed_rrset { - /** domain name, type and class */ - struct packed_rrset_key* k; - /** ttl, count and rdatas (and rrsig) */ - struct packed_rrset_data* d; -}; - -/** - * list of packed rrsets - */ -struct packed_rrset_list { - /** next in list */ - struct packed_rrset_list* next; - /** rrset key and data */ - struct packed_rrset rrset; -}; - -/** - * Delete packed rrset key and data, not entered in hashtables yet. - * Used during parsing. - * @param pkey: rrset key structure with locks, key and data pointers. - * @param alloc: where to return the unfree-able key structure. - */ -void ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, - struct alloc_cache* alloc); - -/** - * Memory size of rrset data. RRset data must be filled in correctly. - * @param data: data to examine. - * @return size in bytes. - */ -size_t packed_rrset_sizeof(struct packed_rrset_data* data); - -/** - * Get TTL of rrset. RRset data must be filled in correctly. - * @param key: rrset key, with data to examine. - * @return ttl value. - */ -time_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key); - -/** - * Calculate memory size of rrset entry. For hash table usage. - * @param key: struct ub_packed_rrset_key*. - * @param data: struct packed_rrset_data*. - * @return size in bytes. - */ -size_t ub_rrset_sizefunc(void* key, void* data); - -/** - * compares two rrset keys. - * @param k1: struct ub_packed_rrset_key*. - * @param k2: struct ub_packed_rrset_key*. - * @return 0 if equal. - */ -int ub_rrset_compare(void* k1, void* k2); - -/** - * compare two rrset data structures. - * Compared rdata and rrsigdata, not the trust or ttl value. - * @param d1: data to compare. - * @param d2: data to compare. - * @return 1 if equal. - */ -int rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2); - -/** - * Old key to be deleted. RRset keys are recycled via alloc. - * The id is set to 0. So that other threads, after acquiring a lock always - * get the correct value, in this case the 0 deleted-special value. - * @param key: struct ub_packed_rrset_key*. - * @param userdata: alloc structure to use for recycling. - */ -void ub_rrset_key_delete(void* key, void* userdata); - -/** - * Old data to be deleted. - * @param data: what to delete. - * @param userdata: user data ptr. - */ -void rrset_data_delete(void* data, void* userdata); - -/** - * Calculate hash value for a packed rrset key. - * @param key: the rrset key with name, type, class, flags. - * @return hash value. - */ -hashvalue_type rrset_key_hash(struct packed_rrset_key* key); - -/** - * Fixup pointers in fixed data packed_rrset_data blob. - * After a memcpy of the data for example. Will set internal pointers right. - * @param data: rrset data structure. Otherwise correctly filled in. - */ -void packed_rrset_ptr_fixup(struct packed_rrset_data* data); - -/** - * Fixup TTLs in fixed data packed_rrset_data blob. - * @param data: rrset data structure. Otherwise correctly filled in. - * @param add: how many seconds to add, pass time(0) for example. - */ -void packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add); - -/** - * Utility procedure to extract CNAME target name from its rdata. - * Failsafes; it will change passed dname to a valid dname or do nothing. - * @param rrset: the rrset structure. Must be a CNAME. - * Only first RR is used (multiple RRs are technically illegal anyway). - * Also works on type DNAME. Returns target name. - * @param dname: this pointer is updated to point into the cname rdata. - * If a failsafe fails, nothing happens to the pointer (such as the - * rdata was not a valid dname, not a CNAME, ...). - * @param dname_len: length of dname is returned. - */ -void get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, - size_t* dname_len); - -/** - * Get a printable string for a rrset trust value - * @param s: rrset trust value - * @return printable string. - */ -const char* rrset_trust_to_string(enum rrset_trust s); - -/** - * Get a printable string for a security status value - * @param s: security status - * @return printable string. - */ -const char* sec_status_to_string(enum sec_status s); - -/** - * Print string with neat domain name, type, class from rrset. - * @param v: at what verbosity level to print this. - * @param str: string of message. - * @param rrset: structure with name, type and class. - */ -void log_rrset_key(enum verbosity_value v, const char* str, - struct ub_packed_rrset_key* rrset); - -/** - * Convert RR from RRset to string. - * @param rrset: structure with data. - * @param i: index of rr or RRSIG. - * @param now: time that is subtracted from ttl before printout. Can be 0. - * @param dest: destination string buffer. Must be nonNULL. - * @param dest_len: length of dest buffer (>0). - * @return false on failure. - */ -int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, - time_t now, char* dest, size_t dest_len); - -/** - * Print the string with prefix, one rr per line. - * @param v: at what verbosity level to print this. - * @param str: string of message. - * @param rrset: with name, and rdata, and rrsigs. - */ -void log_packed_rrset(enum verbosity_value v, const char* str, - struct ub_packed_rrset_key* rrset); - -/** - * Allocate rrset in region - no more locks needed - * @param key: a (just from rrset cache looked up) rrset key + valid, - * packed data record. - * @param region: where to alloc the copy - * @param now: adjust the TTLs to be relative (subtract from all TTLs). - * @return new region-alloced rrset key or NULL on alloc failure. - */ -struct ub_packed_rrset_key* packed_rrset_copy_region( - struct ub_packed_rrset_key* key, struct regional* region, - time_t now); - -/** - * Allocate rrset with malloc (from region or you are holding the lock). - * @param key: key with data entry. - * @param alloc: alloc_cache to create rrset_keys - * @param now: adjust the TTLs to be absolute (add to all TTLs). - * @return new region-alloced rrset key or NULL on alloc failure. - */ -struct ub_packed_rrset_key* packed_rrset_copy_alloc( - struct ub_packed_rrset_key* key, struct alloc_cache* alloc, - time_t now); - -/** - * Find RR index in packed rrset - * Raw comparison, does not canonicalize RDATA - * @param d: packed rrset - * @param rdata: RDATA of RR to find - * @param len: length of rdata - * @param index: pointer to int to store index of found RR - * @return 1 if RR found, 0 otherwise - */ -int -packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len, - size_t* index); - -#endif /* UTIL_DATA_PACKED_RRSET_H */ diff --git a/crates/libunbound-sys/unbound/util/edns.c b/crates/libunbound-sys/unbound/util/edns.c deleted file mode 100644 index 2b4047f0..00000000 --- a/crates/libunbound-sys/unbound/util/edns.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * util/edns.c - handle base EDNS options. - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for base EDNS options. - */ - -#include "config.h" -#include "util/edns.h" -#include "util/config_file.h" -#include "util/netevent.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/rfc_1982.h" -#include "util/siphash.h" -#include "util/data/msgparse.h" -#include "util/data/msgreply.h" -#include "sldns/sbuffer.h" - -struct edns_strings* edns_strings_create(void) -{ - struct edns_strings* edns_strings = calloc(1, - sizeof(struct edns_strings)); - if(!edns_strings) - return NULL; - if(!(edns_strings->region = regional_create())) { - edns_strings_delete(edns_strings); - return NULL; - } - return edns_strings; -} - -void edns_strings_delete(struct edns_strings* edns_strings) -{ - if(!edns_strings) - return; - regional_destroy(edns_strings->region); - free(edns_strings); -} - -static int -edns_strings_client_insert(struct edns_strings* edns_strings, - struct sockaddr_storage* addr, socklen_t addrlen, int net, - const char* string) -{ - struct edns_string_addr* esa = regional_alloc_zero(edns_strings->region, - sizeof(struct edns_string_addr)); - if(!esa) - return 0; - esa->string_len = strlen(string); - esa->string = regional_alloc_init(edns_strings->region, string, - esa->string_len); - if(!esa->string) - return 0; - if(!addr_tree_insert(&edns_strings->client_strings, &esa->node, addr, - addrlen, net)) { - verbose(VERB_QUERY, "duplicate EDNS client string ignored."); - } - return 1; -} - -int edns_strings_apply_cfg(struct edns_strings* edns_strings, - struct config_file* config) -{ - struct config_str2list* c; - regional_free_all(edns_strings->region); - addr_tree_init(&edns_strings->client_strings); - - for(c=config->edns_client_strings; c; c=c->next) { - struct sockaddr_storage addr; - socklen_t addrlen; - int net; - log_assert(c->str && c->str2); - - if(!netblockstrtoaddr(c->str, UNBOUND_DNS_PORT, &addr, &addrlen, - &net)) { - log_err("cannot parse EDNS client string IP netblock: " - "%s", c->str); - return 0; - } - if(!edns_strings_client_insert(edns_strings, &addr, addrlen, - net, c->str2)) { - log_err("out of memory while adding EDNS strings"); - return 0; - } - } - edns_strings->client_string_opcode = config->edns_client_string_opcode; - - addr_tree_init_parents(&edns_strings->client_strings); - return 1; -} - -struct edns_string_addr* -edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen); -} - -uint8_t* -edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret, int v4, - uint8_t* hash) -{ - v4?siphash(in, 20, secret, hash, 8):siphash(in, 32, secret, hash, 8); - return hash; -} - -void -edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4, - uint32_t timestamp) -{ - uint8_t hash[8]; - buf[ 8] = 1; /* Version */ - buf[ 9] = 0; /* Reserved */ - buf[10] = 0; /* Reserved */ - buf[11] = 0; /* Reserved */ - sldns_write_uint32(buf + 12, timestamp); - (void)edns_cookie_server_hash(buf, secret, v4, hash); - memcpy(buf + 16, hash, 8); -} - -enum edns_cookie_val_status -edns_cookie_server_validate(const uint8_t* cookie, size_t cookie_len, - const uint8_t* secret, size_t secret_len, int v4, - const uint8_t* hash_input, uint32_t now) -{ - uint8_t hash[8]; - uint32_t timestamp; - uint32_t subt_1982 = 0; /* Initialize for the compiler; unused value */ - int comp_1982; - if(cookie_len != 24) - /* RFC9018 cookies are 24 bytes long */ - return COOKIE_STATUS_CLIENT_ONLY; - if(secret_len != 16 || /* RFC9018 cookies have 16 byte secrets */ - cookie[8] != 1) /* RFC9018 cookies are cookie version 1 */ - return COOKIE_STATUS_INVALID; - timestamp = sldns_read_uint32(cookie + 12); - if((comp_1982 = compare_1982(now, timestamp)) > 0 - && (subt_1982 = subtract_1982(timestamp, now)) > 3600) - /* Cookie is older than 1 hour (see RFC9018 Section 4.3.) */ - return COOKIE_STATUS_EXPIRED; - if(comp_1982 <= 0 && subtract_1982(now, timestamp) > 300) - /* Cookie time is more than 5 minutes in the future. - * (see RFC9018 Section 4.3.) */ - return COOKIE_STATUS_FUTURE; - if(memcmp(edns_cookie_server_hash(hash_input, secret, v4, hash), - cookie + 16, 8) != 0) - /* Hashes do not match */ - return COOKIE_STATUS_INVALID; - if(comp_1982 > 0 && subt_1982 > 1800) - /* Valid cookie but older than 30 minutes, so create a new one - * anyway */ - return COOKIE_STATUS_VALID_RENEW; - return COOKIE_STATUS_VALID; -} diff --git a/crates/libunbound-sys/unbound/util/edns.h b/crates/libunbound-sys/unbound/util/edns.h deleted file mode 100644 index 5da0ecb2..00000000 --- a/crates/libunbound-sys/unbound/util/edns.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * util/edns.h - handle base EDNS options. - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for base EDNS options. - */ - -#ifndef UTIL_EDNS_H -#define UTIL_EDNS_H - -#include "util/storage/dnstree.h" - -struct edns_data; -struct config_file; -struct comm_point; -struct regional; - -/** - * Structure containing all EDNS strings. - */ -struct edns_strings { - /** Tree of EDNS client strings to use in upstream queries, per address - * prefix. Contains nodes of type edns_string_addr. */ - rbtree_type client_strings; - /** EDNS opcode to use for client strings */ - uint16_t client_string_opcode; - /** region to allocate tree nodes in */ - struct regional* region; -}; - -/** - * EDNS string. Node of rbtree, containing string and prefix. - */ -struct edns_string_addr { - /** node in address tree, used for tree lookups. Need to be the first - * member of this struct. */ - struct addr_tree_node node; - /** string, ascii format */ - uint8_t* string; - /** length of string */ - size_t string_len; -}; - -enum edns_cookie_val_status { - COOKIE_STATUS_CLIENT_ONLY = -3, - COOKIE_STATUS_FUTURE = -2, - COOKIE_STATUS_EXPIRED = -1, - COOKIE_STATUS_INVALID = 0, - COOKIE_STATUS_VALID = 1, - COOKIE_STATUS_VALID_RENEW = 2, -}; - -/** - * Create structure to hold EDNS strings - * @return: newly created edns_strings, NULL on alloc failure. - */ -struct edns_strings* edns_strings_create(void); - -/** Delete EDNS strings structure - * @param edns_strings: struct to delete - */ -void edns_strings_delete(struct edns_strings* edns_strings); - -/** - * Add configured EDNS strings - * @param edns_strings: edns strings to apply config to - * @param config: struct containing EDNS strings configuration - * @return 0 on error - */ -int edns_strings_apply_cfg(struct edns_strings* edns_strings, - struct config_file* config); - -/** - * Find string for address. - * @param tree: tree containing EDNS strings per address prefix. - * @param addr: address to use for tree lookup - * @param addrlen: length of address - * @return: matching tree node, NULL otherwise - */ -struct edns_string_addr* -edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr, - socklen_t addrlen); - -/** - * Compute the interoperable DNS cookie (RFC9018) hash. - * @param in: buffer input for the hash generation. It needs to be: - * Client Cookie | Version | Reserved | Timestamp | Client-IP - * @param secret: the server secret; implicit length of 16 octets. - * @param v4: if the client IP is v4 or v6. - * @param hash: buffer to write the hash to. - * return a pointer to the hash. - */ -uint8_t* edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret, - int v4, uint8_t* hash); - -/** - * Write an interoperable DNS server cookie (RFC9018). - * @param buf: buffer to write to. It should have a size of at least 32 octets - * as it doubles as the output buffer and the hash input buffer. - * The first 8 octets are expected to be the Client Cookie and will be - * left untouched. - * The next 8 octets will be written with Version | Reserved | Timestamp. - * The next 4 or 16 octets are expected to be the IPv4 or the IPv6 address - * based on the v4 flag. - * Thus the first 20 or 32 octets, based on the v4 flag, will be used as - * the hash input. - * The server hash (8 octets) will be written after the first 16 octets; - * overwriting the address information. - * The caller expects a complete, 24 octet long cookie in the buffer. - * @param secret: the server secret; implicit length of 16 octets. - * @param v4: if the client IP is v4 or v6. - * @param timestamp: the timestamp to use. - */ -void edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4, - uint32_t timestamp); - -/** - * Validate an interoperable DNS cookie (RFC9018). - * @param cookie: pointer to the cookie data. - * @param cookie_len: the length of the cookie data. - * @param secret: pointer to the server secret. - * @param secret_len: the length of the secret. - * @param v4: if the client IP is v4 or v6. - * @param hash_input: pointer to the hash input for validation. It needs to be: - * Client Cookie | Version | Reserved | Timestamp | Client-IP - * @param now: the current time. - * return edns_cookie_val_status with the cookie validation status i.e., - * <=0 for invalid, else valid. - */ -enum edns_cookie_val_status edns_cookie_server_validate(const uint8_t* cookie, - size_t cookie_len, const uint8_t* secret, size_t secret_len, int v4, - const uint8_t* hash_input, uint32_t now); - -#endif diff --git a/crates/libunbound-sys/unbound/util/fptr_wlist.c b/crates/libunbound-sys/unbound/util/fptr_wlist.c deleted file mode 100644 index 3b88da23..00000000 --- a/crates/libunbound-sys/unbound/util/fptr_wlist.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * util/fptr_wlist.c - function pointer whitelists. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions that check function pointers. - * The functions contain a whitelist of known good callback values. - * Any other values lead to an error. - * - * Due to the listing nature, this file violates all the modularization - * boundaries in the program. - */ -#include "config.h" -#include "util/fptr_wlist.h" -#include "util/mini_event.h" -#include "services/outside_network.h" -#include "services/mesh.h" -#include "services/localzone.h" -#include "services/authzone.h" -#include "services/cache/infra.h" -#include "services/cache/rrset.h" -#include "services/view.h" -#include "dns64/dns64.h" -#include "iterator/iterator.h" -#include "iterator/iter_fwd.h" -#include "validator/validator.h" -#include "validator/val_anchor.h" -#include "validator/val_nsec3.h" -#include "validator/val_sigcrypt.h" -#include "validator/val_kentry.h" -#include "validator/val_neg.h" -#include "validator/autotrust.h" -#include "util/data/msgreply.h" -#include "util/data/packed_rrset.h" -#include "util/storage/slabhash.h" -#include "util/storage/dnstree.h" -#include "util/locks.h" -#include "libunbound/libworker.h" -#include "libunbound/context.h" -#include "libunbound/worker.h" -#include "util/tube.h" -#include "util/config_file.h" -#ifdef UB_ON_WINDOWS -#include "winrc/win_svc.h" -#endif -#include "respip/respip.h" - -#ifdef WITH_PYTHONMODULE -#include "pythonmod/pythonmod.h" -#endif -#ifdef WITH_DYNLIBMODULE -#include "dynlibmod/dynlibmod.h" -#endif -#ifdef USE_CACHEDB -#include "cachedb/cachedb.h" -#endif -#ifdef USE_IPSECMOD -#include "ipsecmod/ipsecmod.h" -#endif -#ifdef CLIENT_SUBNET -#include "edns-subnet/subnetmod.h" -#endif -#ifdef USE_IPSET -#include "ipset/ipset.h" -#endif -#ifdef USE_DNSTAP -#include "dnstap/dtstream.h" -#endif - -int -fptr_whitelist_comm_point(comm_point_callback_type *fptr) -{ - if(fptr == &worker_handle_request) return 1; - else if(fptr == &outnet_udp_cb) return 1; - else if(fptr == &outnet_tcp_cb) return 1; - else if(fptr == &tube_handle_listen) return 1; - else if(fptr == &auth_xfer_probe_udp_callback) return 1; - else if(fptr == &auth_xfer_transfer_tcp_callback) return 1; - else if(fptr == &auth_xfer_transfer_http_callback) return 1; - return 0; -} - -int -fptr_whitelist_comm_point_raw(comm_point_callback_type *fptr) -{ - if(fptr == &tube_handle_listen) return 1; - else if(fptr == &tube_handle_write) return 1; - else if(fptr == &remote_accept_callback) return 1; - else if(fptr == &remote_control_callback) return 1; - return 0; -} - -int -fptr_whitelist_comm_timer(void (*fptr)(void*)) -{ - if(fptr == &pending_udp_timer_cb) return 1; - else if(fptr == &outnet_tcptimer) return 1; - else if(fptr == &pending_udp_timer_delay_cb) return 1; - else if(fptr == &worker_stat_timer_cb) return 1; - else if(fptr == &worker_probe_timer_cb) return 1; -#ifdef UB_ON_WINDOWS - else if(fptr == &wsvc_cron_cb) return 1; -#endif - else if(fptr == &auth_xfer_timer) return 1; - else if(fptr == &auth_xfer_probe_timer_callback) return 1; - else if(fptr == &auth_xfer_transfer_timer_callback) return 1; - else if(fptr == &mesh_serve_expired_callback) return 1; - else if(fptr == &serviced_timer_cb) return 1; -#ifdef USE_DNSTAP - else if(fptr == &mq_wakeup_cb) return 1; -#endif - return 0; -} - -int -fptr_whitelist_comm_signal(void (*fptr)(int, void*)) -{ - if(fptr == &worker_sighandler) return 1; - return 0; -} - -int fptr_whitelist_start_accept(void (*fptr)(void*)) -{ - if(fptr == &worker_start_accept) return 1; - return 0; -} - -int fptr_whitelist_stop_accept(void (*fptr)(void*)) -{ - if(fptr == &worker_stop_accept) return 1; - return 0; -} - -int -fptr_whitelist_event(void (*fptr)(int, short, void *)) -{ - if(fptr == &comm_point_udp_callback) return 1; - else if(fptr == &comm_point_udp_ancil_callback) return 1; - else if(fptr == &comm_point_tcp_accept_callback) return 1; - else if(fptr == &comm_point_tcp_handle_callback) return 1; - else if(fptr == &comm_timer_callback) return 1; - else if(fptr == &comm_signal_callback) return 1; - else if(fptr == &comm_point_local_handle_callback) return 1; - else if(fptr == &comm_point_raw_handle_callback) return 1; - else if(fptr == &tube_handle_signal) return 1; - else if(fptr == &comm_base_handle_slow_accept) return 1; - else if(fptr == &comm_point_http_handle_callback) return 1; -#ifdef USE_DNSTAP - else if(fptr == &dtio_output_cb) return 1; - else if(fptr == &dtio_cmd_cb) return 1; - else if(fptr == &dtio_reconnect_timeout_cb) return 1; - else if(fptr == &dtio_stop_timer_cb) return 1; - else if(fptr == &dtio_stop_ev_cb) return 1; - else if(fptr == &dtio_tap_callback) return 1; - else if(fptr == &dtio_mainfdcallback) return 1; -#endif -#ifdef UB_ON_WINDOWS - else if(fptr == &worker_win_stop_cb) return 1; -#endif - return 0; -} - -int -fptr_whitelist_pending_udp(comm_point_callback_type *fptr) -{ - if(fptr == &serviced_udp_callback) return 1; - return 0; -} - -int -fptr_whitelist_pending_tcp(comm_point_callback_type *fptr) -{ - if(fptr == &serviced_tcp_callback) return 1; - return 0; -} - -int -fptr_whitelist_serviced_query(comm_point_callback_type *fptr) -{ - if(fptr == &worker_handle_service_reply) return 1; - else if(fptr == &libworker_handle_service_reply) return 1; - return 0; -} - -int -fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *)) -{ - if(fptr == &mesh_state_compare) return 1; - else if(fptr == &mesh_state_ref_compare) return 1; - else if(fptr == &addr_tree_compare) return 1; - else if(fptr == &addr_tree_addrport_compare) return 1; - else if(fptr == &local_zone_cmp) return 1; - else if(fptr == &local_data_cmp) return 1; - else if(fptr == &fwd_cmp) return 1; - else if(fptr == &pending_cmp) return 1; - else if(fptr == &serviced_cmp) return 1; - else if(fptr == &reuse_cmp) return 1; - else if(fptr == &reuse_id_cmp) return 1; - else if(fptr == &name_tree_compare) return 1; - else if(fptr == &order_lock_cmp) return 1; - else if(fptr == &codeline_cmp) return 1; - else if(fptr == &nsec3_hash_cmp) return 1; - else if(fptr == &mini_ev_cmp) return 1; - else if(fptr == &anchor_cmp) return 1; - else if(fptr == &canonical_tree_compare) return 1; - else if(fptr == &context_query_cmp) return 1; - else if(fptr == &val_neg_data_compare) return 1; - else if(fptr == &val_neg_zone_compare) return 1; - else if(fptr == &probetree_cmp) return 1; - else if(fptr == &replay_var_compare) return 1; - else if(fptr == &view_cmp) return 1; - else if(fptr == &auth_zone_cmp) return 1; - else if(fptr == &auth_data_cmp) return 1; - else if(fptr == &auth_xfer_cmp) return 1; - return 0; -} - -int -fptr_whitelist_hash_sizefunc(lruhash_sizefunc_type fptr) -{ - if(fptr == &msgreply_sizefunc) return 1; - else if(fptr == &ub_rrset_sizefunc) return 1; - else if(fptr == &infra_sizefunc) return 1; - else if(fptr == &key_entry_sizefunc) return 1; - else if(fptr == &rate_sizefunc) return 1; - else if(fptr == &ip_rate_sizefunc) return 1; - else if(fptr == &test_slabhash_sizefunc) return 1; -#ifdef CLIENT_SUBNET - else if(fptr == &msg_cache_sizefunc) return 1; -#endif -#ifdef USE_DNSCRYPT - else if(fptr == &dnsc_shared_secrets_sizefunc) return 1; - else if(fptr == &dnsc_nonces_sizefunc) return 1; -#endif - return 0; -} - -int -fptr_whitelist_hash_compfunc(lruhash_compfunc_type fptr) -{ - if(fptr == &query_info_compare) return 1; - else if(fptr == &ub_rrset_compare) return 1; - else if(fptr == &infra_compfunc) return 1; - else if(fptr == &key_entry_compfunc) return 1; - else if(fptr == &rate_compfunc) return 1; - else if(fptr == &ip_rate_compfunc) return 1; - else if(fptr == &test_slabhash_compfunc) return 1; -#ifdef USE_DNSCRYPT - else if(fptr == &dnsc_shared_secrets_compfunc) return 1; - else if(fptr == &dnsc_nonces_compfunc) return 1; -#endif - return 0; -} - -int -fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_type fptr) -{ - if(fptr == &query_entry_delete) return 1; - else if(fptr == &ub_rrset_key_delete) return 1; - else if(fptr == &infra_delkeyfunc) return 1; - else if(fptr == &key_entry_delkeyfunc) return 1; - else if(fptr == &rate_delkeyfunc) return 1; - else if(fptr == &ip_rate_delkeyfunc) return 1; - else if(fptr == &test_slabhash_delkey) return 1; -#ifdef USE_DNSCRYPT - else if(fptr == &dnsc_shared_secrets_delkeyfunc) return 1; - else if(fptr == &dnsc_nonces_delkeyfunc) return 1; -#endif - return 0; -} - -int -fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_type fptr) -{ - if(fptr == &reply_info_delete) return 1; - else if(fptr == &rrset_data_delete) return 1; - else if(fptr == &infra_deldatafunc) return 1; - else if(fptr == &key_entry_deldatafunc) return 1; - else if(fptr == &rate_deldatafunc) return 1; - else if(fptr == &test_slabhash_deldata) return 1; -#ifdef CLIENT_SUBNET - else if(fptr == &subnet_data_delete) return 1; -#endif -#ifdef USE_DNSCRYPT - else if(fptr == &dnsc_shared_secrets_deldatafunc) return 1; - else if(fptr == &dnsc_nonces_deldatafunc) return 1; -#endif - return 0; -} - -int -fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr) -{ - if(fptr == NULL) return 1; - else if(fptr == &rrset_markdel) return 1; -#ifdef CLIENT_SUBNET - else if(fptr == &subnet_markdel) return 1; -#endif - return 0; -} - -/** whitelist env->send_query callbacks */ -int -fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( - struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int check_ratelimit, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream, - int ssl_upstream, char* tls_auth_name, struct module_qstate* q, - int* was_ratelimited)) -{ - if(fptr == &worker_send_query) return 1; - else if(fptr == &libworker_send_query) return 1; - return 0; -} - -int -fptr_whitelist_modenv_detach_subs(void (*fptr)( - struct module_qstate* qstate)) -{ - if(fptr == &mesh_detach_subs) return 1; - return 0; -} - -int -fptr_whitelist_modenv_attach_sub(int (*fptr)( - struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq)) -{ - if(fptr == &mesh_attach_sub) return 1; - return 0; -} - -int -fptr_whitelist_modenv_add_sub(int (*fptr)( - struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub)) -{ - if(fptr == &mesh_add_sub) return 1; - return 0; -} - -int -fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq)) -{ - if(fptr == &mesh_state_delete) return 1; - return 0; -} - -int -fptr_whitelist_modenv_detect_cycle(int (*fptr)( - struct module_qstate* qstate, struct query_info* qinfo, - uint16_t flags, int prime, int valrec)) -{ - if(fptr == &mesh_detect_cycle) return 1; - return 0; -} - -int -fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)) -{ - if(fptr == &iter_init) return 1; - else if(fptr == &val_init) return 1; - else if(fptr == &dns64_init) return 1; - else if(fptr == &respip_init) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_init) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_init) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_init) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_init) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_init) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_init) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)) -{ - if(fptr == &iter_deinit) return 1; - else if(fptr == &val_deinit) return 1; - else if(fptr == &dns64_deinit) return 1; - else if(fptr == &respip_deinit) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_deinit) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_deinit) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_deinit) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_deinit) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_deinit) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_deinit) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate, - enum module_ev event, int id, struct outbound_entry* outbound)) -{ - if(fptr == &iter_operate) return 1; - else if(fptr == &val_operate) return 1; - else if(fptr == &dns64_operate) return 1; - else if(fptr == &respip_operate) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_operate) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_operate) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_operate) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_operate) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_operate) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_operate) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_inform_super(void (*fptr)( - struct module_qstate* qstate, int id, struct module_qstate* super)) -{ - if(fptr == &iter_inform_super) return 1; - else if(fptr == &val_inform_super) return 1; - else if(fptr == &dns64_inform_super) return 1; - else if(fptr == &respip_inform_super) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_inform_super) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_inform_super) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_inform_super) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_inform_super) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_inform_super) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_inform_super) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate, - int id)) -{ - if(fptr == &iter_clear) return 1; - else if(fptr == &val_clear) return 1; - else if(fptr == &dns64_clear) return 1; - else if(fptr == &respip_clear) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_clear) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_clear) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_clear) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_clear) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_clear) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_clear) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)) -{ - if(fptr == &iter_get_mem) return 1; - else if(fptr == &val_get_mem) return 1; - else if(fptr == &dns64_get_mem) return 1; - else if(fptr == &respip_get_mem) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_get_mem) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - else if(fptr == &dynlibmod_get_mem) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_get_mem) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_get_mem) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_get_mem) return 1; -#endif -#ifdef USE_IPSET - else if(fptr == &ipset_get_mem) return 1; -#endif - return 0; -} - -int -fptr_whitelist_alloc_cleanup(void (*fptr)(void*)) -{ - if(fptr == &worker_alloc_cleanup) return 1; - return 0; -} - -int fptr_whitelist_tube_listen(tube_callback_type* fptr) -{ - if(fptr == &worker_handle_control_cmd) return 1; - else if(fptr == &libworker_handle_control_cmd) return 1; - return 0; -} - -int fptr_whitelist_mesh_cb(mesh_cb_func_type fptr) -{ - if(fptr == &libworker_fg_done_cb) return 1; - else if(fptr == &libworker_bg_done_cb) return 1; - else if(fptr == &libworker_event_done_cb) return 1; - else if(fptr == &probe_answer_cb) return 1; - else if(fptr == &auth_xfer_probe_lookup_callback) return 1; - else if(fptr == &auth_xfer_transfer_lookup_callback) return 1; - else if(fptr == &auth_zonemd_dnskey_lookup_callback) return 1; - return 0; -} - -int fptr_whitelist_print_func(void (*fptr)(char*,void*)) -{ - if(fptr == &config_print_func) return 1; - else if(fptr == &config_collate_func) return 1; - else if(fptr == &remote_get_opt_ssl) return 1; - return 0; -} - -int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr, - enum inplace_cb_list_type type) -{ -#ifndef WITH_PYTHONMODULE - (void)fptr; -#endif - if(type == inplace_cb_reply) { -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_reply_generic) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_reply_generic) return 1; -#endif - } else if(type == inplace_cb_reply_cache) { -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_reply_generic) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_reply_generic) return 1; -#endif - } else if(type == inplace_cb_reply_local) { -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_reply_generic) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_reply_generic) return 1; -#endif - } else if(type == inplace_cb_reply_servfail) { -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_reply_generic) return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_reply_generic) return 1; -#endif - } - return 0; -} - -int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr) -{ -#ifdef CLIENT_SUBNET - if(fptr == &ecs_whitelist_check) - return 1; -#endif -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_query_generic) - return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_query_generic) - return 1; -#endif - (void)fptr; - return 0; -} - -int fptr_whitelist_inplace_cb_edns_back_parsed( - inplace_cb_edns_back_parsed_func_type* fptr) -{ -#ifdef CLIENT_SUBNET - if(fptr == &ecs_edns_back_parsed) - return 1; -#else - (void)fptr; -#endif -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_edns_back_parsed_call) - return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_edns_back_parsed) - return 1; -#endif - return 0; -} - -int fptr_whitelist_inplace_cb_query_response( - inplace_cb_query_response_func_type* fptr) -{ -#ifdef CLIENT_SUBNET - if(fptr == &ecs_query_response) - return 1; -#else - (void)fptr; -#endif -#ifdef WITH_PYTHONMODULE - if(fptr == &python_inplace_cb_query_response) - return 1; -#endif -#ifdef WITH_DYNLIBMODULE - if(fptr == &dynlib_inplace_cb_query_response) - return 1; -#endif - return 0; -} - -int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr) -{ - if(fptr == &mesh_serve_expired_lookup) - return 1; - return 0; -} diff --git a/crates/libunbound-sys/unbound/util/fptr_wlist.h b/crates/libunbound-sys/unbound/util/fptr_wlist.h deleted file mode 100644 index a0d98675..00000000 --- a/crates/libunbound-sys/unbound/util/fptr_wlist.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * util/fptr_wlist.h - function pointer whitelists. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions that check function pointers. - * The functions contain a whitelist of known good callback values. - * Any other values lead to an error. - * - * This prevent heap overflow based exploits, where the callback pointer - * is overwritten by a buffer overflow (apart from this defense, buffer - * overflows should be fixed of course). - * - * Function pointers are used in - * o network code callbacks. - * o rbtree, lruhash, region data manipulation - * in lruhash, the assertions are before the critical regions. - * in other places, assertions are before the callback. - * o module operations. - */ - -#ifndef UTIL_FPTR_WLIST_H -#define UTIL_FPTR_WLIST_H -#include "util/netevent.h" -#include "util/storage/lruhash.h" -#include "util/module.h" -#include "util/tube.h" -#include "services/mesh.h" - -/** - * Macro to perform an assertion check for fptr wlist checks. - * Does not get disabled in optimize mode. Check adds security by layers. - */ -#if defined(EXPORT_ALL_SYMBOLS) -#define fptr_ok(x) /* nothing, dll-exe memory layout on win disables it */ -#else -#define fptr_ok(x) \ - do { if(!(x)) \ - fatal_exit("%s:%d: %s: pointer whitelist %s failed", \ - __FILE__, __LINE__, __func__, #x); \ - } while(0); -#endif - -/** - * Check function pointer whitelist for comm_point callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_comm_point(comm_point_callback_type *fptr); - -/** - * Check function pointer whitelist for raw comm_point callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_comm_point_raw(comm_point_callback_type *fptr); - -/** - * Check function pointer whitelist for comm_timer callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_comm_timer(void (*fptr)(void*)); - -/** - * Check function pointer whitelist for comm_signal callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_comm_signal(void (*fptr)(int, void*)); - -/** - * Check function pointer whitelist for start_accept callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_start_accept(void (*fptr)(void*)); - -/** - * Check function pointer whitelist for stop_accept callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_stop_accept(void (*fptr)(void*)); - -/** - * Check function pointer whitelist for event structure callback values. - * This is not called by libevent itself, but checked by netevent. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_event(void (*fptr)(int, short, void *)); - -/** - * Check function pointer whitelist for pending udp callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_pending_udp(comm_point_callback_type *fptr); - -/** - * Check function pointer whitelist for pending tcp callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_pending_tcp(comm_point_callback_type *fptr); - -/** - * Check function pointer whitelist for serviced query callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_serviced_query(comm_point_callback_type *fptr); - -/** - * Check function pointer whitelist for rbtree cmp callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *)); - -/** - * Check function pointer whitelist for lruhash sizefunc callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_hash_sizefunc(lruhash_sizefunc_type fptr); - -/** - * Check function pointer whitelist for lruhash compfunc callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_hash_compfunc(lruhash_compfunc_type fptr); - -/** - * Check function pointer whitelist for lruhash delkeyfunc callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_type fptr); - -/** - * Check function pointer whitelist for lruhash deldata callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_type fptr); - -/** - * Check function pointer whitelist for lruhash markdel callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr); - -/** - * Check function pointer whitelist for module_env send_query callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( - struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, int check_ratelimit, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream, - int ssl_upstream, char* tls_auth_name, struct module_qstate* q, - int* was_ratelimited)); - -/** - * Check function pointer whitelist for module_env detach_subs callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_detach_subs(void (*fptr)( - struct module_qstate* qstate)); - -/** - * Check function pointer whitelist for module_env attach_sub callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_attach_sub(int (*fptr)( - struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq)); - -/** - * Check function pointer whitelist for module_env add_sub callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_add_sub(int (*fptr)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, int valrec, - struct module_qstate** newq, struct mesh_state** sub)); -/** - * Check function pointer whitelist for module_env kill_sub callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq)); - -/** - * Check function pointer whitelist for module_env detect_cycle callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_modenv_detect_cycle(int (*fptr)( - struct module_qstate* qstate, struct query_info* qinfo, - uint16_t flags, int prime, int valrec)); - -/** - * Check function pointer whitelist for module init call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)); - -/** - * Check function pointer whitelist for module deinit call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)); - -/** - * Check function pointer whitelist for module operate call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate, - enum module_ev event, int id, struct outbound_entry* outbound)); - -/** - * Check function pointer whitelist for module inform_super call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_inform_super(void (*fptr)( - struct module_qstate* qstate, int id, struct module_qstate* super)); - -/** - * Check function pointer whitelist for module clear call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate, - int id)); - -/** - * Check function pointer whitelist for module get_mem call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)); - -/** - * Check function pointer whitelist for alloc clear on id overflow call values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_alloc_cleanup(void (*fptr)(void*)); - -/** - * Check function pointer whitelist for tube listen handler values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_tube_listen(tube_callback_type* fptr); - -/** - * Check function pointer whitelist for mesh state callback values. - * - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_mesh_cb(mesh_cb_func_type fptr); - -/** - * Check function pointer whitelist for config_get_option func values. - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_print_func(void (*fptr)(char*,void*)); - -/** - * Check function pointer whitelist for inplace_cb_reply, - * inplace_cb_reply_cache, inplace_cb_reply_local and inplace_cb_reply_servfail - * func values. - * @param fptr: function pointer to check. - * @param type: the type of the callback function. - * @return false if not in whitelist. - */ -int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr, - enum inplace_cb_list_type type); - -/** - * Check function pointer whitelist for inplace_cb_query func values. - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr); - -/** - * Check function pointer whitelist for inplace_cb_edns_back_parsed func values. - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_inplace_cb_edns_back_parsed( - inplace_cb_edns_back_parsed_func_type* fptr); - -/** - * Check function pointer whitelist for inplace_cb_query_response func values. - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_inplace_cb_query_response( - inplace_cb_query_response_func_type* fptr); - -/** - * Check function pointer whitelist for serve_expired_lookup func values. - * @param fptr: function pointer to check. - * @return false if not in whitelist. - */ -int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr); - -/** Due to module breakage by fptr wlist, these test app declarations - * are presented here */ -/** - * compare two order_ids from lock-verify test app - * @param e1: first order_id - * @param e2: second order_id - * @return compare code -1, 0, +1 (like memcmp). - */ -int order_lock_cmp(const void* e1, const void* e2); - -/** - * compare two codeline structs for rbtree from memstats test app - * @param a: codeline - * @param b: codeline - * @return compare code -1, 0, +1 (like memcmp). - */ -int codeline_cmp(const void* a, const void* b); - -/** compare two replay_vars */ -int replay_var_compare(const void* a, const void* b); - -#endif /* UTIL_FPTR_WLIST_H */ diff --git a/crates/libunbound-sys/unbound/util/iana_ports.inc b/crates/libunbound-sys/unbound/util/iana_ports.inc deleted file mode 100644 index 5cb127ed..00000000 --- a/crates/libunbound-sys/unbound/util/iana_ports.inc +++ /dev/null @@ -1,5502 +0,0 @@ -1, -2, -3, -5, -7, -9, -11, -13, -17, -18, -19, -20, -21, -22, -23, -24, -25, -27, -29, -31, -33, -35, -37, -38, -39, -41, -42, -43, -44, -45, -46, -48, -49, -50, -52, -53, -54, -55, -56, -57, -58, -59, -62, -63, -64, -65, -66, -67, -68, -69, -70, -71, -72, -73, -74, -75, -76, -77, -78, -79, -80, -82, -83, -84, -85, -86, -87, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -101, -102, -103, -104, -105, -106, -107, -108, -109, -110, -111, -112, -113, -115, -116, -117, -118, -119, -120, -121, -122, -123, -124, -125, -126, -127, -128, -129, -130, -131, -132, -133, -134, -135, -136, -137, -138, -139, -140, -141, -142, -144, -145, -146, -147, -148, -149, -150, -151, -152, -153, -154, -155, -156, -157, -158, -159, -160, -161, -162, -163, -164, -165, -166, -167, -168, -169, -170, -171, -172, -173, -174, -175, -176, -177, -178, -179, -180, -181, -182, -183, -184, -185, -186, -187, -188, -189, -190, -191, -192, -193, -194, -195, -196, -197, -198, -199, -200, -201, -202, -203, -204, -205, -206, -207, -208, -209, -210, -211, -212, -213, -214, -215, -216, -217, -218, -219, -220, -221, -222, -223, -224, -242, -243, -244, -245, -246, -247, -248, -256, -257, -259, -260, -261, -262, -263, -264, -265, -266, -267, -268, -269, -270, -280, -281, -282, -283, -284, -286, -287, -308, -309, -310, -311, -312, -313, -314, -315, -316, -317, -318, -319, -320, -321, -322, -333, -344, -345, -346, -347, -348, -349, -350, -351, -352, -353, -354, -355, -356, -357, -358, -359, -360, -361, -362, -363, -364, -365, -366, -367, -368, -369, -370, -371, -372, -373, -374, -375, -376, -377, -378, -379, -380, -381, -382, -383, -384, -385, -386, -387, -388, -389, -390, -391, -392, -393, -394, -395, -396, -397, -398, -399, -400, -401, -402, -403, -404, -405, -406, -407, -408, -409, -410, -411, -412, -413, -414, -415, -416, -417, -418, -419, -420, -421, -422, -423, -424, -425, -426, -427, -428, -429, -430, -431, -432, -433, -434, -435, -436, -437, -438, -439, -440, -441, -442, -443, -444, -445, -446, -447, -448, -449, -450, -451, -452, -453, -454, -455, -456, -457, -458, -459, -460, -461, -462, -463, -464, -465, -466, -467, -468, -469, -470, -471, -472, -473, -474, -475, -476, -477, -478, -479, -480, -481, -482, -483, -484, -485, -486, -487, -488, -489, -490, -491, -492, -493, -494, -495, -496, -497, -498, -499, -500, -501, -502, -503, -504, -505, -506, -507, -508, -509, -510, -511, -512, -513, -514, -515, -516, -517, -518, -519, -520, -521, -522, -523, -524, -525, -526, -527, -528, -529, -530, -531, -532, -533, -534, -535, -536, -537, -538, -539, -540, -541, -542, -543, -544, -545, -546, -547, -548, -549, -550, -551, -552, -553, -554, -555, -556, -557, -558, -559, -560, -561, -562, -563, -564, -565, -566, -567, -568, -569, -570, -571, -572, -573, -574, -575, -576, -577, -578, -579, -580, -581, -582, -583, -584, -586, -587, -588, -589, -590, -591, -592, -593, -594, -595, -596, -597, -598, -599, -600, -601, -602, -603, -604, -605, -606, -607, -608, -609, -610, -611, -612, -613, -614, -615, -616, -617, -618, -619, -620, -621, -622, -623, -624, -625, -626, -627, -628, -629, -630, -631, -632, -633, -634, -635, -636, -637, -638, -639, -640, -641, -642, -643, -644, -645, -646, -647, -648, -649, -650, -651, -652, -653, -654, -655, -656, -657, -658, -660, -661, -662, -663, -664, -665, -666, -667, -668, -669, -670, -671, -672, -673, -674, -675, -676, -677, -678, -679, -680, -681, -682, -683, -684, -685, -686, -687, -688, -689, -690, -691, -692, -693, -694, -695, -696, -697, -698, -699, -700, -701, -702, -704, -705, -706, -707, -709, -710, -711, -712, -713, -714, -715, -716, -729, -730, -731, -741, -742, -744, -747, -748, -749, -750, -751, -752, -753, -754, -758, -759, -760, -761, -762, -763, -764, -765, -767, -769, -770, -771, -772, -773, -774, -775, -776, -777, -780, -800, -801, -802, -810, -828, -829, -830, -831, -832, -833, -847, -848, -853, -854, -860, -861, -862, -873, -886, -887, -888, -900, -901, -902, -903, -910, -911, -912, -913, -914, -915, -989, -990, -991, -992, -995, -996, -997, -998, -999, -1000, -1008, -1010, -1021, -1022, -1025, -1026, -1027, -1029, -1033, -1034, -1035, -1036, -1037, -1038, -1039, -1040, -1041, -1042, -1043, -1044, -1045, -1046, -1047, -1048, -1049, -1050, -1051, -1052, -1053, -1054, -1055, -1056, -1057, -1058, -1059, -1060, -1061, -1062, -1063, -1064, -1065, -1066, -1067, -1068, -1069, -1070, -1071, -1072, -1073, -1074, -1075, -1076, -1077, -1078, -1079, -1080, -1081, -1082, -1083, -1084, -1085, -1086, -1087, -1088, -1089, -1090, -1091, -1092, -1093, -1094, -1095, -1096, -1097, -1098, -1099, -1100, -1101, -1102, -1103, -1104, -1105, -1106, -1107, -1108, -1110, -1111, -1112, -1113, -1114, -1115, -1116, -1117, -1118, -1119, -1120, -1121, -1122, -1123, -1124, -1125, -1126, -1127, -1128, -1129, -1130, -1131, -1132, -1133, -1134, -1135, -1136, -1137, -1138, -1139, -1140, -1141, -1142, -1143, -1144, -1145, -1146, -1147, -1148, -1149, -1150, -1151, -1152, -1153, -1154, -1155, -1156, -1157, -1158, -1159, -1160, -1161, -1162, -1163, -1164, -1165, -1166, -1167, -1168, -1169, -1170, -1171, -1172, -1173, -1174, -1175, -1176, -1177, -1178, -1179, -1180, -1181, -1182, -1183, -1184, -1185, -1186, -1187, -1188, -1189, -1190, -1191, -1192, -1193, -1194, -1195, -1196, -1197, -1198, -1199, -1200, -1201, -1202, -1203, -1204, -1205, -1206, -1207, -1208, -1209, -1210, -1211, -1212, -1213, -1214, -1215, -1216, -1217, -1218, -1219, -1220, -1221, -1222, -1223, -1224, -1225, -1226, -1227, -1228, -1229, -1230, -1231, -1232, -1233, -1234, -1235, -1236, -1237, -1238, -1239, -1240, -1241, -1242, -1243, -1244, -1245, -1246, -1247, -1248, -1249, -1250, -1251, -1252, -1253, -1254, -1255, -1256, -1257, -1258, -1259, -1260, -1261, -1262, -1263, -1264, -1265, -1266, -1267, -1268, -1269, -1270, -1271, -1272, -1273, -1274, -1275, -1277, -1278, -1279, -1280, -1281, -1282, -1283, -1284, -1285, -1286, -1287, -1288, -1289, -1290, -1291, -1292, -1293, -1294, -1295, -1296, -1297, -1298, -1299, -1300, -1303, -1304, -1305, -1306, -1307, -1308, -1309, -1310, -1311, -1312, -1313, -1314, -1315, -1316, -1317, -1318, -1319, -1320, -1321, -1322, -1323, -1324, -1325, -1326, -1327, -1328, -1329, -1330, -1331, -1332, -1333, -1334, -1335, -1336, -1337, -1338, -1339, -1340, -1341, -1342, -1343, -1344, -1345, -1346, -1347, -1348, -1349, -1350, -1351, -1352, -1353, -1354, -1355, -1356, -1357, -1358, -1359, -1360, -1361, -1362, -1363, -1364, -1365, -1366, -1367, -1368, -1369, -1370, -1371, -1372, -1373, -1374, -1375, -1376, -1377, -1378, -1379, -1380, -1381, -1382, -1383, -1384, -1385, -1386, -1387, -1388, -1389, -1390, -1391, -1392, -1393, -1394, -1395, -1396, -1397, -1398, -1399, -1400, -1401, -1402, -1403, -1404, -1405, -1406, -1408, -1409, -1410, -1411, -1412, -1413, -1414, -1415, -1416, -1417, -1418, -1419, -1420, -1421, -1422, -1423, -1424, -1425, -1426, -1427, -1428, -1429, -1430, -1431, -1432, -1433, -1434, -1435, -1436, -1437, -1438, -1439, -1440, -1441, -1442, -1443, -1444, -1445, -1446, -1447, -1448, -1449, -1450, -1451, -1452, -1453, -1454, -1455, -1456, -1457, -1458, -1459, -1460, -1461, -1462, -1463, -1464, -1465, -1466, -1467, -1468, -1469, -1470, -1471, -1472, -1473, -1474, -1475, -1476, -1477, -1478, -1479, -1480, -1481, -1482, -1483, -1484, -1485, -1486, -1487, -1488, -1489, -1490, -1492, -1493, -1494, -1495, -1496, -1497, -1498, -1499, -1500, -1501, -1502, -1503, -1504, -1505, -1506, -1507, -1508, -1509, -1510, -1511, -1512, -1513, -1514, -1515, -1516, -1517, -1518, -1519, -1520, -1521, -1522, -1523, -1524, -1525, -1526, -1527, -1528, -1529, -1530, -1531, -1532, -1533, -1534, -1535, -1536, -1537, -1538, -1539, -1540, -1541, -1542, -1543, -1544, -1545, -1546, -1547, -1548, -1549, -1550, -1551, -1552, -1553, -1554, -1555, -1556, -1557, -1558, -1559, -1560, -1561, -1562, -1563, -1564, -1565, -1566, -1567, -1568, -1569, -1570, -1571, -1572, -1573, -1574, -1575, -1576, -1577, -1578, -1579, -1580, -1581, -1582, -1583, -1584, -1585, -1586, -1587, -1588, -1589, -1590, -1591, -1592, -1593, -1594, -1595, -1596, -1597, -1598, -1599, -1600, -1601, -1602, -1603, -1604, -1605, -1606, -1607, -1608, -1609, -1610, -1611, -1612, -1613, -1614, -1615, -1616, -1617, -1618, -1619, -1620, -1621, -1622, -1623, -1624, -1625, -1626, -1627, -1628, -1629, -1630, -1631, -1632, -1633, -1634, -1635, -1636, -1637, -1638, -1639, -1640, -1641, -1642, -1643, -1644, -1645, -1646, -1647, -1648, -1649, -1650, -1651, -1652, -1653, -1654, -1655, -1656, -1657, -1658, -1659, -1660, -1661, -1662, -1663, -1664, -1665, -1666, -1667, -1668, -1669, -1670, -1671, -1672, -1673, -1674, -1675, -1676, -1677, -1678, -1679, -1680, -1681, -1682, -1683, -1684, -1685, -1686, -1687, -1688, -1689, -1690, -1691, -1692, -1693, -1694, -1695, -1696, -1697, -1698, -1699, -1700, -1701, -1702, -1703, -1704, -1705, -1706, -1707, -1708, -1709, -1710, -1711, -1712, -1713, -1714, -1715, -1716, -1717, -1718, -1719, -1720, -1721, -1722, -1723, -1724, -1725, -1726, -1727, -1728, -1729, -1730, -1731, -1732, -1733, -1734, -1735, -1736, -1737, -1738, -1739, -1740, -1741, -1742, -1743, -1744, -1745, -1746, -1747, -1748, -1749, -1750, -1751, -1752, -1754, -1755, -1756, -1757, -1758, -1759, -1760, -1761, -1762, -1763, -1764, -1765, -1766, -1767, -1768, -1769, -1770, -1771, -1772, -1773, -1774, -1776, -1777, -1778, -1779, -1780, -1781, -1782, -1784, -1785, -1786, -1787, -1788, -1789, -1790, -1791, -1792, -1793, -1794, -1795, -1796, -1797, -1798, -1799, -1800, -1801, -1802, -1803, -1804, -1805, -1806, -1807, -1808, -1809, -1810, -1811, -1812, -1813, -1814, -1815, -1816, -1817, -1818, -1819, -1820, -1821, -1822, -1823, -1824, -1825, -1826, -1827, -1828, -1829, -1830, -1831, -1832, -1833, -1834, -1835, -1836, -1837, -1838, -1839, -1840, -1841, -1842, -1843, -1844, -1845, -1846, -1847, -1848, -1849, -1850, -1851, -1852, -1853, -1854, -1855, -1856, -1857, -1858, -1859, -1860, -1861, -1862, -1863, -1864, -1865, -1866, -1867, -1868, -1869, -1870, -1871, -1872, -1873, -1874, -1875, -1876, -1877, -1878, -1879, -1880, -1881, -1882, -1883, -1884, -1885, -1886, -1887, -1888, -1889, -1890, -1891, -1892, -1893, -1894, -1896, -1897, -1898, -1899, -1900, -1901, -1902, -1903, -1904, -1905, -1906, -1907, -1908, -1909, -1910, -1911, -1912, -1913, -1914, -1915, -1916, -1917, -1918, -1919, -1920, -1921, -1922, -1923, -1924, -1925, -1926, -1927, -1928, -1929, -1930, -1931, -1932, -1933, -1934, -1935, -1936, -1937, -1938, -1939, -1940, -1941, -1942, -1943, -1944, -1945, -1946, -1947, -1948, -1949, -1950, -1951, -1952, -1953, -1954, -1955, -1956, -1957, -1958, -1959, -1960, -1961, -1962, -1963, -1964, -1965, -1966, -1967, -1968, -1969, -1970, -1971, -1972, -1973, -1974, -1975, -1976, -1977, -1978, -1979, -1980, -1981, -1982, -1983, -1984, -1985, -1986, -1987, -1988, -1989, -1990, -1991, -1992, -1993, -1994, -1995, -1996, -1997, -1998, -1999, -2000, -2001, -2002, -2003, -2004, -2005, -2006, -2007, -2008, -2009, -2010, -2011, -2012, -2013, -2014, -2015, -2016, -2017, -2018, -2019, -2020, -2021, -2022, -2023, -2024, -2025, -2026, -2027, -2028, -2029, -2030, -2031, -2032, -2033, -2034, -2035, -2036, -2037, -2038, -2039, -2040, -2041, -2042, -2043, -2044, -2045, -2046, -2047, -2048, -2049, -2050, -2051, -2052, -2053, -2054, -2055, -2056, -2057, -2058, -2059, -2060, -2061, -2062, -2063, -2064, -2065, -2066, -2067, -2068, -2069, -2070, -2071, -2072, -2073, -2074, -2075, -2076, -2077, -2078, -2079, -2080, -2081, -2082, -2083, -2084, -2085, -2086, -2087, -2088, -2089, -2090, -2091, -2092, -2093, -2094, -2095, -2096, -2097, -2098, -2099, -2100, -2101, -2102, -2103, -2104, -2105, -2106, -2107, -2108, -2109, -2110, -2111, -2112, -2113, -2114, -2115, -2116, -2117, -2118, -2119, -2120, -2121, -2122, -2123, -2124, -2125, -2126, -2127, -2128, -2129, -2130, -2131, -2132, -2133, -2134, -2135, -2136, -2137, -2138, -2139, -2140, -2141, -2142, -2143, -2144, -2145, -2146, -2147, -2148, -2149, -2150, -2151, -2152, -2153, -2154, -2155, -2156, -2157, -2158, -2159, -2160, -2161, -2162, -2163, -2164, -2165, -2166, -2167, -2168, -2169, -2170, -2171, -2172, -2173, -2174, -2175, -2176, -2177, -2178, -2179, -2180, -2181, -2182, -2183, -2184, -2185, -2186, -2187, -2190, -2191, -2192, -2193, -2197, -2198, -2199, -2201, -2202, -2203, -2204, -2205, -2206, -2207, -2208, -2209, -2210, -2211, -2212, -2213, -2214, -2215, -2216, -2217, -2218, -2219, -2220, -2221, -2222, -2223, -2224, -2226, -2227, -2228, -2229, -2230, -2231, -2232, -2233, -2234, -2235, -2236, -2237, -2238, -2239, -2240, -2241, -2242, -2243, -2244, -2245, -2246, -2247, -2248, -2249, -2250, -2251, -2252, -2253, -2254, -2255, -2256, -2257, -2258, -2259, -2260, -2261, -2262, -2263, -2264, -2265, -2266, -2267, -2268, -2269, -2270, -2271, -2272, -2273, -2274, -2275, -2276, -2277, -2278, -2279, -2280, -2281, -2282, -2283, -2284, -2285, -2286, -2287, -2288, -2289, -2290, -2291, -2292, -2293, -2294, -2295, -2296, -2297, -2298, -2299, -2300, -2301, -2302, -2303, -2304, -2305, -2306, -2307, -2308, -2309, -2310, -2311, -2312, -2313, -2314, -2315, -2316, -2317, -2318, -2319, -2320, -2321, -2322, -2323, -2324, -2325, -2326, -2327, -2328, -2329, -2330, -2331, -2332, -2333, -2334, -2335, -2336, -2337, -2338, -2339, -2340, -2341, -2342, -2343, -2344, -2345, -2346, -2347, -2348, -2349, -2350, -2351, -2352, -2353, -2354, -2355, -2356, -2357, -2358, -2359, -2360, -2361, -2362, -2363, -2364, -2365, -2366, -2367, -2368, -2369, -2370, -2372, -2378, -2381, -2382, -2383, -2384, -2385, -2386, -2387, -2388, -2389, -2390, -2391, -2392, -2393, -2394, -2395, -2396, -2397, -2398, -2399, -2400, -2401, -2402, -2403, -2404, -2405, -2406, -2407, -2409, -2410, -2411, -2412, -2413, -2414, -2415, -2416, -2417, -2418, -2419, -2420, -2421, -2422, -2423, -2424, -2425, -2426, -2427, -2428, -2429, -2430, -2431, -2432, -2433, -2434, -2435, -2436, -2437, -2438, -2439, -2440, -2441, -2442, -2443, -2444, -2445, -2446, -2447, -2448, -2449, -2450, -2451, -2452, -2453, -2454, -2455, -2456, -2457, -2458, -2459, -2460, -2461, -2462, -2463, -2464, -2465, -2466, -2467, -2468, -2469, -2470, -2471, -2472, -2473, -2474, -2475, -2476, -2477, -2478, -2479, -2480, -2481, -2482, -2483, -2484, -2485, -2486, -2487, -2488, -2489, -2490, -2491, -2492, -2493, -2494, -2495, -2496, -2497, -2498, -2499, -2500, -2501, -2502, -2503, -2504, -2505, -2506, -2507, -2508, -2509, -2510, -2511, -2512, -2513, -2514, -2515, -2516, -2517, -2518, -2519, -2520, -2521, -2522, -2523, -2524, -2525, -2526, -2527, -2528, -2529, -2530, -2531, -2532, -2533, -2534, -2535, -2536, -2537, -2538, -2539, -2540, -2541, -2542, -2543, -2544, -2545, -2546, -2547, -2548, -2549, -2550, -2551, -2552, -2553, -2554, -2555, -2556, -2557, -2558, -2559, -2560, -2561, -2562, -2563, -2564, -2565, -2566, -2567, -2568, -2569, -2570, -2571, -2572, -2573, -2574, -2575, -2576, -2577, -2578, -2579, -2580, -2581, -2582, -2583, -2584, -2585, -2586, -2587, -2588, -2589, -2590, -2591, -2592, -2593, -2594, -2595, -2596, -2597, -2598, -2599, -2600, -2601, -2602, -2603, -2604, -2605, -2606, -2607, -2608, -2609, -2610, -2611, -2612, -2613, -2614, -2615, -2616, -2617, -2618, -2619, -2620, -2621, -2622, -2623, -2624, -2625, -2626, -2627, -2628, -2629, -2630, -2631, -2632, -2633, -2634, -2635, -2636, -2637, -2638, -2639, -2640, -2641, -2642, -2643, -2644, -2645, -2646, -2647, -2648, -2649, -2650, -2651, -2652, -2653, -2654, -2655, -2656, -2657, -2658, -2659, -2660, -2661, -2662, -2663, -2664, -2665, -2666, -2667, -2668, -2669, -2670, -2671, -2672, -2673, -2674, -2675, -2676, -2677, -2678, -2679, -2680, -2681, -2683, -2684, -2685, -2686, -2687, -2688, -2689, -2690, -2691, -2692, -2694, -2695, -2696, -2697, -2698, -2699, -2700, -2701, -2702, -2703, -2704, -2705, -2706, -2707, -2708, -2709, -2710, -2711, -2712, -2713, -2714, -2715, -2716, -2717, -2718, -2719, -2720, -2721, -2722, -2723, -2724, -2725, -2726, -2727, -2728, -2729, -2730, -2731, -2732, -2733, -2734, -2735, -2736, -2737, -2738, -2739, -2740, -2741, -2742, -2743, -2744, -2745, -2746, -2747, -2748, -2749, -2750, -2751, -2752, -2753, -2754, -2755, -2756, -2757, -2758, -2759, -2760, -2761, -2762, -2763, -2764, -2765, -2766, -2767, -2768, -2769, -2770, -2771, -2772, -2773, -2774, -2775, -2776, -2777, -2778, -2779, -2780, -2781, -2782, -2783, -2784, -2785, -2786, -2787, -2788, -2789, -2790, -2791, -2792, -2793, -2795, -2796, -2797, -2798, -2799, -2800, -2801, -2802, -2803, -2804, -2805, -2806, -2807, -2808, -2809, -2810, -2811, -2812, -2813, -2814, -2815, -2816, -2817, -2818, -2819, -2820, -2821, -2822, -2823, -2824, -2826, -2827, -2828, -2829, -2830, -2831, -2832, -2833, -2834, -2835, -2836, -2837, -2838, -2839, -2840, -2841, -2842, -2843, -2844, -2845, -2846, -2847, -2848, -2849, -2850, -2851, -2852, -2853, -2854, -2856, -2857, -2858, -2859, -2860, -2861, -2862, -2863, -2864, -2865, -2866, -2867, -2868, -2869, -2870, -2871, -2872, -2873, -2874, -2875, -2876, -2877, -2878, -2879, -2880, -2881, -2882, -2883, -2884, -2885, -2886, -2887, -2888, -2889, -2890, -2891, -2892, -2893, -2894, -2895, -2896, -2897, -2898, -2899, -2900, -2901, -2902, -2903, -2904, -2906, -2907, -2908, -2909, -2910, -2911, -2912, -2913, -2914, -2915, -2916, -2917, -2918, -2919, -2920, -2921, -2922, -2923, -2924, -2926, -2927, -2928, -2929, -2930, -2931, -2932, -2933, -2934, -2935, -2936, -2937, -2938, -2939, -2940, -2941, -2942, -2943, -2944, -2945, -2946, -2947, -2948, -2949, -2950, -2951, -2952, -2953, -2954, -2955, -2956, -2957, -2958, -2959, -2960, -2961, -2962, -2963, -2964, -2965, -2966, -2967, -2968, -2969, -2970, -2971, -2972, -2973, -2974, -2975, -2976, -2977, -2978, -2979, -2980, -2981, -2982, -2983, -2984, -2985, -2986, -2987, -2988, -2989, -2990, -2991, -2992, -2993, -2994, -2995, -2996, -2997, -2998, -3000, -3002, -3003, -3004, -3005, -3006, -3007, -3008, -3009, -3010, -3011, -3012, -3013, -3014, -3015, -3016, -3017, -3018, -3019, -3020, -3021, -3022, -3023, -3024, -3025, -3026, -3027, -3028, -3029, -3030, -3031, -3032, -3033, -3034, -3035, -3036, -3037, -3038, -3039, -3040, -3041, -3042, -3043, -3044, -3045, -3046, -3047, -3048, -3049, -3050, -3051, -3052, -3053, -3054, -3055, -3056, -3057, -3058, -3059, -3060, -3061, -3062, -3063, -3064, -3065, -3066, -3067, -3068, -3069, -3070, -3072, -3073, -3074, -3075, -3076, -3077, -3078, -3079, -3080, -3081, -3082, -3083, -3084, -3085, -3086, -3087, -3088, -3089, -3090, -3091, -3093, -3094, -3095, -3096, -3098, -3099, -3100, -3101, -3102, -3103, -3104, -3105, -3106, -3107, -3108, -3109, -3110, -3111, -3112, -3113, -3114, -3115, -3116, -3117, -3118, -3119, -3120, -3122, -3123, -3124, -3125, -3127, -3128, -3129, -3130, -3131, -3132, -3133, -3134, -3135, -3136, -3137, -3138, -3139, -3140, -3141, -3142, -3143, -3144, -3145, -3146, -3147, -3148, -3149, -3150, -3151, -3152, -3153, -3154, -3155, -3156, -3157, -3158, -3159, -3160, -3161, -3162, -3163, -3164, -3165, -3166, -3167, -3168, -3169, -3170, -3171, -3172, -3173, -3174, -3175, -3176, -3177, -3178, -3179, -3180, -3181, -3182, -3183, -3184, -3185, -3186, -3187, -3188, -3189, -3190, -3191, -3192, -3193, -3194, -3195, -3196, -3197, -3198, -3199, -3200, -3201, -3202, -3203, -3204, -3205, -3206, -3207, -3208, -3209, -3210, -3211, -3212, -3213, -3214, -3215, -3216, -3217, -3218, -3219, -3220, -3221, -3222, -3223, -3224, -3225, -3226, -3227, -3228, -3229, -3230, -3231, -3232, -3233, -3234, -3235, -3236, -3237, -3238, -3239, -3240, -3241, -3242, -3243, -3244, -3245, -3246, -3247, -3248, -3249, -3250, -3251, -3252, -3253, -3254, -3255, -3256, -3257, -3258, -3259, -3260, -3261, -3262, -3263, -3264, -3265, -3266, -3267, -3268, -3269, -3270, -3271, -3272, -3273, -3274, -3275, -3276, -3277, -3278, -3279, -3280, -3281, -3282, -3283, -3284, -3285, -3286, -3287, -3288, -3289, -3290, -3291, -3292, -3293, -3294, -3295, -3296, -3297, -3298, -3299, -3301, -3302, -3303, -3304, -3305, -3306, -3307, -3308, -3309, -3310, -3311, -3312, -3313, -3314, -3315, -3316, -3317, -3318, -3319, -3320, -3321, -3326, -3327, -3328, -3329, -3330, -3331, -3332, -3333, -3334, -3335, -3336, -3337, -3338, -3339, -3340, -3341, -3342, -3343, -3344, -3345, -3346, -3347, -3348, -3349, -3350, -3351, -3352, -3353, -3354, -3355, -3356, -3357, -3358, -3359, -3360, -3361, -3362, -3363, -3364, -3365, -3366, -3372, -3373, -3374, -3375, -3376, -3377, -3378, -3379, -3380, -3381, -3382, -3383, -3384, -3385, -3386, -3387, -3388, -3389, -3390, -3391, -3392, -3393, -3394, -3395, -3396, -3397, -3398, -3399, -3400, -3401, -3402, -3405, -3406, -3407, -3408, -3409, -3410, -3411, -3412, -3413, -3414, -3415, -3416, -3417, -3418, -3419, -3420, -3421, -3422, -3423, -3424, -3425, -3426, -3427, -3428, -3429, -3430, -3431, -3432, -3433, -3434, -3435, -3436, -3437, -3438, -3439, -3440, -3441, -3442, -3443, -3444, -3445, -3446, -3447, -3448, -3449, -3450, -3451, -3452, -3453, -3454, -3455, -3456, -3457, -3458, -3459, -3460, -3461, -3462, -3463, -3464, -3465, -3466, -3467, -3468, -3469, -3470, -3471, -3472, -3473, -3474, -3475, -3476, -3477, -3478, -3479, -3480, -3481, -3482, -3483, -3484, -3485, -3486, -3487, -3488, -3489, -3490, -3491, -3492, -3493, -3494, -3495, -3496, -3497, -3498, -3499, -3500, -3501, -3502, -3503, -3504, -3505, -3506, -3507, -3508, -3509, -3510, -3511, -3512, -3513, -3514, -3515, -3516, -3517, -3518, -3519, -3520, -3521, -3522, -3523, -3524, -3525, -3526, -3527, -3528, -3529, -3530, -3531, -3532, -3533, -3534, -3535, -3536, -3537, -3538, -3539, -3540, -3541, -3542, -3543, -3544, -3545, -3547, -3548, -3549, -3550, -3551, -3552, -3553, -3554, -3555, -3556, -3557, -3558, -3559, -3560, -3561, -3562, -3563, -3564, -3567, -3568, -3569, -3570, -3571, -3572, -3573, -3574, -3575, -3576, -3577, -3578, -3579, -3580, -3581, -3582, -3583, -3584, -3585, -3586, -3587, -3588, -3589, -3590, -3591, -3592, -3593, -3594, -3595, -3596, -3597, -3598, -3599, -3600, -3601, -3602, -3603, -3604, -3605, -3606, -3607, -3608, -3609, -3610, -3611, -3612, -3613, -3614, -3615, -3616, -3617, -3618, -3619, -3620, -3621, -3622, -3623, -3624, -3625, -3626, -3627, -3628, -3629, -3630, -3631, -3632, -3633, -3634, -3635, -3636, -3637, -3638, -3639, -3640, -3641, -3642, -3643, -3644, -3645, -3646, -3647, -3648, -3649, -3650, -3651, -3652, -3653, -3654, -3655, -3656, -3657, -3658, -3659, -3660, -3661, -3662, -3663, -3664, -3665, -3666, -3667, -3668, -3669, -3670, -3671, -3672, -3673, -3674, -3675, -3676, -3677, -3678, -3679, -3680, -3681, -3682, -3683, -3684, -3685, -3686, -3687, -3688, -3689, -3690, -3691, -3692, -3695, -3696, -3697, -3698, -3699, -3700, -3701, -3702, -3703, -3704, -3705, -3706, -3707, -3708, -3709, -3710, -3711, -3712, -3713, -3714, -3715, -3716, -3717, -3718, -3719, -3720, -3721, -3722, -3723, -3724, -3725, -3726, -3727, -3728, -3729, -3730, -3731, -3732, -3733, -3734, -3735, -3736, -3738, -3739, -3740, -3741, -3742, -3743, -3744, -3745, -3746, -3747, -3748, -3749, -3750, -3751, -3752, -3753, -3754, -3755, -3756, -3757, -3758, -3759, -3760, -3761, -3762, -3763, -3764, -3765, -3767, -3768, -3769, -3770, -3771, -3772, -3773, -3774, -3775, -3776, -3777, -3778, -3779, -3780, -3781, -3782, -3783, -3784, -3785, -3786, -3787, -3788, -3789, -3790, -3791, -3792, -3793, -3794, -3795, -3796, -3797, -3798, -3799, -3800, -3801, -3802, -3803, -3804, -3805, -3806, -3807, -3808, -3809, -3810, -3811, -3812, -3813, -3814, -3815, -3816, -3817, -3818, -3819, -3820, -3821, -3822, -3823, -3824, -3825, -3826, -3827, -3828, -3829, -3830, -3831, -3832, -3833, -3834, -3835, -3836, -3837, -3838, -3839, -3840, -3842, -3843, -3844, -3845, -3846, -3847, -3848, -3849, -3850, -3851, -3852, -3853, -3854, -3855, -3856, -3857, -3858, -3859, -3860, -3861, -3862, -3863, -3865, -3866, -3867, -3869, -3870, -3871, -3872, -3873, -3874, -3875, -3876, -3877, -3878, -3879, -3880, -3881, -3882, -3883, -3884, -3885, -3886, -3887, -3888, -3889, -3890, -3891, -3892, -3893, -3894, -3895, -3896, -3897, -3898, -3899, -3900, -3901, -3902, -3903, -3904, -3905, -3906, -3907, -3908, -3909, -3910, -3911, -3912, -3913, -3914, -3915, -3916, -3917, -3918, -3919, -3920, -3921, -3922, -3923, -3924, -3925, -3926, -3927, -3928, -3929, -3930, -3931, -3932, -3933, -3934, -3935, -3936, -3937, -3938, -3939, -3940, -3941, -3942, -3943, -3944, -3945, -3946, -3947, -3948, -3949, -3950, -3951, -3952, -3953, -3954, -3955, -3956, -3957, -3958, -3959, -3960, -3961, -3962, -3963, -3964, -3965, -3966, -3967, -3968, -3969, -3970, -3971, -3972, -3973, -3974, -3975, -3976, -3977, -3978, -3979, -3981, -3982, -3983, -3984, -3985, -3986, -3987, -3988, -3989, -3990, -3991, -3992, -3993, -3995, -3996, -3997, -3998, -3999, -4000, -4001, -4002, -4003, -4004, -4005, -4006, -4007, -4008, -4009, -4010, -4011, -4012, -4013, -4014, -4015, -4016, -4017, -4018, -4019, -4020, -4021, -4022, -4023, -4024, -4025, -4026, -4027, -4028, -4029, -4030, -4031, -4032, -4033, -4034, -4035, -4036, -4037, -4038, -4039, -4040, -4041, -4042, -4043, -4044, -4045, -4046, -4047, -4049, -4050, -4051, -4052, -4053, -4054, -4055, -4056, -4057, -4058, -4059, -4060, -4061, -4062, -4063, -4064, -4065, -4066, -4067, -4068, -4069, -4070, -4071, -4072, -4073, -4074, -4075, -4076, -4077, -4079, -4080, -4081, -4082, -4083, -4084, -4086, -4089, -4090, -4091, -4092, -4093, -4094, -4095, -4096, -4097, -4098, -4099, -4100, -4101, -4102, -4103, -4104, -4105, -4106, -4107, -4108, -4109, -4110, -4111, -4112, -4113, -4114, -4115, -4116, -4117, -4118, -4119, -4121, -4122, -4123, -4124, -4125, -4126, -4127, -4128, -4129, -4130, -4131, -4132, -4133, -4134, -4135, -4136, -4137, -4138, -4139, -4140, -4141, -4142, -4143, -4145, -4146, -4147, -4148, -4149, -4150, -4151, -4152, -4153, -4154, -4155, -4156, -4157, -4158, -4159, -4160, -4161, -4162, -4163, -4164, -4165, -4166, -4167, -4168, -4169, -4172, -4173, -4174, -4177, -4178, -4179, -4180, -4181, -4182, -4183, -4184, -4185, -4188, -4191, -4192, -4195, -4197, -4199, -4300, -4301, -4302, -4303, -4304, -4305, -4306, -4307, -4308, -4309, -4310, -4319, -4320, -4321, -4322, -4323, -4325, -4326, -4327, -4328, -4333, -4340, -4341, -4342, -4343, -4344, -4345, -4346, -4347, -4348, -4349, -4350, -4351, -4352, -4353, -4354, -4355, -4356, -4357, -4358, -4359, -4361, -4362, -4366, -4368, -4369, -4370, -4371, -4372, -4373, -4375, -4376, -4377, -4378, -4379, -4389, -4390, -4394, -4395, -4400, -4401, -4402, -4403, -4404, -4405, -4406, -4412, -4413, -4416, -4418, -4420, -4425, -4426, -4430, -4432, -4441, -4442, -4443, -4444, -4445, -4446, -4447, -4448, -4449, -4450, -4451, -4452, -4453, -4454, -4455, -4456, -4457, -4458, -4484, -4486, -4488, -4500, -4534, -4535, -4536, -4537, -4538, -4545, -4546, -4547, -4548, -4549, -4550, -4551, -4552, -4554, -4555, -4556, -4557, -4558, -4559, -4566, -4567, -4568, -4569, -4591, -4592, -4593, -4594, -4595, -4596, -4597, -4598, -4599, -4600, -4601, -4621, -4646, -4658, -4659, -4660, -4661, -4662, -4663, -4664, -4665, -4666, -4667, -4668, -4669, -4670, -4671, -4672, -4673, -4674, -4675, -4676, -4677, -4678, -4679, -4680, -4681, -4682, -4683, -4684, -4685, -4686, -4687, -4688, -4689, -4690, -4691, -4692, -4700, -4701, -4702, -4711, -4725, -4726, -4727, -4728, -4729, -4730, -4732, -4737, -4738, -4739, -4740, -4741, -4742, -4743, -4744, -4745, -4746, -4747, -4749, -4750, -4751, -4752, -4753, -4754, -4755, -4784, -4785, -4789, -4790, -4791, -4792, -4800, -4801, -4802, -4803, -4804, -4827, -4837, -4838, -4839, -4840, -4841, -4842, -4843, -4844, -4845, -4846, -4847, -4848, -4849, -4850, -4851, -4867, -4868, -4869, -4870, -4871, -4876, -4877, -4878, -4881, -4882, -4884, -4885, -4894, -4899, -4900, -4914, -4936, -4937, -4940, -4941, -4942, -4949, -4950, -4951, -4952, -4969, -4970, -4980, -4986, -4987, -4988, -4989, -4990, -4991, -4999, -5000, -5001, -5002, -5003, -5004, -5005, -5006, -5007, -5008, -5009, -5010, -5011, -5012, -5013, -5014, -5020, -5021, -5022, -5023, -5024, -5025, -5026, -5027, -5029, -5031, -5042, -5043, -5044, -5046, -5047, -5049, -5050, -5051, -5052, -5053, -5055, -5056, -5057, -5058, -5059, -5060, -5061, -5062, -5064, -5065, -5066, -5067, -5069, -5070, -5071, -5072, -5073, -5074, -5078, -5079, -5080, -5081, -5082, -5083, -5084, -5085, -5092, -5093, -5094, -5099, -5100, -5101, -5102, -5104, -5105, -5111, -5112, -5116, -5120, -5133, -5136, -5137, -5145, -5150, -5151, -5152, -5154, -5155, -5164, -5165, -5166, -5167, -5168, -5190, -5191, -5192, -5193, -5200, -5201, -5202, -5203, -5223, -5224, -5225, -5226, -5227, -5234, -5235, -5236, -5237, -5245, -5246, -5247, -5248, -5249, -5250, -5251, -5252, -5264, -5265, -5270, -5271, -5272, -5282, -5298, -5299, -5300, -5301, -5302, -5303, -5304, -5305, -5306, -5307, -5308, -5309, -5310, -5312, -5313, -5314, -5315, -5343, -5344, -5349, -5350, -5351, -5352, -5353, -5354, -5355, -5356, -5357, -5358, -5359, -5360, -5361, -5362, -5363, -5364, -5397, -5398, -5399, -5400, -5401, -5402, -5403, -5404, -5405, -5406, -5407, -5408, -5409, -5410, -5411, -5412, -5413, -5414, -5415, -5416, -5417, -5418, -5419, -5420, -5421, -5422, -5423, -5424, -5425, -5426, -5427, -5428, -5429, -5430, -5431, -5432, -5433, -5434, -5435, -5436, -5437, -5443, -5450, -5453, -5454, -5455, -5456, -5461, -5462, -5463, -5464, -5465, -5474, -5500, -5501, -5502, -5503, -5504, -5505, -5506, -5540, -5553, -5554, -5555, -5556, -5567, -5568, -5569, -5573, -5580, -5581, -5582, -5583, -5584, -5585, -5597, -5598, -5599, -5600, -5601, -5602, -5603, -5604, -5605, -5627, -5628, -5629, -5630, -5631, -5632, -5633, -5634, -5670, -5671, -5672, -5673, -5674, -5675, -5676, -5677, -5678, -5679, -5680, -5681, -5682, -5683, -5684, -5687, -5688, -5689, -5713, -5714, -5715, -5716, -5717, -5718, -5719, -5720, -5721, -5722, -5723, -5724, -5728, -5729, -5730, -5741, -5742, -5743, -5744, -5745, -5746, -5747, -5748, -5750, -5755, -5757, -5766, -5767, -5768, -5769, -5770, -5771, -5777, -5781, -5782, -5783, -5784, -5785, -5786, -5787, -5793, -5794, -5813, -5814, -5859, -5863, -5900, -5903, -5904, -5905, -5906, -5907, -5908, -5909, -5910, -5911, -5912, -5913, -5963, -5968, -5969, -5984, -5985, -5986, -5987, -5988, -5989, -5990, -5991, -5992, -5999, -6000, -6064, -6065, -6066, -6069, -6070, -6071, -6072, -6073, -6074, -6080, -6081, -6082, -6083, -6085, -6086, -6087, -6088, -6100, -6101, -6102, -6103, -6104, -6105, -6106, -6107, -6108, -6109, -6110, -6111, -6112, -6118, -6122, -6123, -6124, -6133, -6140, -6141, -6142, -6143, -6144, -6145, -6146, -6147, -6148, -6149, -6160, -6161, -6162, -6163, -6200, -6201, -6209, -6222, -6241, -6242, -6243, -6244, -6251, -6252, -6253, -6268, -6269, -6300, -6301, -6306, -6315, -6316, -6317, -6320, -6321, -6322, -6324, -6343, -6346, -6347, -6350, -6355, -6360, -6363, -6370, -6382, -6389, -6390, -6417, -6419, -6420, -6421, -6443, -6444, -6445, -6446, -6455, -6456, -6464, -6471, -6480, -6481, -6482, -6483, -6484, -6485, -6486, -6487, -6488, -6489, -6500, -6501, -6502, -6503, -6505, -6506, -6507, -6508, -6509, -6510, -6511, -6514, -6515, -6543, -6544, -6547, -6548, -6549, -6550, -6551, -6558, -6566, -6568, -6579, -6580, -6581, -6582, -6583, -6619, -6620, -6621, -6622, -6623, -6626, -6627, -6628, -6629, -6633, -6634, -6635, -6636, -6653, -6657, -6670, -6671, -6672, -6673, -6678, -6679, -6689, -6696, -6699, -6701, -6702, -6703, -6714, -6715, -6767, -6768, -6769, -6770, -6771, -6784, -6785, -6786, -6787, -6788, -6790, -6791, -6801, -6831, -6841, -6842, -6850, -6868, -6888, -6924, -6935, -6936, -6946, -6951, -6961, -6962, -6963, -6964, -6965, -6966, -6969, -6980, -6997, -6998, -6999, -7000, -7001, -7002, -7003, -7004, -7005, -7006, -7007, -7008, -7009, -7010, -7011, -7012, -7013, -7014, -7015, -7016, -7017, -7019, -7020, -7021, -7022, -7023, -7024, -7025, -7030, -7040, -7070, -7071, -7072, -7080, -7088, -7095, -7099, -7100, -7101, -7107, -7121, -7128, -7129, -7161, -7162, -7163, -7164, -7165, -7166, -7169, -7170, -7171, -7174, -7181, -7200, -7201, -7227, -7235, -7244, -7262, -7272, -7273, -7274, -7275, -7276, -7277, -7278, -7279, -7280, -7281, -7282, -7365, -7391, -7392, -7393, -7394, -7395, -7397, -7400, -7401, -7402, -7410, -7411, -7420, -7421, -7426, -7427, -7428, -7429, -7430, -7431, -7437, -7443, -7473, -7491, -7500, -7501, -7510, -7511, -7542, -7543, -7544, -7545, -7546, -7547, -7548, -7549, -7550, -7560, -7566, -7570, -7574, -7588, -7606, -7624, -7627, -7628, -7629, -7633, -7648, -7663, -7674, -7675, -7676, -7677, -7680, -7689, -7697, -7707, -7708, -7720, -7724, -7725, -7726, -7727, -7728, -7734, -7738, -7741, -7743, -7744, -7747, -7777, -7778, -7779, -7781, -7784, -7786, -7787, -7789, -7794, -7797, -7798, -7799, -7800, -7801, -7802, -7810, -7845, -7846, -7872, -7880, -7887, -7900, -7901, -7902, -7903, -7913, -7932, -7933, -7962, -7967, -7979, -7980, -7982, -7998, -7999, -8000, -8001, -8002, -8003, -8005, -8006, -8007, -8008, -8017, -8019, -8020, -8021, -8022, -8023, -8025, -8026, -8027, -8032, -8033, -8034, -8040, -8041, -8052, -8053, -8054, -8055, -8056, -8057, -8058, -8059, -8060, -8074, -8080, -8081, -8082, -8083, -8086, -8087, -8088, -8097, -8100, -8111, -8115, -8116, -8118, -8121, -8122, -8128, -8129, -8130, -8131, -8132, -8148, -8149, -8160, -8161, -8182, -8184, -8192, -8194, -8195, -8199, -8200, -8201, -8202, -8204, -8205, -8206, -8207, -8208, -8211, -8230, -8231, -8232, -8243, -8266, -8276, -8280, -8282, -8292, -8294, -8300, -8301, -8320, -8321, -8322, -8351, -8376, -8377, -8378, -8379, -8380, -8383, -8384, -8400, -8401, -8402, -8403, -8416, -8417, -8433, -8442, -8443, -8444, -8445, -8450, -8472, -8473, -8474, -8500, -8501, -8503, -8554, -8555, -8567, -8600, -8609, -8610, -8611, -8612, -8613, -8614, -8675, -8686, -8732, -8733, -8763, -8764, -8765, -8766, -8770, -8786, -8787, -8793, -8800, -8804, -8805, -8807, -8808, -8809, -8873, -8880, -8883, -8888, -8889, -8890, -8891, -8892, -8893, -8894, -8899, -8900, -8901, -8910, -8911, -8912, -8913, -8954, -8980, -8981, -8989, -8990, -8991, -8999, -9000, -9001, -9002, -9006, -9007, -9009, -9011, -9020, -9021, -9022, -9023, -9024, -9025, -9026, -9060, -9080, -9081, -9084, -9085, -9086, -9087, -9088, -9089, -9090, -9091, -9092, -9100, -9101, -9102, -9103, -9104, -9105, -9106, -9111, -9119, -9131, -9160, -9161, -9162, -9163, -9164, -9191, -9200, -9201, -9202, -9203, -9204, -9205, -9206, -9207, -9208, -9209, -9210, -9211, -9212, -9213, -9214, -9215, -9216, -9217, -9222, -9255, -9277, -9278, -9279, -9280, -9281, -9282, -9283, -9284, -9285, -9286, -9287, -9292, -9293, -9294, -9295, -9300, -9318, -9321, -9343, -9344, -9346, -9374, -9380, -9396, -9397, -9400, -9401, -9402, -9418, -9443, -9444, -9450, -9500, -9522, -9535, -9536, -9555, -9592, -9593, -9594, -9595, -9596, -9597, -9598, -9599, -9600, -9612, -9618, -9628, -9629, -9632, -9667, -9668, -9694, -9695, -9700, -9747, -9750, -9753, -9762, -9800, -9801, -9802, -9875, -9878, -9888, -9889, -9898, -9899, -9900, -9901, -9903, -9909, -9911, -9950, -9951, -9952, -9953, -9955, -9956, -9966, -9987, -9990, -9991, -9992, -9993, -9994, -9995, -9996, -9997, -9998, -9999, -10000, -10001, -10002, -10003, -10007, -10008, -10009, -10023, -10050, -10051, -10080, -10081, -10100, -10101, -10102, -10103, -10104, -10107, -10110, -10111, -10113, -10114, -10115, -10116, -10117, -10128, -10160, -10161, -10162, -10200, -10201, -10252, -10253, -10260, -10288, -10439, -10500, -10540, -10541, -10542, -10543, -10544, -10800, -10805, -10810, -10860, -10880, -10990, -11000, -11001, -11095, -11106, -11108, -11111, -11112, -11161, -11162, -11163, -11164, -11165, -11171, -11201, -11208, -11211, -11319, -11320, -11321, -11367, -11371, -11430, -11600, -11720, -11723, -11751, -11796, -11876, -11877, -11967, -12000, -12001, -12002, -12003, -12004, -12005, -12006, -12007, -12008, -12009, -12012, -12013, -12109, -12121, -12168, -12172, -12300, -12321, -12322, -12345, -12753, -13160, -13216, -13217, -13218, -13223, -13224, -13400, -13720, -13721, -13722, -13724, -13782, -13783, -13785, -13786, -13818, -13819, -13820, -13821, -13822, -13894, -13929, -14000, -14001, -14002, -14033, -14034, -14141, -14142, -14145, -14149, -14154, -14250, -14414, -14936, -14937, -15000, -15118, -15345, -15363, -15555, -15660, -15740, -15998, -16003, -16161, -16309, -16310, -16311, -16360, -16361, -16367, -16368, -16384, -16666, -16900, -16950, -16991, -16992, -16993, -16994, -16995, -17007, -17185, -17219, -17220, -17221, -17222, -17224, -17225, -17234, -17235, -17500, -17729, -17754, -17755, -17756, -18000, -18181, -18182, -18183, -18184, -18185, -18186, -18187, -18241, -18262, -18463, -18516, -18634, -18635, -18668, -18769, -18881, -18888, -19000, -19007, -19191, -19194, -19220, -19283, -19315, -19398, -19410, -19411, -19412, -19539, -19540, -19541, -19788, -19999, -20000, -20001, -20002, -20003, -20005, -20012, -20014, -20034, -20046, -20048, -20049, -20167, -20202, -20222, -20480, -20670, -20999, -21000, -21554, -21590, -21800, -21845, -21846, -21847, -21848, -21849, -22000, -22001, -22002, -22003, -22004, -22005, -22273, -22305, -22333, -22335, -22343, -22347, -22350, -22555, -22763, -22800, -22951, -23000, -23001, -23002, -23003, -23004, -23005, -23272, -23294, -23333, -23400, -23401, -23402, -24000, -24001, -24002, -24003, -24004, -24005, -24006, -24242, -24249, -24321, -24322, -24386, -24465, -24554, -24577, -24676, -24677, -24678, -24680, -24850, -24922, -25000, -25001, -25002, -25003, -25004, -25005, -25006, -25007, -25008, -25009, -25793, -25900, -25901, -25902, -25903, -25954, -25955, -26000, -26133, -26208, -26260, -26261, -26262, -26263, -26486, -26487, -26489, -27345, -27442, -27504, -27782, -27999, -28000, -28119, -28200, -28240, -29167, -30001, -30002, -30003, -30004, -30260, -30832, -30999, -31016, -31029, -31337, -31416, -31457, -31620, -31765, -31948, -31949, -32034, -32249, -32483, -32635, -32636, -32767, -32768, -32769, -32770, -32771, -32772, -32773, -32774, -32775, -32776, -32777, -32801, -32896, -33123, -33331, -33334, -33434, -33435, -33656, -34249, -34378, -34379, -34567, -34962, -34963, -34964, -34980, -35001, -35004, -35100, -35355, -36001, -36411, -36865, -37475, -37654, -38002, -38201, -38202, -38203, -39681, -40000, -40023, -40841, -40842, -40843, -40853, -41111, -41230, -41794, -41795, -42508, -42509, -42510, -43000, -43188, -43189, -43190, -43210, -43438, -43439, -43440, -43441, -44321, -44322, -44544, -44553, -44600, -44818, -44900, -45000, -45054, -45514, -45678, -45825, -45966, -46999, -47000, -47100, -47557, -47624, -47806, -47808, -47809, -48000, -48001, -48002, -48003, -48128, -48129, -48556, -48619, -48653, -49001, diff --git a/crates/libunbound-sys/unbound/util/locks.c b/crates/libunbound-sys/unbound/util/locks.c deleted file mode 100644 index b65a02bd..00000000 --- a/crates/libunbound-sys/unbound/util/locks.c +++ /dev/null @@ -1,264 +0,0 @@ -/** - * util/locks.c - unbound locking primitives - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * Implementation of locking and threading support. - * A place for locking debug code since most locking functions are macros. - */ - -#include "config.h" -#include "util/locks.h" -#include -#ifdef HAVE_SYS_WAIT_H -#include -#endif - -/** block all signals, masks them away. */ -void -ub_thread_blocksigs(void) -{ -#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK) -# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) - int err; -# endif - sigset_t sigset; - sigfillset(&sigset); -#ifdef HAVE_PTHREAD - if((err=pthread_sigmask(SIG_SETMASK, &sigset, NULL))) - fatal_exit("pthread_sigmask: %s", strerror(err)); -#else -# ifdef HAVE_SOLARIS_THREADS - if((err=thr_sigsetmask(SIG_SETMASK, &sigset, NULL))) - fatal_exit("thr_sigsetmask: %s", strerror(err)); -# else - /* have nothing, do single process signal mask */ - if(sigprocmask(SIG_SETMASK, &sigset, NULL)) - fatal_exit("sigprocmask: %s", strerror(errno)); -# endif /* HAVE_SOLARIS_THREADS */ -#endif /* HAVE_PTHREAD */ -#endif /* have signal stuff */ -} - -/** unblock one signal, so we can catch it */ -void ub_thread_sig_unblock(int sig) -{ -#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK) -# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) - int err; -# endif - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, sig); -#ifdef HAVE_PTHREAD - if((err=pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))) - fatal_exit("pthread_sigmask: %s", strerror(err)); -#else -# ifdef HAVE_SOLARIS_THREADS - if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL))) - fatal_exit("thr_sigsetmask: %s", strerror(err)); -# else - /* have nothing, do single thread case */ - if(sigprocmask(SIG_UNBLOCK, &sigset, NULL)) - fatal_exit("sigprocmask: %s", strerror(errno)); -# endif /* HAVE_SOLARIS_THREADS */ -#endif /* HAVE_PTHREAD */ -#else - (void)sig; -#endif /* have signal stuff */ -} - -#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) -/** - * No threading available: fork a new process. - * This means no shared data structure, and no locking. - * Only the main thread ever returns. Exits on errors. - * @param thr: the location where to store the thread-id. - * @param func: function body of the thread. Return value of func is lost. - * @param arg: user argument to func. - */ -void -ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg) -{ - pid_t pid = fork(); - switch(pid) { - default: /* main */ - *thr = (ub_thread_type)pid; - return; - case 0: /* child */ - *thr = (ub_thread_type)getpid(); - (void)(*func)(arg); - exit(0); - case -1: /* error */ - fatal_exit("could not fork: %s", strerror(errno)); - } -} - -/** - * There is no threading. Wait for a process to terminate. - * Note that ub_thread_type is defined as pid_t. - * @param thread: the process id to wait for. - */ -void ub_thr_fork_wait(ub_thread_type thread) -{ - int status = 0; - if(waitpid((pid_t)thread, &status, 0) == -1) - log_err("waitpid(%d): %s", (int)thread, strerror(errno)); - if(status != 0) - log_warn("process %d abnormal exit with status %d", - (int)thread, status); -} -#endif /* !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) */ - -#ifdef HAVE_SOLARIS_THREADS -void* ub_thread_key_get(ub_thread_key_type key) -{ - void* ret=NULL; - LOCKRET(thr_getspecific(key, &ret)); - return ret; -} -#endif - -#ifdef HAVE_WINDOWS_THREADS -/** log a windows GetLastError message */ -static void log_win_err(const char* str, DWORD err) -{ - LPTSTR buf; - if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, err, 0, (LPTSTR)&buf, 0, NULL) == 0) { - /* could not format error message */ - log_err("%s, GetLastError=%d", str, (int)err); - return; - } - log_err("%s, (err=%d): %s", str, (int)err, buf); - LocalFree(buf); -} - -void lock_basic_init(lock_basic_type* lock) -{ - /* implement own lock, because windows HANDLE as Mutex usage - * uses too many handles and would bog down the whole system. */ - (void)InterlockedExchange(lock, 0); -} - -void lock_basic_destroy(lock_basic_type* lock) -{ - (void)InterlockedExchange(lock, 0); -} - -void lock_basic_lock(lock_basic_type* lock) -{ - LONG wait = 1; /* wait 1 msec at first */ - - while(InterlockedExchange(lock, 1)) { - /* if the old value was 1 then if was already locked */ - Sleep(wait); /* wait with sleep */ - wait *= 2; /* exponential backoff for waiting */ - } - /* the old value was 0, but we inserted 1, we locked it! */ -} - -void lock_basic_unlock(lock_basic_type* lock) -{ - /* unlock it by inserting the value of 0. xchg for cache coherency. */ - (void)InterlockedExchange(lock, 0); -} - -void ub_thread_key_create(ub_thread_key_type* key, void* f) -{ - *key = TlsAlloc(); - if(*key == TLS_OUT_OF_INDEXES) { - *key = 0; - log_win_err("TlsAlloc Failed(OUT_OF_INDEXES)", GetLastError()); - } - else ub_thread_key_set(*key, f); -} - -void ub_thread_key_set(ub_thread_key_type key, void* v) -{ - if(!TlsSetValue(key, v)) { - log_win_err("TlsSetValue failed", GetLastError()); - } -} - -void* ub_thread_key_get(ub_thread_key_type key) -{ - void* ret = (void*)TlsGetValue(key); - if(ret == NULL && GetLastError() != ERROR_SUCCESS) { - log_win_err("TlsGetValue failed", GetLastError()); - } - return ret; -} - -void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg) -{ -#ifndef HAVE__BEGINTHREADEX - *thr = CreateThread(NULL, /* default security (no inherit handle) */ - 0, /* default stack size */ - (LPTHREAD_START_ROUTINE)func, arg, - 0, /* default flags, run immediately */ - NULL); /* do not store thread identifier anywhere */ -#else - /* the beginthreadex routine setups for the C lib; aligns stack */ - *thr=(ub_thread_type)_beginthreadex(NULL, 0, (void*)func, arg, 0, NULL); -#endif - if(*thr == NULL) { - log_win_err("CreateThread failed", GetLastError()); - fatal_exit("thread create failed"); - } -} - -ub_thread_type ub_thread_self(void) -{ - return GetCurrentThread(); -} - -void ub_thread_join(ub_thread_type thr) -{ - DWORD ret = WaitForSingleObject(thr, INFINITE); - if(ret == WAIT_FAILED) { - log_win_err("WaitForSingleObject(Thread):WAIT_FAILED", - GetLastError()); - } else if(ret == WAIT_TIMEOUT) { - log_win_err("WaitForSingleObject(Thread):WAIT_TIMEOUT", - GetLastError()); - } - /* and close the handle to the thread */ - if(!CloseHandle(thr)) { - log_win_err("CloseHandle(Thread) failed", GetLastError()); - } -} -#endif /* HAVE_WINDOWS_THREADS */ diff --git a/crates/libunbound-sys/unbound/util/locks.h b/crates/libunbound-sys/unbound/util/locks.h deleted file mode 100644 index d86ee492..00000000 --- a/crates/libunbound-sys/unbound/util/locks.h +++ /dev/null @@ -1,313 +0,0 @@ -/** - * util/locks.h - unbound locking primitives - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UTIL_LOCKS_H -#define UTIL_LOCKS_H - -/** - * \file - * Locking primitives. - * If pthreads is available, these are used. - * If no locking exists, they do nothing. - * - * The idea is to have different sorts of locks for different tasks. - * This allows the locking code to be ported more easily. - * - * Types of locks that are supported. - * o lock_rw: lock that has many readers and one writer (to a data entry). - * o lock_basic: simple mutex. Blocking, one person has access only. - * This lock is meant for non performance sensitive uses. - * o lock_quick: speed lock. For performance sensitive locking of critical - * sections. Could be implemented by a mutex or a spinlock. - * - * Also thread creation and deletion functions are defined here. - */ - -/* if you define your own LOCKRET before including locks.h, you can get most - * locking functions without the dependency on log_err. */ -#ifndef LOCKRET -#include "util/log.h" -/** - * The following macro is used to check the return value of the - * pthread calls. They return 0 on success and an errno on error. - * The errno is logged to the logfile with a descriptive comment. - */ -#define LOCKRET(func) do {\ - int lockret_err; \ - if( (lockret_err=(func)) != 0) \ - log_err("%s at %d could not " #func ": %s", \ - __FILE__, __LINE__, strerror(lockret_err)); \ - } while(0) -#endif - -/** DEBUG: use thread debug whenever possible */ -#if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_SPINLOCK_T) && defined(ENABLE_LOCK_CHECKS) -# define USE_THREAD_DEBUG -#endif - -#ifdef USE_THREAD_DEBUG -/******************* THREAD DEBUG ************************/ -/* (some) checking; to detect races and deadlocks. */ -#include "testcode/checklocks.h" - -#else /* USE_THREAD_DEBUG */ -#define lock_protect(lock, area, size) /* nop */ -#define lock_unprotect(lock, area) /* nop */ -#define lock_get_mem(lock) (0) /* nothing */ -#define checklock_start() /* nop */ -#define checklock_stop() /* nop */ - -#ifdef HAVE_PTHREAD -#include - -/******************* PTHREAD ************************/ - -/** use pthread mutex for basic lock */ -typedef pthread_mutex_t lock_basic_type; -/** small front for pthread init func, NULL is default attrs. */ -#define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) -#define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) -#define lock_basic_lock(lock) LOCKRET(pthread_mutex_lock(lock)) -#define lock_basic_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) - -#ifndef HAVE_PTHREAD_RWLOCK_T -/** in case rwlocks are not supported, use a mutex. */ -typedef pthread_mutex_t lock_rw_type; -#define lock_rw_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) -#define lock_rw_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) -#define lock_rw_rdlock(lock) LOCKRET(pthread_mutex_lock(lock)) -#define lock_rw_wrlock(lock) LOCKRET(pthread_mutex_lock(lock)) -#define lock_rw_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) -#else /* HAVE_PTHREAD_RWLOCK_T */ -/** we use the pthread rwlock */ -typedef pthread_rwlock_t lock_rw_type; -/** small front for pthread init func, NULL is default attrs. */ -#define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL)) -#define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock)) -#define lock_rw_rdlock(lock) LOCKRET(pthread_rwlock_rdlock(lock)) -#define lock_rw_wrlock(lock) LOCKRET(pthread_rwlock_wrlock(lock)) -#define lock_rw_unlock(lock) LOCKRET(pthread_rwlock_unlock(lock)) -#endif /* HAVE_PTHREAD_RWLOCK_T */ - -#ifndef HAVE_PTHREAD_SPINLOCK_T -/** in case spinlocks are not supported, use a mutex. */ -typedef pthread_mutex_t lock_quick_type; -/** small front for pthread init func, NULL is default attrs. */ -#define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) -#define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) -#define lock_quick_lock(lock) LOCKRET(pthread_mutex_lock(lock)) -#define lock_quick_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) - -#else /* HAVE_PTHREAD_SPINLOCK_T */ -/** use pthread spinlock for the quick lock */ -typedef pthread_spinlock_t lock_quick_type; -/** - * allocate process private since this is available whether - * Thread Process-Shared Synchronization is supported or not. - * This means only threads inside this process may access the lock. - * (not threads from another process that shares memory). - * spinlocks are not supported on all pthread platforms. - */ -#define lock_quick_init(lock) LOCKRET(pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE)) -#define lock_quick_destroy(lock) LOCKRET(pthread_spin_destroy(lock)) -#define lock_quick_lock(lock) LOCKRET(pthread_spin_lock(lock)) -#define lock_quick_unlock(lock) LOCKRET(pthread_spin_unlock(lock)) - -#endif /* HAVE SPINLOCK */ - -/** Thread creation */ -typedef pthread_t ub_thread_type; -/** On alpine linux default thread stack size is 80 Kb. See -http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Thread_stack_size -This is not enough and cause segfault. Other linux distros have 2 Mb at least. -Wrapper for set up thread stack size */ -#define PTHREADSTACKSIZE 2*1024*1024 -#define PTHREADCREATE(thr, stackrequired, func, arg) do {\ - pthread_attr_t attr; \ - size_t stacksize; \ - LOCKRET(pthread_attr_init(&attr)); \ - LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \ - if (stacksize < stackrequired) { \ - LOCKRET(pthread_attr_setstacksize(&attr, stackrequired)); \ - LOCKRET(pthread_create(thr, &attr, func, arg)); \ - LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \ - verbose(VERB_ALGO, "Thread stack size set to %u", (unsigned)stacksize); \ - } else {LOCKRET(pthread_create(thr, NULL, func, arg));} \ - } while(0) -/** Use wrapper for set thread stack size on attributes. */ -#define ub_thread_create(thr, func, arg) PTHREADCREATE(thr, PTHREADSTACKSIZE, func, arg) -/** get self id. */ -#define ub_thread_self() pthread_self() -/** wait for another thread to terminate */ -#define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL)) -typedef pthread_key_t ub_thread_key_type; -#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f)) -#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v)) -#define ub_thread_key_get(key) pthread_getspecific(key) - -#else /* we do not HAVE_PTHREAD */ -#ifdef HAVE_SOLARIS_THREADS - -/******************* SOLARIS THREADS ************************/ -#include -#include - -typedef rwlock_t lock_rw_type; -#define lock_rw_init(lock) LOCKRET(rwlock_init(lock, USYNC_THREAD, NULL)) -#define lock_rw_destroy(lock) LOCKRET(rwlock_destroy(lock)) -#define lock_rw_rdlock(lock) LOCKRET(rw_rdlock(lock)) -#define lock_rw_wrlock(lock) LOCKRET(rw_wrlock(lock)) -#define lock_rw_unlock(lock) LOCKRET(rw_unlock(lock)) - -/** use basic mutex */ -typedef mutex_t lock_basic_type; -#define lock_basic_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL)) -#define lock_basic_destroy(lock) LOCKRET(mutex_destroy(lock)) -#define lock_basic_lock(lock) LOCKRET(mutex_lock(lock)) -#define lock_basic_unlock(lock) LOCKRET(mutex_unlock(lock)) - -/** No spinlocks in solaris threads API. Use a mutex. */ -typedef mutex_t lock_quick_type; -#define lock_quick_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL)) -#define lock_quick_destroy(lock) LOCKRET(mutex_destroy(lock)) -#define lock_quick_lock(lock) LOCKRET(mutex_lock(lock)) -#define lock_quick_unlock(lock) LOCKRET(mutex_unlock(lock)) - -/** Thread creation, create a default thread. */ -typedef thread_t ub_thread_type; -#define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr)) -#define ub_thread_self() thr_self() -#define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL)) -typedef thread_key_t ub_thread_key_type; -#define ub_thread_key_create(key, f) LOCKRET(thr_keycreate(key, f)) -#define ub_thread_key_set(key, v) LOCKRET(thr_setspecific(key, v)) -void* ub_thread_key_get(ub_thread_key_type key); - - -#else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */ -/******************* WINDOWS THREADS ************************/ -#ifdef HAVE_WINDOWS_THREADS -#include - -/* Use a mutex */ -typedef LONG lock_rw_type; -#define lock_rw_init(lock) lock_basic_init(lock) -#define lock_rw_destroy(lock) lock_basic_destroy(lock) -#define lock_rw_rdlock(lock) lock_basic_lock(lock) -#define lock_rw_wrlock(lock) lock_basic_lock(lock) -#define lock_rw_unlock(lock) lock_basic_unlock(lock) - -/** the basic lock is a mutex, implemented opaquely, for error handling. */ -typedef LONG lock_basic_type; -void lock_basic_init(lock_basic_type* lock); -void lock_basic_destroy(lock_basic_type* lock); -void lock_basic_lock(lock_basic_type* lock); -void lock_basic_unlock(lock_basic_type* lock); - -/** on windows no spinlock, use mutex too. */ -typedef LONG lock_quick_type; -#define lock_quick_init(lock) lock_basic_init(lock) -#define lock_quick_destroy(lock) lock_basic_destroy(lock) -#define lock_quick_lock(lock) lock_basic_lock(lock) -#define lock_quick_unlock(lock) lock_basic_unlock(lock) - -/** Thread creation, create a default thread. */ -typedef HANDLE ub_thread_type; -void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg); -ub_thread_type ub_thread_self(void); -void ub_thread_join(ub_thread_type thr); -typedef DWORD ub_thread_key_type; -void ub_thread_key_create(ub_thread_key_type* key, void* f); -void ub_thread_key_set(ub_thread_key_type key, void* v); -void* ub_thread_key_get(ub_thread_key_type key); - -#else /* we do not HAVE_SOLARIS_THREADS, PTHREADS or WINDOWS_THREADS */ - -/******************* NO THREADS ************************/ -#define THREADS_DISABLED 1 -/** In case there is no thread support, define locks to do nothing */ -typedef int lock_rw_type; -#define lock_rw_init(lock) /* nop */ -#define lock_rw_destroy(lock) /* nop */ -#define lock_rw_rdlock(lock) /* nop */ -#define lock_rw_wrlock(lock) /* nop */ -#define lock_rw_unlock(lock) /* nop */ - -/** define locks to do nothing */ -typedef int lock_basic_type; -#define lock_basic_init(lock) /* nop */ -#define lock_basic_destroy(lock) /* nop */ -#define lock_basic_lock(lock) /* nop */ -#define lock_basic_unlock(lock) /* nop */ - -/** define locks to do nothing */ -typedef int lock_quick_type; -#define lock_quick_init(lock) /* nop */ -#define lock_quick_destroy(lock) /* nop */ -#define lock_quick_lock(lock) /* nop */ -#define lock_quick_unlock(lock) /* nop */ - -/** Thread creation, threads do not exist */ -typedef pid_t ub_thread_type; -/** ub_thread_create is simulated with fork (extremely heavy threads, - * with no shared memory). */ -#define ub_thread_create(thr, func, arg) \ - ub_thr_fork_create(thr, func, arg) -#define ub_thread_self() getpid() -#define ub_thread_join(thread) ub_thr_fork_wait(thread) -void ub_thr_fork_wait(ub_thread_type thread); -void ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg); -typedef void* ub_thread_key_type; -#define ub_thread_key_create(key, f) (*(key)) = NULL -#define ub_thread_key_set(key, v) (key) = (v) -#define ub_thread_key_get(key) (key) - -#endif /* HAVE_WINDOWS_THREADS */ -#endif /* HAVE_SOLARIS_THREADS */ -#endif /* HAVE_PTHREAD */ -#endif /* USE_THREAD_DEBUG */ - -/** - * Block all signals for this thread. - * fatal exit on error. - */ -void ub_thread_blocksigs(void); - -/** - * unblock one signal for this thread. - */ -void ub_thread_sig_unblock(int sig); - -#endif /* UTIL_LOCKS_H */ diff --git a/crates/libunbound-sys/unbound/util/log.c b/crates/libunbound-sys/unbound/util/log.c deleted file mode 100644 index dfbb2334..00000000 --- a/crates/libunbound-sys/unbound/util/log.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * util/log.c - implementation of the log code - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Implementation of log.h. - */ - -#include "config.h" -#include "util/log.h" -#include "util/locks.h" -#include "sldns/sbuffer.h" -#include -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_SYSLOG_H -# include -#else -/**define LOG_ constants */ -# define LOG_CRIT 2 -# define LOG_ERR 3 -# define LOG_WARNING 4 -# define LOG_NOTICE 5 -# define LOG_INFO 6 -# define LOG_DEBUG 7 -#endif -#ifdef UB_ON_WINDOWS -# include "winrc/win_svc.h" -#endif - -/* default verbosity */ -enum verbosity_value verbosity = NO_VERBOSE; -/** the file logged to. */ -static FILE* logfile = 0; -/** if key has been created */ -static int key_created = 0; -/** pthread key for thread ids in logfile */ -static ub_thread_key_type logkey; -#ifndef THREADS_DISABLED -/** pthread mutex to protect FILE* */ -static lock_basic_type log_lock; -#endif -/** the identity of this executable/process */ -static const char* ident="unbound"; -static const char* default_ident="unbound"; -#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) -/** are we using syslog(3) to log to */ -static int logging_to_syslog = 0; -#endif /* HAVE_SYSLOG_H */ -/** print time in UTC or in secondsfrom1970 */ -static int log_time_asc = 0; - -void -log_init(const char* filename, int use_syslog, const char* chrootdir) -{ - FILE *f; - if(!key_created) { - key_created = 1; - ub_thread_key_create(&logkey, NULL); - lock_basic_init(&log_lock); - } - lock_basic_lock(&log_lock); - if(logfile -#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) - || logging_to_syslog -#endif - ) { - lock_basic_unlock(&log_lock); /* verbose() needs the lock */ - verbose(VERB_QUERY, "switching log to %s", - use_syslog?"syslog":(filename&&filename[0]?filename:"stderr")); - lock_basic_lock(&log_lock); - } - if(logfile && logfile != stderr) { - FILE* cl = logfile; - logfile = NULL; /* set to NULL before it is closed, so that - other threads have a valid logfile or NULL */ - fclose(cl); - } -#ifdef HAVE_SYSLOG_H - if(logging_to_syslog) { - closelog(); - logging_to_syslog = 0; - } - if(use_syslog) { - /* do not delay opening until first write, because we may - * chroot and no longer be able to access dev/log and so on */ - /* the facility is LOG_DAEMON by default, but - * --with-syslog-facility=LOCAL[0-7] can override it */ - openlog(ident, LOG_NDELAY, UB_SYSLOG_FACILITY); - logging_to_syslog = 1; - lock_basic_unlock(&log_lock); - return; - } -#elif defined(UB_ON_WINDOWS) - if(logging_to_syslog) { - logging_to_syslog = 0; - } - if(use_syslog) { - logging_to_syslog = 1; - lock_basic_unlock(&log_lock); - return; - } -#endif /* HAVE_SYSLOG_H */ - if(!filename || !filename[0]) { - logfile = stderr; - lock_basic_unlock(&log_lock); - return; - } - /* open the file for logging */ - if(chrootdir && chrootdir[0] && strncmp(filename, chrootdir, - strlen(chrootdir)) == 0) - filename += strlen(chrootdir); - f = fopen(filename, "a"); - if(!f) { - lock_basic_unlock(&log_lock); - log_err("Could not open logfile %s: %s", filename, - strerror(errno)); - return; - } -#ifndef UB_ON_WINDOWS - /* line buffering does not work on windows */ - setvbuf(f, NULL, (int)_IOLBF, 0); -#endif - logfile = f; - lock_basic_unlock(&log_lock); -} - -void log_file(FILE *f) -{ - lock_basic_lock(&log_lock); - logfile = f; - lock_basic_unlock(&log_lock); -} - -void log_thread_set(int* num) -{ - ub_thread_key_set(logkey, num); -} - -int log_thread_get(void) -{ - unsigned int* tid; - if(!key_created) return 0; - tid = (unsigned int*)ub_thread_key_get(logkey); - return (int)(tid?*tid:0); -} - -void log_ident_set(const char* id) -{ - ident = id; -} - -void log_ident_set_default(const char* id) -{ - default_ident = id; -} - -void log_ident_revert_to_default() -{ - ident = default_ident; -} - -void log_ident_set_or_default(const char* identity) -{ - if(identity == NULL || identity[0] == 0) - log_ident_set(default_ident); - else - log_ident_set(identity); -} - -void log_set_time_asc(int use_asc) -{ - log_time_asc = use_asc; -} - -void* log_get_lock(void) -{ - if(!key_created) - return NULL; -#ifndef THREADS_DISABLED - return (void*)&log_lock; -#else - return NULL; -#endif -} - -void -log_vmsg(int pri, const char* type, - const char *format, va_list args) -{ - char message[MAXSYSLOGMSGLEN]; - unsigned int* tid = (unsigned int*)ub_thread_key_get(logkey); - time_t now; -#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) - char tmbuf[32]; - struct tm tm; -#elif defined(UB_ON_WINDOWS) - char tmbuf[128], dtbuf[128]; -#endif - (void)pri; - vsnprintf(message, sizeof(message), format, args); -#ifdef HAVE_SYSLOG_H - if(logging_to_syslog) { - syslog(pri, "[%d:%x] %s: %s", - (int)getpid(), tid?*tid:0, type, message); - return; - } -#elif defined(UB_ON_WINDOWS) - if(logging_to_syslog) { - char m[32768]; - HANDLE* s; - LPCTSTR str = m; - DWORD tp = MSG_GENERIC_ERR; - WORD wt = EVENTLOG_ERROR_TYPE; - if(strcmp(type, "info") == 0) { - tp=MSG_GENERIC_INFO; - wt=EVENTLOG_INFORMATION_TYPE; - } else if(strcmp(type, "warning") == 0) { - tp=MSG_GENERIC_WARN; - wt=EVENTLOG_WARNING_TYPE; - } else if(strcmp(type, "notice") == 0 - || strcmp(type, "debug") == 0) { - tp=MSG_GENERIC_SUCCESS; - wt=EVENTLOG_SUCCESS; - } - snprintf(m, sizeof(m), "[%s:%x] %s: %s", - ident, tid?*tid:0, type, message); - s = RegisterEventSource(NULL, SERVICE_NAME); - if(!s) return; - ReportEvent(s, wt, 0, tp, NULL, 1, 0, &str, NULL); - DeregisterEventSource(s); - return; - } -#endif /* HAVE_SYSLOG_H */ - lock_basic_lock(&log_lock); - if(!logfile) { - lock_basic_unlock(&log_lock); - return; - } - now = (time_t)time(NULL); -#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) - if(log_time_asc && strftime(tmbuf, sizeof(tmbuf), "%b %d %H:%M:%S", - localtime_r(&now, &tm))%(sizeof(tmbuf)) != 0) { - /* %sizeof buf!=0 because old strftime returned max on error */ - fprintf(logfile, "%s %s[%d:%x] %s: %s\n", tmbuf, - ident, (int)getpid(), tid?*tid:0, type, message); - } else -#elif defined(UB_ON_WINDOWS) - if(log_time_asc && GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL, NULL, - tmbuf, sizeof(tmbuf)) && GetDateFormat(LOCALE_USER_DEFAULT, 0, - NULL, NULL, dtbuf, sizeof(dtbuf))) { - fprintf(logfile, "%s %s %s[%d:%x] %s: %s\n", dtbuf, tmbuf, - ident, (int)getpid(), tid?*tid:0, type, message); - } else -#endif - fprintf(logfile, "[" ARG_LL "d] %s[%d:%x] %s: %s\n", (long long)now, - ident, (int)getpid(), tid?*tid:0, type, message); -#ifdef UB_ON_WINDOWS - /* line buffering does not work on windows */ - fflush(logfile); -#endif - lock_basic_unlock(&log_lock); -} - -/** - * implementation of log_info - * @param format: format string printf-style. - */ -void -log_info(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_INFO, "info", format, args); - va_end(args); -} - -/** - * implementation of log_err - * @param format: format string printf-style. - */ -void -log_err(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_ERR, "error", format, args); - va_end(args); -} - -/** - * implementation of log_warn - * @param format: format string printf-style. - */ -void -log_warn(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_WARNING, "warning", format, args); - va_end(args); -} - -/** - * implementation of fatal_exit - * @param format: format string printf-style. - */ -void -fatal_exit(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_CRIT, "fatal error", format, args); - va_end(args); - exit(1); -} - -/** - * implementation of verbose - * @param level: verbose level for the message. - * @param format: format string printf-style. - */ -void -verbose(enum verbosity_value level, const char* format, ...) -{ - va_list args; - va_start(args, format); - if(verbosity >= level) { - if(level == VERB_OPS) - log_vmsg(LOG_NOTICE, "notice", format, args); - else if(level == VERB_DETAIL) - log_vmsg(LOG_INFO, "info", format, args); - else log_vmsg(LOG_DEBUG, "debug", format, args); - } - va_end(args); -} - -/** log hex data */ -static void -log_hex_f(enum verbosity_value v, const char* msg, void* data, size_t length) -{ - size_t i, j; - uint8_t* data8 = (uint8_t*)data; - const char* hexchar = "0123456789ABCDEF"; - char buf[1024+1]; /* alloc blocksize hex chars + \0 */ - const size_t blocksize = 512; - size_t len; - - if(length == 0) { - verbose(v, "%s[%u]", msg, (unsigned)length); - return; - } - - for(i=0; i> 4 ]; - buf[j*2 + 1] = hexchar[ data8[i+j] & 0xF ]; - } - buf[len*2] = 0; - verbose(v, "%s[%u:%u] %.*s", msg, (unsigned)length, - (unsigned)i, (int)len*2, buf); - } -} - -void -log_hex(const char* msg, void* data, size_t length) -{ - log_hex_f(verbosity, msg, data, length); -} - -void -log_query(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_INFO, "query", format, args); - va_end(args); -} - -void -log_reply(const char *format, ...) -{ - va_list args; - va_start(args, format); - log_vmsg(LOG_INFO, "reply", format, args); - va_end(args); -} - -void log_buf(enum verbosity_value level, const char* msg, sldns_buffer* buf) -{ - if(verbosity < level) - return; - log_hex_f(level, msg, sldns_buffer_begin(buf), sldns_buffer_limit(buf)); -} - -#ifdef USE_WINSOCK -char* wsa_strerror(DWORD err) -{ - static char unknown[32]; - - switch(err) { - case WSA_INVALID_HANDLE: return "Specified event object handle is invalid."; - case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available."; - case WSA_INVALID_PARAMETER: return "One or more parameters are invalid."; - case WSA_OPERATION_ABORTED: return "Overlapped operation aborted."; - case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state."; - case WSA_IO_PENDING: return "Overlapped operations will complete later."; - case WSAEINTR: return "Interrupted function call."; - case WSAEBADF: return "File handle is not valid."; - case WSAEACCES: return "Permission denied."; - case WSAEFAULT: return "Bad address."; - case WSAEINVAL: return "Invalid argument."; - case WSAEMFILE: return "Too many open files."; - case WSAEWOULDBLOCK: return "Resource temporarily unavailable."; - case WSAEINPROGRESS: return "Operation now in progress."; - case WSAEALREADY: return "Operation already in progress."; - case WSAENOTSOCK: return "Socket operation on nonsocket."; - case WSAEDESTADDRREQ: return "Destination address required."; - case WSAEMSGSIZE: return "Message too long."; - case WSAEPROTOTYPE: return "Protocol wrong type for socket."; - case WSAENOPROTOOPT: return "Bad protocol option."; - case WSAEPROTONOSUPPORT: return "Protocol not supported."; - case WSAESOCKTNOSUPPORT: return "Socket type not supported."; - case WSAEOPNOTSUPP: return "Operation not supported."; - case WSAEPFNOSUPPORT: return "Protocol family not supported."; - case WSAEAFNOSUPPORT: return "Address family not supported by protocol family."; - case WSAEADDRINUSE: return "Address already in use."; - case WSAEADDRNOTAVAIL: return "Cannot assign requested address."; - case WSAENETDOWN: return "Network is down."; - case WSAENETUNREACH: return "Network is unreachable."; - case WSAENETRESET: return "Network dropped connection on reset."; - case WSAECONNABORTED: return "Software caused connection abort."; - case WSAECONNRESET: return "Connection reset by peer."; - case WSAENOBUFS: return "No buffer space available."; - case WSAEISCONN: return "Socket is already connected."; - case WSAENOTCONN: return "Socket is not connected."; - case WSAESHUTDOWN: return "Cannot send after socket shutdown."; - case WSAETOOMANYREFS: return "Too many references."; - case WSAETIMEDOUT: return "Connection timed out."; - case WSAECONNREFUSED: return "Connection refused."; - case WSAELOOP: return "Cannot translate name."; - case WSAENAMETOOLONG: return "Name too long."; - case WSAEHOSTDOWN: return "Host is down."; - case WSAEHOSTUNREACH: return "No route to host."; - case WSAENOTEMPTY: return "Directory not empty."; - case WSAEPROCLIM: return "Too many processes."; - case WSAEUSERS: return "User quota exceeded."; - case WSAEDQUOT: return "Disk quota exceeded."; - case WSAESTALE: return "Stale file handle reference."; - case WSAEREMOTE: return "Item is remote."; - case WSASYSNOTREADY: return "Network subsystem is unavailable."; - case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range."; - case WSANOTINITIALISED: return "Successful WSAStartup not yet performed."; - case WSAEDISCON: return "Graceful shutdown in progress."; - case WSAENOMORE: return "No more results."; - case WSAECANCELLED: return "Call has been canceled."; - case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid."; - case WSAEINVALIDPROVIDER: return "Service provider is invalid."; - case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize."; - case WSASYSCALLFAILURE: return "System call failure."; - case WSASERVICE_NOT_FOUND: return "Service not found."; - case WSATYPE_NOT_FOUND: return "Class type not found."; - case WSA_E_NO_MORE: return "No more results."; - case WSA_E_CANCELLED: return "Call was canceled."; - case WSAEREFUSED: return "Database query was refused."; - case WSAHOST_NOT_FOUND: return "Host not found."; - case WSATRY_AGAIN: return "Nonauthoritative host not found."; - case WSANO_RECOVERY: return "This is a nonrecoverable error."; - case WSANO_DATA: return "Valid name, no data record of requested type."; - case WSA_QOS_RECEIVERS: return "QOS receivers."; - case WSA_QOS_SENDERS: return "QOS senders."; - case WSA_QOS_NO_SENDERS: return "No QOS senders."; - case WSA_QOS_NO_RECEIVERS: return "QOS no receivers."; - case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed."; - case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error."; - case WSA_QOS_POLICY_FAILURE: return "QOS policy failure."; - case WSA_QOS_BAD_STYLE: return "QOS bad style."; - case WSA_QOS_BAD_OBJECT: return "QOS bad object."; - case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error."; - case WSA_QOS_GENERIC_ERROR: return "QOS generic error."; - case WSA_QOS_ESERVICETYPE: return "QOS service type error."; - case WSA_QOS_EFLOWSPEC: return "QOS flowspec error."; - case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer."; - case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style."; - case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type."; - case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count."; - case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length."; - case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count."; - /*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/ - case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object."; - case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor."; - case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec."; - case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec."; - case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object."; - case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object."; - case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type."; - default: - snprintf(unknown, sizeof(unknown), - "unknown WSA error code %d", (int)err); - return unknown; - } -} -#endif /* USE_WINSOCK */ diff --git a/crates/libunbound-sys/unbound/util/log.h b/crates/libunbound-sys/unbound/util/log.h deleted file mode 100644 index 29a1ba38..00000000 --- a/crates/libunbound-sys/unbound/util/log.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * util/log.h - logging service - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains logging functions. - */ - -#ifndef UTIL_LOG_H -#define UTIL_LOG_H -struct sldns_buffer; - -/** - * verbosity value: - */ -enum verbosity_value { - /** 0 - no verbose messages */ - NO_VERBOSE = 0, - /** 1 - operational information */ - VERB_OPS, - /** 2 - detailed information */ - VERB_DETAIL, - /** 3 - query level information */ - VERB_QUERY, - /** 4 - algorithm level information */ - VERB_ALGO, - /** 5 - querier client information */ - VERB_CLIENT -}; - -/** The global verbosity setting */ -extern enum verbosity_value verbosity; - -/** - * log a verbose message, pass the level for this message. - * It has printf formatted arguments. No trailing newline is needed. - * @param level: verbosity level for this message, compared to global - * verbosity setting. - * @param format: printf-style format string. Arguments follow. - */ -void verbose(enum verbosity_value level, - const char* format, ...) ATTR_FORMAT(printf, 2, 3); - -/** - * call this to initialize logging services. - * @param filename: if NULL stderr is used. - * @param use_syslog: set to true to ignore filename and use syslog(3). - * @param chrootdir: to which directory we have been chrooted, if any. - */ -void log_init(const char* filename, int use_syslog, const char* chrootdir); - -/** - * Set logging to go to the specified file *. - * This setting does not affect the use_syslog setting. - * @param f: to that file, or pass NULL to disable logging. - */ -void log_file(FILE *f); - -/** - * Init a thread (will print this number for the thread log entries). - * Must be called from the thread itself. If not called 0 is printed. - * @param num: number to print for this thread. Owned by caller, must - * continue to exist. - */ -void log_thread_set(int* num); - -/** - * Get the thread id from logging system. Set after log_init is - * initialised, or log_thread_set for newly created threads. - * This initialisation happens in unbound as a daemon, in daemon - * startup code, when that spawns threads. - * @return thread number, from 0 and up. Before initialised, returns 0. - */ -int log_thread_get(void); - -/** - * Set identity to print, default is 'unbound'. - * @param id: string to print. Name of executable. - */ -void log_ident_set(const char* id); - -/** - * Set default identity to print, default is 'unbound'. - * @param id: string to print. Name of executable. - */ -void log_ident_set_default(const char* id); - -/** - * Revert identity to print, back to the recorded default value. - */ -void log_ident_revert_to_default(void); - -/** - * Set identity to print if there is an identity, otherwise - * set the default. - * @param identity: the identity to set. - */ -void log_ident_set_or_default(const char* identity); - -/** - * Set if the time value is printed ascii or decimal in log entries. - * @param use_asc: if true, ascii is printed, otherwise decimal. - * If the conversion fails or you have no time functions, - * decimal is printed. - */ -void log_set_time_asc(int use_asc); - -/** get log lock */ -void* log_get_lock(void); - -/** - * Log informational message. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void log_info(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - -/** - * Log error message. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void log_err(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - -/** - * Log warning message. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - -/** - * Log a hex-string to the log. Can be any length. - * performs mallocs to do so, slow. But debug useful. - * @param msg: string desc to accompany the hexdump. - * @param data: data to dump in hex format. - * @param length: length of data. - */ -void log_hex(const char* msg, void* data, size_t length); - -/** - * Log query. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void log_query(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - -/** - * Log reply. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void log_reply(const char* format, ...) ATTR_FORMAT(printf, 1, 2); - -/** - * Easy alternative for log_hex, takes a sldns_buffer. - * @param level: verbosity level for this message, compared to global - * verbosity setting. - * @param msg: string desc to print - * @param buf: the buffer. - */ -void log_buf(enum verbosity_value level, const char* msg, struct sldns_buffer* buf); - -/** - * Log fatal error message, and exit the current process. - * Pass printf formatted arguments. No trailing newline is needed. - * @param format: printf-style format string. Arguments follow. - */ -void fatal_exit(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN; - -/** - * va_list argument version of log_info. - * @param pri: priority type, for example 5 (INFO). - * @param type: string to designate type of message (info, error). - * @param format: the printf style format to print. no newline. - * @param args: arguments for format string. - */ -void log_vmsg(int pri, const char* type, const char* format, va_list args); - -/** - * an assertion that is thrown to the logfile. - */ -#ifdef UNBOUND_DEBUG -#ifdef __clang_analyzer__ -/* clang analyzer needs to know that log_assert is an assertion, otherwise - * it could complain about the nullptr the assert is guarding against. */ -#define log_assert(x) assert(x) -#else -# define log_assert(x) \ - do { if(!(x)) \ - fatal_exit("%s:%d: %s: assertion %s failed", \ - __FILE__, __LINE__, __func__, #x); \ - } while(0); -#endif -#else -# define log_assert(x) /*nothing*/ -#endif - -#ifdef USE_WINSOCK -/** - * Convert WSA error into string. - * @param err: from WSAGetLastError() - * @return: string. - */ -char* wsa_strerror(DWORD err); -#endif /* USE_WINSOCK */ - -#endif /* UTIL_LOG_H */ diff --git a/crates/libunbound-sys/unbound/util/mini_event.c b/crates/libunbound-sys/unbound/util/mini_event.c deleted file mode 100644 index c05dc668..00000000 --- a/crates/libunbound-sys/unbound/util/mini_event.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * mini_event.c - implementation of part of libevent api, portably. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * fake libevent implementation. Less broad in functionality, and only - * supports select(2). - */ - -#include "config.h" -#include "util/mini_event.h" -#ifdef HAVE_TIME_H -#include -#endif -#include - -#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) -#include -#include "util/fptr_wlist.h" - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int mini_ev_cmp(const void* a, const void* b) -{ - const struct event *e = (const struct event*)a; - const struct event *f = (const struct event*)b; - if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) - return -1; - if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) - return 1; - if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) - return -1; - if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) - return 1; - if(e < f) - return -1; - if(e > f) - return 1; - return 0; -} - -/** set time */ -static int -settime(struct event_base* base) -{ - if(gettimeofday(base->time_tv, NULL) < 0) { - return -1; - } -#ifndef S_SPLINT_S - *base->time_secs = (time_t)base->time_tv->tv_sec; -#endif - return 0; -} - -/** create event base */ -void *event_init(time_t* time_secs, struct timeval* time_tv) -{ - struct event_base* base = (struct event_base*)malloc( - sizeof(struct event_base)); - if(!base) - return NULL; - memset(base, 0, sizeof(*base)); - base->time_secs = time_secs; - base->time_tv = time_tv; - if(settime(base) < 0) { - event_base_free(base); - return NULL; - } - base->times = rbtree_create(mini_ev_cmp); - if(!base->times) { - event_base_free(base); - return NULL; - } - base->capfd = MAX_FDS; -#ifdef FD_SETSIZE - if((int)FD_SETSIZE < base->capfd) - base->capfd = (int)FD_SETSIZE; -#endif - base->fds = (struct event**)calloc((size_t)base->capfd, - sizeof(struct event*)); - if(!base->fds) { - event_base_free(base); - return NULL; - } - base->signals = (struct event**)calloc(MAX_SIG, sizeof(struct event*)); - if(!base->signals) { - event_base_free(base); - return NULL; - } -#ifndef S_SPLINT_S - FD_ZERO(&base->reads); - FD_ZERO(&base->writes); -#endif - return base; -} - -/** get version */ -const char *event_get_version(void) -{ - return "mini-event-"PACKAGE_VERSION; -} - -/** get polling method, select */ -const char *event_get_method(void) -{ - return "select"; -} - -/** call timeouts handlers, and return how long to wait for next one or -1 */ -static void handle_timeouts(struct event_base* base, struct timeval* now, - struct timeval* wait) -{ - struct event* p; -#ifndef S_SPLINT_S - wait->tv_sec = (time_t)-1; -#endif - - while((rbnode_type*)(p = (struct event*)rbtree_first(base->times)) - !=RBTREE_NULL) { -#ifndef S_SPLINT_S - if(p->ev_timeout.tv_sec > now->tv_sec || - (p->ev_timeout.tv_sec==now->tv_sec && - p->ev_timeout.tv_usec > now->tv_usec)) { - /* there is a next larger timeout. wait for it */ - wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; - if(now->tv_usec > p->ev_timeout.tv_usec) { - wait->tv_sec--; - wait->tv_usec = 1000000 - (now->tv_usec - - p->ev_timeout.tv_usec); - } else { - wait->tv_usec = p->ev_timeout.tv_usec - - now->tv_usec; - } - return; - } -#endif - /* event times out, remove it */ - (void)rbtree_delete(base->times, p); - p->ev_events &= ~EV_TIMEOUT; - fptr_ok(fptr_whitelist_event(p->ev_callback)); - (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); - } -} - -/** call select and callbacks for that */ -static int handle_select(struct event_base* base, struct timeval* wait) -{ - fd_set r, w; - int ret, i; - -#ifndef S_SPLINT_S - if(wait->tv_sec==(time_t)-1) - wait = NULL; -#endif - memmove(&r, &base->reads, sizeof(fd_set)); - memmove(&w, &base->writes, sizeof(fd_set)); - memmove(&base->ready, &base->content, sizeof(fd_set)); - - if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) { - ret = errno; - if(settime(base) < 0) - return -1; - errno = ret; - if(ret == EAGAIN || ret == EINTR) - return 0; - return -1; - } - if(settime(base) < 0) - return -1; - - for(i=0; imaxfd+1; i++) { - short bits = 0; - if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) { - continue; - } - if(FD_ISSET(i, &r)) { - bits |= EV_READ; - ret--; - } - if(FD_ISSET(i, &w)) { - bits |= EV_WRITE; - ret--; - } - bits &= base->fds[i]->ev_events; - if(bits) { - fptr_ok(fptr_whitelist_event( - base->fds[i]->ev_callback)); - (*base->fds[i]->ev_callback)(base->fds[i]->ev_fd, - bits, base->fds[i]->ev_arg); - if(ret==0) - break; - } - } - return 0; -} - -/** run select in a loop */ -int event_base_dispatch(struct event_base* base) -{ - struct timeval wait; - if(settime(base) < 0) - return -1; - while(!base->need_to_exit) - { - /* see if timeouts need handling */ - handle_timeouts(base, base->time_tv, &wait); - if(base->need_to_exit) - return 0; - /* do select */ - if(handle_select(base, &wait) < 0) { - if(base->need_to_exit) - return 0; - return -1; - } - } - return 0; -} - -/** exit that loop */ -int event_base_loopexit(struct event_base* base, - struct timeval* ATTR_UNUSED(tv)) -{ - base->need_to_exit = 1; - return 0; -} - -/* free event base, free events yourself */ -void event_base_free(struct event_base* base) -{ - if(!base) - return; - free(base->times); - free(base->fds); - free(base->signals); - free(base); -} - -/** set content of event */ -void event_set(struct event* ev, int fd, short bits, - void (*cb)(int, short, void *), void* arg) -{ - ev->node.key = ev; - ev->ev_fd = fd; - ev->ev_events = bits; - ev->ev_callback = cb; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - ev->ev_arg = arg; - ev->added = 0; -} - -/* add event to a base */ -int event_base_set(struct event_base* base, struct event* ev) -{ - ev->ev_base = base; - ev->added = 0; - return 0; -} - -/* add event to make it active, you may not change it with event_set anymore */ -int event_add(struct event* ev, struct timeval* tv) -{ - if(ev->added) - event_del(ev); - if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) - return -1; - if( (ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - ev->ev_base->fds[ev->ev_fd] = ev; - if(ev->ev_events&EV_READ) { - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->reads); - } - if(ev->ev_events&EV_WRITE) { - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->writes); - } - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->content); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); - if(ev->ev_fd > ev->ev_base->maxfd) - ev->ev_base->maxfd = ev->ev_fd; - } - if(tv && (ev->ev_events&EV_TIMEOUT)) { -#ifndef S_SPLINT_S - struct timeval *now = ev->ev_base->time_tv; - ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; - ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; - while(ev->ev_timeout.tv_usec >= 1000000) { - ev->ev_timeout.tv_usec -= 1000000; - ev->ev_timeout.tv_sec++; - } -#endif - (void)rbtree_insert(ev->ev_base->times, &ev->node); - } - ev->added = 1; - return 0; -} - -/* remove event, you may change it again */ -int event_del(struct event* ev) -{ - if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) - return -1; - if((ev->ev_events&EV_TIMEOUT)) - (void)rbtree_delete(ev->ev_base->times, &ev->node); - if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - ev->ev_base->fds[ev->ev_fd] = NULL; - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->reads); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content); - if(ev->ev_fd == ev->ev_base->maxfd) { - int i = ev->ev_base->maxfd - 1; - for (; i > 3; i--) { - if (NULL != ev->ev_base->fds[i]) { - break; - } - } - ev->ev_base->maxfd = i; - } - } - ev->added = 0; - return 0; -} - -/** which base gets to handle signals */ -static struct event_base* signal_base = NULL; -/** signal handler */ -static RETSIGTYPE sigh(int sig) -{ - struct event* ev; - if(!signal_base || sig < 0 || sig >= MAX_SIG) - return; - ev = signal_base->signals[sig]; - if(!ev) - return; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - (*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg); -} - -/** install signal handler */ -int signal_add(struct event* ev, struct timeval* ATTR_UNUSED(tv)) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - signal_base = ev->ev_base; - ev->ev_base->signals[ev->ev_fd] = ev; - ev->added = 1; - if(signal(ev->ev_fd, sigh) == SIG_ERR) { - return -1; - } - return 0; -} - -/** remove signal handler */ -int signal_del(struct event* ev) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - ev->ev_base->signals[ev->ev_fd] = NULL; - ev->added = 0; - return 0; -} - -#else /* USE_MINI_EVENT */ -#ifndef USE_WINSOCK -int mini_ev_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - return 0; -} -#endif /* not USE_WINSOCK */ -#endif /* USE_MINI_EVENT */ diff --git a/crates/libunbound-sys/unbound/util/mini_event.h b/crates/libunbound-sys/unbound/util/mini_event.h deleted file mode 100644 index fa71ca3d..00000000 --- a/crates/libunbound-sys/unbound/util/mini_event.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * mini-event.h - micro implementation of libevent api, using select() only. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * This file implements part of the event(3) libevent api. - * The back end is only select. Max number of fds is limited. - * Max number of signals is limited, one handler per signal only. - * And one handler per fd. - * - * Although limited to select() and a max (1024) open fds, it - * is efficient: - * o dispatch call caches fd_sets to use. - * o handler calling takes time ~ to the number of fds. - * o timeouts are stored in a redblack tree, sorted, so take log(n). - * Timeouts are only accurate to the second (no subsecond accuracy). - * To avoid cpu hogging, fractional timeouts are rounded up to a whole second. - */ - -#ifndef MINI_EVENT_H -#define MINI_EVENT_H - -#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) - -#ifdef HAVE_SYS_SELECT_H -/* for fd_set on OpenBSD */ -#include -#endif -#include - -#ifndef HAVE_EVENT_BASE_FREE -#define HAVE_EVENT_BASE_FREE -#endif - -/* redefine to use our own namespace so that on platforms where - * linkers crosslink library-private symbols with other symbols, it works */ -#define event_init minievent_init -#define event_get_version minievent_get_version -#define event_get_method minievent_get_method -#define event_base_dispatch minievent_base_dispatch -#define event_base_loopexit minievent_base_loopexit -#define event_base_free minievent_base_free -#define event_set minievent_set -#define event_base_set minievent_base_set -#define event_add minievent_add -#define event_del minievent_del -#define signal_add minisignal_add -#define signal_del minisignal_del - -/** event timeout */ -#define EV_TIMEOUT 0x01 -/** event fd readable */ -#define EV_READ 0x02 -/** event fd writable */ -#define EV_WRITE 0x04 -/** event signal */ -#define EV_SIGNAL 0x08 -/** event must persist */ -#define EV_PERSIST 0x10 - -/* needs our redblack tree */ -#include "rbtree.h" - -/** max number of file descriptors to support */ -#define MAX_FDS 1024 -/** max number of signals to support */ -#define MAX_SIG 32 - -/** event base */ -struct event_base -{ - /** sorted by timeout (absolute), ptr */ - rbtree_type* times; - /** array of 0 - maxfd of ptr to event for it */ - struct event** fds; - /** max fd in use */ - int maxfd; - /** capacity - size of the fds array */ - int capfd; - /* fdset for read write, for fds ready, and added */ - fd_set - /** fds for reading */ - reads, - /** fds for writing */ - writes, - /** fds determined ready for use */ - ready, - /** ready plus newly added events. */ - content; - /** array of 0 - maxsig of ptr to event for it */ - struct event** signals; - /** if we need to exit */ - int need_to_exit; - /** where to store time in seconds */ - time_t* time_secs; - /** where to store time in microseconds */ - struct timeval* time_tv; -}; - -/** - * Event structure. Has some of the event elements. - */ -struct event { - /** node in timeout rbtree */ - rbnode_type node; - /** is event already added */ - int added; - - /** event base it belongs to */ - struct event_base *ev_base; - /** fd to poll or -1 for timeouts. signal number for sigs. */ - int ev_fd; - /** what events this event is interested in, see EV_.. above. */ - short ev_events; - /** timeout value */ - struct timeval ev_timeout; - - /** callback to call: fd, eventbits, userarg */ - void (*ev_callback)(int, short, void *arg); - /** callback user arg */ - void *ev_arg; -}; - -/* function prototypes (some are as they appear in event.h) */ -/** create event base */ -void *event_init(time_t* time_secs, struct timeval* time_tv); -/** get version */ -const char *event_get_version(void); -/** get polling method, select */ -const char *event_get_method(void); -/** run select in a loop */ -int event_base_dispatch(struct event_base *); -/** exit that loop */ -int event_base_loopexit(struct event_base *, struct timeval *); -/** free event base. Free events yourself */ -void event_base_free(struct event_base *); -/** set content of event */ -void event_set(struct event *, int, short, void (*)(int, short, void *), void *); -/** add event to a base. You *must* call this for every event. */ -int event_base_set(struct event_base *, struct event *); -/** add event to make it active. You may not change it with event_set anymore */ -int event_add(struct event *, struct timeval *); -/** remove event. You may change it again */ -int event_del(struct event *); - -/** add a timer */ -#define evtimer_add(ev, tv) event_add(ev, tv) -/** remove a timer */ -#define evtimer_del(ev) event_del(ev) - -/* uses different implementation. Cannot mix fd/timeouts and signals inside - * the same struct event. create several event structs for that. */ -/** install signal handler */ -int signal_add(struct event *, struct timeval *); -/** set signal event contents */ -#define signal_set(ev, x, cb, arg) \ - event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -/** remove signal handler */ -int signal_del(struct event *); - -#endif /* USE_MINI_EVENT and not USE_WINSOCK */ - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int mini_ev_cmp(const void* a, const void* b); - -#endif /* MINI_EVENT_H */ diff --git a/crates/libunbound-sys/unbound/util/module.c b/crates/libunbound-sys/unbound/util/module.c deleted file mode 100644 index 773dab85..00000000 --- a/crates/libunbound-sys/unbound/util/module.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * util/module.c - module interface - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Implementation of module.h. - */ - -#include "config.h" -#include "util/module.h" -#include "sldns/wire2str.h" -#include "util/config_file.h" -#include "util/regional.h" -#include "util/data/dname.h" -#include "util/net_help.h" - -const char* -strextstate(enum module_ext_state s) -{ - switch(s) { - case module_state_initial: return "module_state_initial"; - case module_wait_reply: return "module_wait_reply"; - case module_wait_module: return "module_wait_module"; - case module_restart_next: return "module_restart_next"; - case module_wait_subquery: return "module_wait_subquery"; - case module_error: return "module_error"; - case module_finished: return "module_finished"; - } - return "bad_extstate_value"; -} - -const char* -strmodulevent(enum module_ev e) -{ - switch(e) { - case module_event_new: return "module_event_new"; - case module_event_pass: return "module_event_pass"; - case module_event_reply: return "module_event_reply"; - case module_event_noreply: return "module_event_noreply"; - case module_event_capsfail: return "module_event_capsfail"; - case module_event_moddone: return "module_event_moddone"; - case module_event_error: return "module_event_error"; - } - return "bad_event_value"; -} - -void errinf(struct module_qstate* qstate, const char* str) -{ - errinf_ede(qstate, str, LDNS_EDE_NONE); -} - -void errinf_ede(struct module_qstate* qstate, - const char* str, sldns_ede_code reason_bogus) -{ - struct errinf_strlist* p; - if(!str || (qstate->env->cfg->val_log_level < 2 && - !qstate->env->cfg->log_servfail)) { - return; - } - p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p)); - if(!p) { - log_err("malloc failure in validator-error-info string"); - return; - } - p->next = NULL; - p->str = regional_strdup(qstate->region, str); - p->reason_bogus = reason_bogus; - if(!p->str) { - log_err("malloc failure in validator-error-info string"); - return; - } - /* add at end */ - if(qstate->errinf) { - struct errinf_strlist* q = qstate->errinf; - while(q->next) - q = q->next; - q->next = p; - } else qstate->errinf = p; -} - -void errinf_origin(struct module_qstate* qstate, struct sock_list *origin) -{ - struct sock_list* p; - if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) - return; - for(p=origin; p; p=p->next) { - char buf[256]; - if(p == origin) - snprintf(buf, sizeof(buf), "from "); - else snprintf(buf, sizeof(buf), "and "); - if(p->len == 0) - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), - "cache"); - else - addr_to_str(&p->addr, p->len, buf+strlen(buf), - sizeof(buf)-strlen(buf)); - errinf(qstate, buf); - } -} - -char* errinf_to_str_bogus(struct module_qstate* qstate) -{ - char buf[20480]; - char* p = buf; - size_t left = sizeof(buf); - struct errinf_strlist* s; - char dname[LDNS_MAX_DOMAINLEN+1]; - char t[16], c[16]; - sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t)); - sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c)); - dname_str(qstate->qinfo.qname, dname); - snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c); - left -= strlen(p); p += strlen(p); - if(!qstate->errinf) - snprintf(p, left, " misc failure"); - else for(s=qstate->errinf; s; s=s->next) { - snprintf(p, left, " %s", s->str); - left -= strlen(p); p += strlen(p); - } - p = strdup(buf); - if(!p) - log_err("malloc failure in errinf_to_str"); - return p; -} - -/* Try to find the latest (most specific) dnssec failure */ -sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate) -{ - struct errinf_strlist* s; - sldns_ede_code ede = LDNS_EDE_NONE; - for(s=qstate->errinf; s; s=s->next) { - if(s->reason_bogus == LDNS_EDE_NONE) continue; - if(ede != LDNS_EDE_NONE - && ede != LDNS_EDE_DNSSEC_BOGUS - && s->reason_bogus == LDNS_EDE_DNSSEC_BOGUS) continue; - ede = s->reason_bogus; - } - return ede; -} - -char* errinf_to_str_servfail(struct module_qstate* qstate) -{ - char buf[20480]; - char* p = buf; - size_t left = sizeof(buf); - struct errinf_strlist* s; - char dname[LDNS_MAX_DOMAINLEN+1]; - char t[16], c[16]; - sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t)); - sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c)); - dname_str(qstate->qinfo.qname, dname); - snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c); - left -= strlen(p); p += strlen(p); - if(!qstate->errinf) - snprintf(p, left, " misc failure"); - else for(s=qstate->errinf; s; s=s->next) { - snprintf(p, left, " %s", s->str); - left -= strlen(p); p += strlen(p); - } - p = strdup(buf); - if(!p) - log_err("malloc failure in errinf_to_str"); - return p; -} - -void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr) -{ - char buf[1024]; - char dname[LDNS_MAX_DOMAINLEN+1]; - char t[16], c[16]; - if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr) - return; - sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t)); - sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c)); - dname_str(rr->rk.dname, dname); - snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c); - errinf(qstate, buf); -} - -void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname) -{ - char b[1024]; - char buf[LDNS_MAX_DOMAINLEN+1]; - if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname) - return; - dname_str(dname, buf); - snprintf(b, sizeof(b), "%s %s", str, buf); - errinf(qstate, b); -} - -int -edns_known_options_init(struct module_env* env) -{ - env->edns_known_options_num = 0; - env->edns_known_options = (struct edns_known_option*)calloc( - MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option)); - if(!env->edns_known_options) return 0; - return 1; -} - -void -edns_known_options_delete(struct module_env* env) -{ - free(env->edns_known_options); - env->edns_known_options = NULL; - env->edns_known_options_num = 0; -} - -int -edns_register_option(uint16_t opt_code, int bypass_cache_stage, - int no_aggregation, struct module_env* env) -{ - size_t i; - if(env->worker) { - log_err("invalid edns registration: " - "trying to register option after module init phase"); - return 0; - } - - /** - * Checking if we are full first is faster but it does not provide - * the option to change the flags when the array is full. - * It only impacts unbound initialization, leave it for now. - */ - /* Check if the option is already registered. */ - for(i=0; iedns_known_options_num; i++) - if(env->edns_known_options[i].opt_code == opt_code) - break; - /* If it is not yet registered check if we have space to add a new one. */ - if(i == env->edns_known_options_num) { - if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) { - log_err("invalid edns registration: maximum options reached"); - return 0; - } - env->edns_known_options_num++; - } - env->edns_known_options[i].opt_code = opt_code; - env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage; - env->edns_known_options[i].no_aggregation = no_aggregation; - return 1; -} - -int -inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg, - struct module_env* env, int id) -{ - struct inplace_cb* callback; - struct inplace_cb** prevp; - if(env->worker) { - log_err("invalid edns callback registration: " - "trying to register callback after module init phase"); - return 0; - } - - callback = (struct inplace_cb*)calloc(1, sizeof(*callback)); - if(callback == NULL) { - log_err("out of memory during edns callback registration."); - return 0; - } - callback->id = id; - callback->next = NULL; - callback->cb = cb; - callback->cb_arg = cbarg; - - prevp = (struct inplace_cb**) &env->inplace_cb_lists[type]; - /* append at end of list */ - while(*prevp != NULL) - prevp = &((*prevp)->next); - *prevp = callback; - return 1; -} - -void -inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type, - int id) -{ - struct inplace_cb* temp = env->inplace_cb_lists[type]; - struct inplace_cb* prev = NULL; - - while(temp) { - if(temp->id == id) { - if(!prev) { - env->inplace_cb_lists[type] = temp->next; - free(temp); - temp = env->inplace_cb_lists[type]; - } - else { - prev->next = temp->next; - free(temp); - temp = prev->next; - } - } - else { - prev = temp; - temp = temp->next; - } - } -} - -struct edns_known_option* -edns_option_is_known(uint16_t opt_code, struct module_env* env) -{ - size_t i; - for(i=0; iedns_known_options_num; i++) - if(env->edns_known_options[i].opt_code == opt_code) - return env->edns_known_options + i; - return NULL; -} - -int -edns_bypass_cache_stage(struct edns_option* list, struct module_env* env) -{ - size_t i; - for(; list; list=list->next) - for(i=0; iedns_known_options_num; i++) - if(env->edns_known_options[i].opt_code == list->opt_code && - env->edns_known_options[i].bypass_cache_stage == 1) - return 1; - return 0; -} - -int -unique_mesh_state(struct edns_option* list, struct module_env* env) -{ - size_t i; - if(env->unique_mesh) - return 1; - for(; list; list=list->next) - for(i=0; iedns_known_options_num; i++) - if(env->edns_known_options[i].opt_code == list->opt_code && - env->edns_known_options[i].no_aggregation == 1) - return 1; - return 0; -} - -void -log_edns_known_options(enum verbosity_value level, struct module_env* env) -{ - size_t i; - char str[32], *s; - size_t slen; - if(env->edns_known_options_num > 0 && verbosity >= level) { - verbose(level, "EDNS known options:"); - verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:"); - for(i=0; iedns_known_options_num; i++) { - s = str; - slen = sizeof(str); - (void)sldns_wire2str_edns_option_code_print(&s, &slen, - env->edns_known_options[i].opt_code); - verbose(level, " %-8.8s %-19s %-15s", str, - env->edns_known_options[i].bypass_cache_stage?"YES":"NO", - env->edns_known_options[i].no_aggregation?"NO":"YES"); - } - } -} - -void -copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id), - struct module_qstate* super) -{ - /* Overwrite super's was_ratelimited only when it was not set */ - if(!super->was_ratelimited) { - super->was_ratelimited = qstate->was_ratelimited; - } -} diff --git a/crates/libunbound-sys/unbound/util/module.h b/crates/libunbound-sys/unbound/util/module.h deleted file mode 100644 index 5b6fcc93..00000000 --- a/crates/libunbound-sys/unbound/util/module.h +++ /dev/null @@ -1,951 +0,0 @@ -/* - * util/module.h - DNS handling module interface - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains the interface for DNS handling modules. - * - * The module interface uses the DNS modules as state machines. The - * state machines are activated in sequence to operate on queries. Once - * they are done, the reply is passed back. In the usual setup the mesh - * is the caller of the state machines and once things are done sends replies - * and invokes result callbacks. - * - * The module provides a number of functions, listed in the module_func_block. - * The module is inited and destroyed and memory usage queries, for the - * module as a whole, for entire-module state (such as a cache). And per-query - * functions are called, operate to move the state machine and cleanup of - * the per-query state. - * - * Most per-query state should simply be allocated in the query region. - * This is destroyed at the end of the query. - * - * The module environment contains services and information and caches - * shared by the modules and the rest of the system. It also contains - * function pointers for module-specific tasks (like sending queries). - * - * *** Example module calls for a normal query - * - * In this example, the query does not need recursion, all the other data - * can be found in the cache. This makes the example shorter. - * - * At the start of the program the iterator module is initialised. - * The iterator module sets up its global state, such as donotquery lists - * and private address trees. - * - * A query comes in, and a mesh entry is created for it. The mesh - * starts the resolution process. The validator module is the first - * in the list of modules, and it is started on this new query. The - * operate() function is called. The validator decides it needs not do - * anything yet until there is a result and returns wait_module, that - * causes the next module in the list to be started. - * - * The next module is the iterator. It is started on the passed query and - * decides to perform a lookup. For this simple example, the delegation - * point information is available, and all the iterator wants to do is - * send a UDP query. The iterator uses env.send_query() to send the - * query. Then the iterator suspends (returns from the operate call). - * - * When the UDP reply comes back (and on errors and timeouts), the - * operate function is called for the query, on the iterator module, - * with the event that there is a reply. The iterator decides that this - * is enough, the work is done. It returns the value finished from the - * operate call, which causes the previous module to be started. - * - * The previous module, the validator module, is started with the event - * that the iterator module is done. The validator decides to validate - * the query. Once it is done (which could take recursive lookups, but - * in this example no recursive lookups are needed), it returns from the - * operate function with finished. - * - * There is no previous module from the validator module, and the mesh - * takes this to mean that the query is finally done. The mesh invokes - * callbacks and sends packets to queriers. - * - * If other modules had been waiting (recursively) on the answer to this - * query, then the mesh will tell them about it. It calls the inform_super - * routine on all the waiting modules, and once that is done it calls all of - * them with the operate() call. During inform_super the query that is done - * still exists and information can be copied from it (but the module should - * not really re-entry codepoints and services). During the operate call - * the modules can use stored state to continue operation with the results. - * (network buffers are used to contain the answer packet during the - * inform_super phase, but after that the network buffers will be cleared - * of their contents so that other tasks can be performed). - * - * *** Example module calls for recursion - * - * A module is called in operate, and it decides that it wants to perform - * recursion. That is, it wants the full state-machine-list to operate on - * a different query. It calls env.attach_sub() to create a new query state. - * The routine returns the newly created state, and potentially the module - * can edit the module-states for the newly created query (i.e. pass along - * some information, like delegation points). The module then suspends, - * returns from the operate routine. - * - * The mesh meanwhile will have the newly created query (or queries) on - * a waiting list, and will call operate() on this query (or queries). - * It starts again at the start of the module list for them. The query - * (or queries) continue to operate their state machines, until they are - * done. When they are done the mesh calls inform_super on the module that - * wanted the recursion. After that the mesh calls operate() on the module - * that wanted to do the recursion, and during this phase the module could, - * for example, decide to create more recursions. - * - * If the module decides it no longer wants the recursive information - * it can call detach_subs. Those queries will still run to completion, - * potentially filling the cache with information. Inform_super is not - * called any more. - * - * The iterator module will fetch items from the cache, so a recursion - * attempt may complete very quickly if the item is in cache. The calling - * module has to wait for completion or eventual timeout. A recursive query - * that times out returns a servfail rcode (servfail is also returned for - * other errors during the lookup). - * - * Results are passed in the qstate, the rcode member is used to pass - * errors without requiring memory allocation, so that the code can continue - * in out-of-memory conditions. If the rcode member is 0 (NOERROR) then - * the dns_msg entry contains a filled out message. This message may - * also contain an rcode that is nonzero, but in this case additional - * information (query, additional) can be passed along. - * - * The rcode and dns_msg are used to pass the result from the the rightmost - * module towards the leftmost modules and then towards the user. - * - * If you want to avoid recursion-cycles where queries need other queries - * that need the first one, use detect_cycle() to see if that will happen. - * - */ - -#ifndef UTIL_MODULE_H -#define UTIL_MODULE_H -#include "util/storage/lruhash.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -struct sldns_buffer; -struct alloc_cache; -struct rrset_cache; -struct key_cache; -struct config_file; -struct slabhash; -struct query_info; -struct edns_data; -struct regional; -struct worker; -struct comm_base; -struct auth_zones; -struct outside_network; -struct module_qstate; -struct ub_randstate; -struct mesh_area; -struct mesh_state; -struct val_anchors; -struct val_neg_cache; -struct iter_forwards; -struct iter_hints; -struct respip_set; -struct respip_client_info; -struct respip_addr_info; - -/** Maximum number of modules in operation */ -#define MAX_MODULE 16 - -/** Maximum number of known edns options */ -#define MAX_KNOWN_EDNS_OPTS 256 - -struct errinf_strlist { - /** next item in list */ - struct errinf_strlist* next; - /** config option string */ - char* str; - /** EDE code companion to the error str */ - int reason_bogus; -}; - -enum inplace_cb_list_type { - /* Inplace callbacks for when a resolved reply is ready to be sent to the - * front.*/ - inplace_cb_reply = 0, - /* Inplace callbacks for when a reply is given from the cache. */ - inplace_cb_reply_cache, - /* Inplace callbacks for when a reply is given with local data - * (or Chaos reply). */ - inplace_cb_reply_local, - /* Inplace callbacks for when the reply is servfail. */ - inplace_cb_reply_servfail, - /* Inplace callbacks for when a query is ready to be sent to the back.*/ - inplace_cb_query, - /* Inplace callback for when a reply is received from the back. */ - inplace_cb_query_response, - /* Inplace callback for when EDNS is parsed on a reply received from the - * back. */ - inplace_cb_edns_back_parsed, - /* Total number of types. Used for array initialization. - * Should always be last. */ - inplace_cb_types_total -}; - - -/** Known edns option. Can be populated during modules' init. */ -struct edns_known_option { - /** type of this edns option */ - uint16_t opt_code; - /** whether the option needs to bypass the cache stage */ - int bypass_cache_stage; - /** whether the option needs mesh aggregation */ - int no_aggregation; -}; - -/** - * Inplace callback list of registered routines to be called. - */ -struct inplace_cb { - /** next in list */ - struct inplace_cb* next; - /** Inplace callback routine */ - void* cb; - void* cb_arg; - /** module id */ - int id; -}; - -/** - * Inplace callback function called before replying. - * Called as func(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, - * region, id, python_callback) - * Where: - * qinfo: the query info. - * qstate: the module state. NULL when calling before the query reaches the - * mesh states. - * rep: reply_info. Could be NULL. - * rcode: the return code. - * edns: the edns_data of the reply. When qstate is NULL, it is also used as - * the edns input. - * opt_list_out: the edns options list for the reply. - * repinfo: reply information for a communication point. NULL when calling - * during the mesh states; the same could be found from - * qstate->mesh_info->reply_list. - * region: region to store data. - * id: module id. - * python_callback: only used for registering a python callback function. - */ -typedef int inplace_cb_reply_func_type(struct query_info* qinfo, - struct module_qstate* qstate, struct reply_info* rep, int rcode, - struct edns_data* edns, struct edns_option** opt_list_out, - struct comm_reply* repinfo, struct regional* region, - struct timeval* start_time, int id, void* callback); - -/** - * Inplace callback function called before sending the query to a nameserver. - * Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, - * id, python_callback) - * Where: - * qinfo: query info. - * flags: flags of the query. - * qstate: query state. - * addr: to which server to send the query. - * addrlen: length of addr. - * zone: name of the zone of the delegation point. wireformat dname. - * This is the delegation point name for which the server is deemed - * authoritative. - * zonelen: length of zone. - * region: region to store data. - * id: module id. - * python_callback: only used for registering a python callback function. - */ -typedef int inplace_cb_query_func_type(struct query_info* qinfo, uint16_t flags, - struct module_qstate* qstate, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region, - int id, void* callback); - -/** - * Inplace callback function called after parsing edns on query reply. - * Called as func(qstate, id, cb_args) - * Where: - * qstate: the query state. - * id: module id. - * cb_args: argument passed when registering callback. - */ -typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate, - int id, void* cb_args); - -/** - * Inplace callback function called after parsing query response. - * Called as func(qstate, response, id, cb_args) - * Where: - * qstate: the query state. - * response: query response. - * id: module id. - * cb_args: argument passed when registering callback. - */ -typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate, - struct dns_msg* response, int id, void* cb_args); - -/** - * Function called when looking for (expired) cached answers during the serve - * expired logic. - * Called as func(qstate, lookup_qinfo) - * Where: - * qstate: the query state. - * lookup_qinfo: the qinfo to lookup for. - */ -typedef struct dns_msg* serve_expired_lookup_func_type( - struct module_qstate* qstate, struct query_info* lookup_qinfo); - -/** - * Module environment. - * Services and data provided to the module. - */ -struct module_env { - /* --- data --- */ - /** config file with config options */ - struct config_file* cfg; - /** shared message cache */ - struct slabhash* msg_cache; - /** shared rrset cache */ - struct rrset_cache* rrset_cache; - /** shared infrastructure cache (edns, lameness) */ - struct infra_cache* infra_cache; - /** shared key cache */ - struct key_cache* key_cache; - - /* --- services --- */ - /** - * Send serviced DNS query to server. UDP/TCP and EDNS is handled. - * operate() should return with wait_reply. Later on a callback - * will cause operate() to be called with event timeout or reply. - * The time until a timeout is calculated from roundtrip timing, - * several UDP retries are attempted. - * @param qinfo: query info. - * @param flags: host order flags word, with opcode and CD bit. - * @param dnssec: if set, EDNS record will have bits set. - * If EDNS_DO bit is set, DO bit is set in EDNS records. - * If BIT_CD is set, CD bit is set in queries with EDNS records. - * @param want_dnssec: if set, the validator wants DNSSEC. Without - * EDNS, the answer is likely to be useless for this domain. - * @param nocaps: do not use caps_for_id, use the qname as given. - * (ignored if caps_for_id is disabled). - * @param check_ratelimit: if set, will check ratelimit before sending out. - * @param addr: where to. - * @param addrlen: length of addr. - * @param zone: delegation point name. - * @param zonelen: length of zone name. - * @param tcp_upstream: use TCP for upstream queries. - * @param ssl_upstream: use SSL for upstream queries. - * @param tls_auth_name: if ssl_upstream, use this name with TLS - * authentication. - * @param q: which query state to reactivate upon return. - * @param was_ratelimited: it will signal back if the query failed to pass the - * ratelimit check. - * @return: false on failure (memory or socket related). no query was - * sent. Or returns an outbound entry with qsent and qstate set. - * This outbound_entry will be used on later module invocations - * that involve this query (timeout, error or reply). - */ - struct outbound_entry* (*send_query)(struct query_info* qinfo, - uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int check_ratelimit, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, - char* tls_auth_name, struct module_qstate* q, int* was_ratelimited); - - /** - * Detach-subqueries. - * Remove all sub-query references from this query state. - * Keeps super-references of those sub-queries correct. - * Updates stat items in mesh_area structure. - * @param qstate: used to find mesh state. - */ - void (*detach_subs)(struct module_qstate* qstate); - - /** - * Attach subquery. - * Creates it if it does not exist already. - * Keeps sub and super references correct. - * Updates stat items in mesh_area structure. - * Pass if it is priming query or not. - * return: - * o if error (malloc) happened. - * o need to initialise the new state (module init; it is a new state). - * so that the next run of the query with this module is successful. - * o no init needed, attachment successful. - * - * @param qstate: the state to find mesh state, and that wants to - * receive the results from the new subquery. - * @param qinfo: what to query for (copied). - * @param qflags: what flags to use (RD, CD flag or not). - * @param prime: if it is a (stub) priming query. - * @param valrec: validation lookup recursion, does not need validation - * @param newq: If the new subquery needs initialisation, it is - * returned, otherwise NULL is returned. - * @return: false on error, true if success (and init may be needed). - */ - int (*attach_sub)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, - int valrec, struct module_qstate** newq); - - /** - * Add detached query. - * Creates it if it does not exist already. - * Does not make super/sub references. - * Performs a cycle detection - for double check - and fails if there is - * one. - * Updates stat items in mesh_area structure. - * Pass if it is priming query or not. - * return: - * o if error (malloc) happened. - * o need to initialise the new state (module init; it is a new state). - * so that the next run of the query with this module is successful. - * o no init needed, attachment successful. - * o added subquery, created if it did not exist already. - * - * @param qstate: the state to find mesh state, and that wants to receive - * the results from the new subquery. - * @param qinfo: what to query for (copied). - * @param qflags: what flags to use (RD / CD flag or not). - * @param prime: if it is a (stub) priming query. - * @param valrec: if it is a validation recursion query (lookup of key, DS). - * @param newq: If the new subquery needs initialisation, it is returned, - * otherwise NULL is returned. - * @param sub: The added mesh state, created if it did not exist already. - * @return: false on error, true if success (and init may be needed). - */ - int (*add_sub)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, - int valrec, struct module_qstate** newq, - struct mesh_state** sub); - - /** - * Kill newly attached sub. If attach_sub returns newq for - * initialisation, but that fails, then this routine will cleanup and - * delete the freshly created sub. - * @param newq: the new subquery that is no longer needed. - * It is removed. - */ - void (*kill_sub)(struct module_qstate* newq); - - /** - * Detect if adding a dependency for qstate on name,type,class will - * create a dependency cycle. - * @param qstate: given mesh querystate. - * @param qinfo: query info for dependency. - * @param flags: query flags of dependency, RD/CD flags. - * @param prime: if dependency is a priming query or not. - * @param valrec: validation lookup recursion, does not need validation - * @return true if the name,type,class exists and the given - * qstate mesh exists as a dependency of that name. Thus - * if qstate becomes dependent on name,type,class then a - * cycle is created. - */ - int (*detect_cycle)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t flags, int prime, - int valrec); - - /** region for temporary usage. May be cleared after operate() call. */ - struct regional* scratch; - /** buffer for temporary usage. May be cleared after operate() call. */ - struct sldns_buffer* scratch_buffer; - /** internal data for daemon - worker thread. */ - struct worker* worker; - /** the worker event base */ - struct comm_base* worker_base; - /** the outside network */ - struct outside_network* outnet; - /** mesh area with query state dependencies */ - struct mesh_area* mesh; - /** allocation service */ - struct alloc_cache* alloc; - /** random table to generate random numbers */ - struct ub_randstate* rnd; - /** time in seconds, converted to integer */ - time_t* now; - /** time in microseconds. Relatively recent. */ - struct timeval* now_tv; - /** is validation required for messages, controls client-facing - * validation status (AD bits) and servfails */ - int need_to_validate; - /** trusted key storage; these are the configured keys, if not NULL, - * otherwise configured by validator. These are the trust anchors, - * and are not primed and ready for validation, but on the bright - * side, they are read only memory, thus no locks and fast. */ - struct val_anchors* anchors; - /** negative cache, configured by the validator. if not NULL, - * contains NSEC record lookup trees. */ - struct val_neg_cache* neg_cache; - /** the 5011-probe timer (if any) */ - struct comm_timer* probe_timer; - /** auth zones */ - struct auth_zones* auth_zones; - /** Mapping of forwarding zones to targets. - * iterator forwarder information. per-thread, created by worker */ - struct iter_forwards* fwds; - /** - * iterator forwarder information. per-thread, created by worker. - * The hints -- these aren't stored in the cache because they don't - * expire. The hints are always used to "prime" the cache. Note - * that both root hints and stub zone "hints" are stored in this - * data structure. - */ - struct iter_hints* hints; - /** module specific data. indexed by module id. */ - void* modinfo[MAX_MODULE]; - - /* Shared linked list of inplace callback functions */ - struct inplace_cb* inplace_cb_lists[inplace_cb_types_total]; - - /** - * Shared array of known edns options (size MAX_KNOWN_EDNS_OPTS). - * Filled by edns literate modules during init. - */ - struct edns_known_option* edns_known_options; - /* Number of known edns options */ - size_t edns_known_options_num; - /** EDNS client string information */ - struct edns_strings* edns_strings; - - /* Make every mesh state unique, do not aggregate mesh states. */ - int unique_mesh; -}; - -/** - * External visible states of the module state machine - * Modules may also have an internal state. - * Modules are supposed to run to completion or until blocked. - */ -enum module_ext_state { - /** initial state - new query */ - module_state_initial = 0, - /** waiting for reply to outgoing network query */ - module_wait_reply, - /** module is waiting for another module */ - module_wait_module, - /** module is waiting for another module; that other is restarted */ - module_restart_next, - /** module is waiting for sub-query */ - module_wait_subquery, - /** module could not finish the query */ - module_error, - /** module is finished with query */ - module_finished -}; - -/** - * Events that happen to modules, that start or wakeup modules. - */ -enum module_ev { - /** new query */ - module_event_new = 0, - /** query passed by other module */ - module_event_pass, - /** reply inbound from server */ - module_event_reply, - /** no reply, timeout or other error */ - module_event_noreply, - /** reply is there, but capitalisation check failed */ - module_event_capsfail, - /** next module is done, and its reply is awaiting you */ - module_event_moddone, - /** error */ - module_event_error -}; - -/** - * Linked list of sockaddrs - * May be allocated such that only 'len' bytes of addr exist for the structure. - */ -struct sock_list { - /** next in list */ - struct sock_list* next; - /** length of addr */ - socklen_t len; - /** sockaddr */ - struct sockaddr_storage addr; -}; - -struct respip_action_info; - -/** - * Struct to hold relevant data for serve expired - */ -struct serve_expired_data { - struct comm_timer* timer; - serve_expired_lookup_func_type* get_cached_answer; -}; - -/** - * Module state, per query. - */ -struct module_qstate { - /** which query is being answered: name, type, class */ - struct query_info qinfo; - /** flags uint16 from query */ - uint16_t query_flags; - /** if this is a (stub or root) priming query (with hints) */ - int is_priming; - /** if this is a validation recursion query that does not get - * validation itself */ - int is_valrec; -#ifdef CLIENT_SUBNET - /** the client network address is needed for the client-subnet option - * when prefetching, but we can't use reply_list in mesh_info, because - * we don't want to send a reply for the internal query. */ - struct sockaddr_storage client_addr; -#endif - - /** comm_reply contains server replies */ - struct comm_reply* reply; - /** the reply message, with message for client and calling module */ - struct dns_msg* return_msg; - /** the rcode, in case of error, instead of a reply message */ - int return_rcode; - /** origin of the reply (can be NULL from cache, list for cnames) */ - struct sock_list* reply_origin; - /** IP blacklist for queries */ - struct sock_list* blacklist; - /** region for this query. Cleared when query process finishes. */ - struct regional* region; - /** failure reason information if val-log-level is high */ - struct errinf_strlist* errinf; - /** which module is executing */ - int curmod; - /** module states */ - enum module_ext_state ext_state[MAX_MODULE]; - /** module specific data for query. indexed by module id. */ - void* minfo[MAX_MODULE]; - /** environment for this query */ - struct module_env* env; - /** mesh related information for this query */ - struct mesh_state* mesh_info; - /** how many seconds before expiry is this prefetched (0 if not) */ - time_t prefetch_leeway; - /** serve expired data */ - struct serve_expired_data* serve_expired_data; - - /** incoming edns options from the front end */ - struct edns_option* edns_opts_front_in; - /** outgoing edns options to the back end */ - struct edns_option* edns_opts_back_out; - /** incoming edns options from the back end */ - struct edns_option* edns_opts_back_in; - /** outgoing edns options to the front end */ - struct edns_option* edns_opts_front_out; - /** whether modules should answer from the cache */ - int no_cache_lookup; - /** whether modules should store answer in the cache */ - int no_cache_store; - /** whether to refetch a fresh answer on finishing this state*/ - int need_refetch; - /** whether the query (or a subquery) was ratelimited */ - int was_ratelimited; - /** time when query was started. This is when the qstate is created. - * This is used so that type NS data cannot be overwritten by them - * expiring while the lookup is in progress, using data fetched from - * those servers. By comparing expiry time with qstarttime for type NS. - */ - time_t qstarttime; - /** whether a message from cachedb will be used for the reply */ - int is_cachedb_answer; - - /** - * Attributes of clients that share the qstate that may affect IP-based - * actions. - */ - struct respip_client_info* client_info; - - /** Extended result of response-ip action processing, mainly - * for logging purposes. */ - struct respip_action_info* respip_action_info; - /** if the query is rpz passthru, no further rpz processing for it */ - int rpz_passthru; - - /** whether the reply should be dropped */ - int is_drop; -}; - -/** - * Module functionality block - */ -struct module_func_block { - /** text string name of module */ - const char* name; - - /** - * init the module. Called once for the global state. - * This is the place to apply settings from the config file. - * @param env: module environment. - * @param id: module id number. - * return: 0 on error - */ - int (*init)(struct module_env* env, int id); - - /** - * de-init, delete, the module. Called once for the global state. - * @param env: module environment. - * @param id: module id number. - */ - void (*deinit)(struct module_env* env, int id); - - /** - * accept a new query, or work further on existing query. - * Changes the qstate->ext_state to be correct on exit. - * @param ev: event that causes the module state machine to - * (re-)activate. - * @param qstate: the query state. - * Note that this method is not allowed to change the - * query state 'identity', that is query info, qflags, - * and priming status. - * Attach a subquery to get results to a different query. - * @param id: module id number that operate() is called on. - * @param outbound: if not NULL this event is due to the reply/timeout - * or error on this outbound query. - * @return: if at exit the ext_state is: - * o wait_module: next module is started. (with pass event). - * o error or finished: previous module is resumed. - * o otherwise it waits until that event happens (assumes - * the service routine to make subrequest or send message - * have been called. - */ - void (*operate)(struct module_qstate* qstate, enum module_ev event, - int id, struct outbound_entry* outbound); - - /** - * inform super querystate about the results from this subquerystate. - * Is called when the querystate is finished. The method invoked is - * the one from the current module active in the super querystate. - * @param qstate: the query state that is finished. - * Examine return_rcode and return_reply in the qstate. - * @param id: module id for this module. - * This coincides with the current module for the super qstate. - * @param super: the super querystate that needs to be informed. - */ - void (*inform_super)(struct module_qstate* qstate, int id, - struct module_qstate* super); - - /** - * clear module specific data - */ - void (*clear)(struct module_qstate* qstate, int id); - - /** - * How much memory is the module specific data using. - * @param env: module environment. - * @param id: the module id. - * @return the number of bytes that are alloced. - */ - size_t (*get_mem)(struct module_env* env, int id); -}; - -/** - * Debug utility: module external qstate to string - * @param s: the state value. - * @return descriptive string. - */ -const char* strextstate(enum module_ext_state s); - -/** - * Debug utility: module event to string - * @param e: the module event value. - * @return descriptive string. - */ -const char* strmodulevent(enum module_ev e); - -/** - * Append text to the error info for validation. - * @param qstate: query state. - * @param str: copied into query region and appended. - * Failures to allocate are logged. - */ -void errinf(struct module_qstate* qstate, const char* str); -void errinf_ede(struct module_qstate* qstate, const char* str, - sldns_ede_code reason_bogus); - -/** - * Append text to error info: from 1.2.3.4 - * @param qstate: query state. - * @param origin: sock list with origin of trouble. - * Every element added. - * If NULL: nothing is added. - * if 0len element: 'from cache' is added. - */ -void errinf_origin(struct module_qstate* qstate, struct sock_list *origin); - -/** - * Append text to error info: for RRset name type class - * @param qstate: query state. - * @param rr: rrset_key. - */ -void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr); - -/** - * Append text to error info: str dname - * @param qstate: query state. - * @param str: explanation string - * @param dname: the dname. - */ -void errinf_dname(struct module_qstate* qstate, const char* str, - uint8_t* dname); - -/** - * Create error info in string. For validation failures. - * @param qstate: query state. - * @return string or NULL on malloc failure (already logged). - * This string is malloced and has to be freed by caller. - */ -char* errinf_to_str_bogus(struct module_qstate* qstate); - -/** - * Check the sldns_ede_code of the qstate->errinf. - * @param qstate: query state. - * @return the latest explicitly set sldns_ede_code or LDNS_EDE_NONE. - */ -sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate); - -/** - * Create error info in string. For other servfails. - * @param qstate: query state. - * @return string or NULL on malloc failure (already logged). - * This string is malloced and has to be freed by caller. - */ -char* errinf_to_str_servfail(struct module_qstate* qstate); - -/** - * Initialize the edns known options by allocating the required space. - * @param env: the module environment. - * @return false on failure (no memory). - */ -int edns_known_options_init(struct module_env* env); - -/** - * Free the allocated space for the known edns options. - * @param env: the module environment. - */ -void edns_known_options_delete(struct module_env* env); - -/** - * Register a known edns option. Overwrite the flags if it is already - * registered. Used before creating workers to register known edns options. - * @param opt_code: the edns option code. - * @param bypass_cache_stage: whether the option interacts with the cache. - * @param no_aggregation: whether the option implies more specific - * aggregation. - * @param env: the module environment. - * @return true on success, false on failure (registering more options than - * allowed or trying to register after the environment is copied to the - * threads.) - */ -int edns_register_option(uint16_t opt_code, int bypass_cache_stage, - int no_aggregation, struct module_env* env); - -/** - * Register an inplace callback function. - * @param cb: pointer to the callback function. - * @param type: inplace callback type. - * @param cbarg: argument for the callback function, or NULL. - * @param env: the module environment. - * @param id: module id. - * @return true on success, false on failure (out of memory or trying to - * register after the environment is copied to the threads.) - */ -int -inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg, - struct module_env* env, int id); - -/** - * Delete callback for specified type and module id. - * @param env: the module environment. - * @param type: inplace callback type. - * @param id: module id. - */ -void -inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type, - int id); - -/** - * Delete all the inplace callback linked lists. - * @param env: the module environment. - */ -void inplace_cb_lists_delete(struct module_env* env); - -/** - * Check if an edns option is known. - * @param opt_code: the edns option code. - * @param env: the module environment. - * @return pointer to registered option if the edns option is known, - * NULL otherwise. - */ -struct edns_known_option* edns_option_is_known(uint16_t opt_code, - struct module_env* env); - -/** - * Check if an edns option needs to bypass the reply from cache stage. - * @param list: the edns options. - * @param env: the module environment. - * @return true if an edns option needs to bypass the cache stage, - * false otherwise. - */ -int edns_bypass_cache_stage(struct edns_option* list, - struct module_env* env); - -/** - * Check if an unique mesh state is required. Might be triggered by EDNS option - * or set for the complete env. - * @param list: the edns options. - * @param env: the module environment. - * @return true if an edns option needs a unique mesh state, - * false otherwise. - */ -int unique_mesh_state(struct edns_option* list, struct module_env* env); - -/** - * Log the known edns options. - * @param level: the desired verbosity level. - * @param env: the module environment. - */ -void log_edns_known_options(enum verbosity_value level, - struct module_env* env); - -/** - * Copy state that may have happened in the subquery and is always relevant to - * the super. - * @param qstate: query state that finished. - * @param id: module id. - * @param super: the qstate to inform. - */ -void copy_state_to_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -#endif /* UTIL_MODULE_H */ diff --git a/crates/libunbound-sys/unbound/util/net_help.c b/crates/libunbound-sys/unbound/util/net_help.c deleted file mode 100644 index e559c9b2..00000000 --- a/crates/libunbound-sys/unbound/util/net_help.c +++ /dev/null @@ -1,1741 +0,0 @@ -/* - * util/net_help.c - implementation of the network helper code - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Implementation of net_help.h. - */ - -#include "config.h" -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_NETIOAPI_H -#include -#endif -#include "util/net_help.h" -#include "util/log.h" -#include "util/data/dname.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "sldns/parseutil.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" -#include -#ifdef HAVE_OPENSSL_SSL_H -#include -#include -#include -#endif -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif -#ifdef HAVE_OPENSSL_CORE_NAMES_H -#include -#endif -#ifdef USE_WINSOCK -#include -#endif -#ifdef HAVE_NGHTTP2_NGHTTP2_H -#include -#endif - -/** max length of an IP address (the address portion) that we allow */ -#define MAX_ADDR_STRLEN 128 /* characters */ -/** default value for EDNS ADVERTISED size */ -uint16_t EDNS_ADVERTISED_SIZE = 4096; - -/** minimal responses when positive answer: default is no */ -int MINIMAL_RESPONSES = 0; - -/** rrset order roundrobin: default is yes */ -int RRSET_ROUNDROBIN = 1; - -/** log tag queries with name instead of 'info' for filtering */ -int LOG_TAG_QUERYREPLY = 0; - -static struct tls_session_ticket_key { - unsigned char *key_name; - unsigned char *aes_key; - unsigned char *hmac_key; -} *ticket_keys; - -#ifdef HAVE_SSL -/** - * callback TLS session ticket encrypt and decrypt - * For use with SSL_CTX_set_tlsext_ticket_key_cb or - * SSL_CTX_set_tlsext_ticket_key_evp_cb - * @param s: the SSL_CTX to use (from connect_sslctx_create()) - * @param key_name: secret name, 16 bytes - * @param iv: up to EVP_MAX_IV_LENGTH. - * @param evp_ctx: the evp cipher context, function sets this. - * @param hmac_ctx: the hmac context, function sets this. - * with ..key_cb it is of type HMAC_CTX* - * with ..key_evp_cb it is of type EVP_MAC_CTX* - * @param enc: 1 is encrypt, 0 is decrypt - * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket - * (the ticket is decrypt only). and <0 for failures. - */ -int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name, - unsigned char* iv, EVP_CIPHER_CTX *evp_ctx, -#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - EVP_MAC_CTX *hmac_ctx, -#else - HMAC_CTX* hmac_ctx, -#endif - int enc); -#endif /* HAVE_SSL */ - -/* returns true is string addr is an ip6 specced address */ -int -str_is_ip6(const char* str) -{ - if(strchr(str, ':')) - return 1; - else return 0; -} - -int -fd_set_nonblock(int s) -{ -#ifdef HAVE_FCNTL - int flag; - if((flag = fcntl(s, F_GETFL)) == -1) { - log_err("can't fcntl F_GETFL: %s", strerror(errno)); - flag = 0; - } - flag |= O_NONBLOCK; - if(fcntl(s, F_SETFL, flag) == -1) { - log_err("can't fcntl F_SETFL: %s", strerror(errno)); - return 0; - } -#elif defined(HAVE_IOCTLSOCKET) - unsigned long on = 1; - if(ioctlsocket(s, FIONBIO, &on) != 0) { - log_err("can't ioctlsocket FIONBIO on: %s", - wsa_strerror(WSAGetLastError())); - } -#endif - return 1; -} - -int -fd_set_block(int s) -{ -#ifdef HAVE_FCNTL - int flag; - if((flag = fcntl(s, F_GETFL)) == -1) { - log_err("cannot fcntl F_GETFL: %s", strerror(errno)); - flag = 0; - } - flag &= ~O_NONBLOCK; - if(fcntl(s, F_SETFL, flag) == -1) { - log_err("cannot fcntl F_SETFL: %s", strerror(errno)); - return 0; - } -#elif defined(HAVE_IOCTLSOCKET) - unsigned long off = 0; - if(ioctlsocket(s, FIONBIO, &off) != 0) { - if(WSAGetLastError() != WSAEINVAL || verbosity >= 4) - log_err("can't ioctlsocket FIONBIO off: %s", - wsa_strerror(WSAGetLastError())); - } -#endif - return 1; -} - -int -is_pow2(size_t num) -{ - if(num == 0) return 1; - return (num & (num-1)) == 0; -} - -void* -memdup(void* data, size_t len) -{ - void* d; - if(!data) return NULL; - if(len == 0) return NULL; - d = malloc(len); - if(!d) return NULL; - memcpy(d, data, len); - return d; -} - -void -log_addr(enum verbosity_value v, const char* str, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - uint16_t port; - const char* family = "unknown"; - char dest[100]; - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - if(verbosity < v) - return; - switch(af) { - case AF_INET: family="ip4"; break; - case AF_INET6: family="ip6"; - sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; - break; - case AF_LOCAL: - dest[0]=0; - (void)inet_ntop(af, sinaddr, dest, - (socklen_t)sizeof(dest)); - verbose(v, "%s local %s", str, dest); - return; /* do not continue and try to get port */ - default: break; - } - if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { - (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); - } - dest[sizeof(dest)-1] = 0; - port = ntohs(((struct sockaddr_in*)addr)->sin_port); - if(verbosity >= 4) - verbose(v, "%s %s %s port %d (len %d)", str, family, dest, - (int)port, (int)addrlen); - else verbose(v, "%s %s port %d", str, dest, (int)port); -} - -int -extstrtoaddr(const char* str, struct sockaddr_storage* addr, - socklen_t* addrlen, int port) -{ - char* s; - if((s=strchr(str, '@'))) { - char buf[MAX_ADDR_STRLEN]; - if(s-str >= MAX_ADDR_STRLEN) { - return 0; - } - (void)strlcpy(buf, str, sizeof(buf)); - buf[s-str] = 0; - port = atoi(s+1); - if(port == 0 && strcmp(s+1,"0")!=0) { - return 0; - } - return ipstrtoaddr(buf, port, addr, addrlen); - } - return ipstrtoaddr(str, port, addr, addrlen); -} - -int -ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, - socklen_t* addrlen) -{ - uint16_t p; - if(!ip) return 0; - p = (uint16_t) port; - if(str_is_ip6(ip)) { - char buf[MAX_ADDR_STRLEN]; - char* s; - struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; - *addrlen = (socklen_t)sizeof(struct sockaddr_in6); - memset(sa, 0, *addrlen); - sa->sin6_family = AF_INET6; - sa->sin6_port = (in_port_t)htons(p); - if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ - if(s-ip >= MAX_ADDR_STRLEN) - return 0; - (void)strlcpy(buf, ip, sizeof(buf)); - buf[s-ip]=0; -#ifdef HAVE_IF_NAMETOINDEX - if (!(sa->sin6_scope_id = if_nametoindex(s+1))) -#endif /* HAVE_IF_NAMETOINDEX */ - sa->sin6_scope_id = (uint32_t)atoi(s+1); - ip = buf; - } - if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { - return 0; - } - } else { /* ip4 */ - struct sockaddr_in* sa = (struct sockaddr_in*)addr; - *addrlen = (socklen_t)sizeof(struct sockaddr_in); - memset(sa, 0, *addrlen); - sa->sin_family = AF_INET; - sa->sin_port = (in_port_t)htons(p); - if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { - return 0; - } - } - return 1; -} - -int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, - socklen_t* addrlen, int* net) -{ - char buf[64]; - char* s; - *net = (str_is_ip6(str)?128:32); - if((s=strchr(str, '/'))) { - if(atoi(s+1) > *net) { - log_err("netblock too large: %s", str); - return 0; - } - *net = atoi(s+1); - if(*net == 0 && strcmp(s+1, "0") != 0) { - log_err("cannot parse netblock: '%s'", str); - return 0; - } - strlcpy(buf, str, sizeof(buf)); - s = strchr(buf, '/'); - if(s) *s = 0; - s = buf; - } - if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { - log_err("cannot parse ip address: '%s'", str); - return 0; - } - if(s) { - addr_mask(addr, *addrlen, *net); - } - return 1; -} - -/* RPZ format address dname to network byte order address */ -static int ipdnametoaddr(uint8_t* dname, size_t dnamelen, - struct sockaddr_storage* addr, socklen_t* addrlen, int* af) -{ - uint8_t* ia; - int dnamelabs = dname_count_labels(dname); - uint8_t lablen; - char* e = NULL; - int z = 0; - size_t len = 0; - int i; - *af = AF_INET; - - /* need 1 byte for label length */ - if(dnamelen < 1) - return 0; - - if(dnamelabs > 6 || - dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) { - *af = AF_INET6; - } - len = *dname; - lablen = *dname++; - i = (*af == AF_INET) ? 3 : 15; - if(*af == AF_INET6) { - struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; - *addrlen = (socklen_t)sizeof(struct sockaddr_in6); - memset(sa, 0, *addrlen); - sa->sin6_family = AF_INET6; - ia = (uint8_t*)&sa->sin6_addr; - } else { /* ip4 */ - struct sockaddr_in* sa = (struct sockaddr_in*)addr; - *addrlen = (socklen_t)sizeof(struct sockaddr_in); - memset(sa, 0, *addrlen); - sa->sin_family = AF_INET; - ia = (uint8_t*)&sa->sin_addr; - } - while(lablen && i >= 0 && len <= dnamelen) { - char buff[LDNS_MAX_LABELLEN+1]; - uint16_t chunk; /* big enough to not overflow on IPv6 hextet */ - if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) || - (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) { - return 0; - } - if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) { - /* Add one or more 0 labels. Address is initialised at - * 0, so just skip the zero part. */ - int zl = 11 - dnamelabs; - if(z || zl < 0) - return 0; - z = 1; - i -= (zl*2); - } else { - memcpy(buff, dname, lablen); - buff[lablen] = '\0'; - chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16); - if(!e || *e != '\0' || (*af == AF_INET && chunk > 255)) - return 0; - if(*af == AF_INET) { - log_assert(i < 4 && i >= 0); - ia[i] = (uint8_t)chunk; - i--; - } else { - log_assert(i < 16 && i >= 1); - /* ia in network byte order */ - ia[i-1] = (uint8_t)(chunk >> 8); - ia[i] = (uint8_t)(chunk & 0x00FF); - i -= 2; - } - } - dname += lablen; - lablen = *dname++; - len += lablen; - } - if(i != -1) - /* input too short */ - return 0; - return 1; -} - -int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, - struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af) -{ - char buff[3 /* 3 digit netblock */ + 1]; - size_t nlablen; - if(dnamelen < 1 || *dname > 3) - /* netblock invalid */ - return 0; - nlablen = *dname; - - if(dnamelen < 1 + nlablen) - return 0; - - memcpy(buff, dname+1, nlablen); - buff[nlablen] = '\0'; - *net = atoi(buff); - if(*net == 0 && strcmp(buff, "0") != 0) - return 0; - dname += nlablen; - dname++; - if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) - return 0; - if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32)) - return 0; - return 1; -} - -int authextstrtoaddr(char* str, struct sockaddr_storage* addr, - socklen_t* addrlen, char** auth_name) -{ - char* s; - int port = UNBOUND_DNS_PORT; - if((s=strchr(str, '@'))) { - char buf[MAX_ADDR_STRLEN]; - size_t len = (size_t)(s-str); - char* hash = strchr(s+1, '#'); - if(hash) { - *auth_name = hash+1; - } else { - *auth_name = NULL; - } - if(len >= MAX_ADDR_STRLEN) { - return 0; - } - (void)strlcpy(buf, str, sizeof(buf)); - buf[len] = 0; - port = atoi(s+1); - if(port == 0) { - if(!hash && strcmp(s+1,"0")!=0) - return 0; - if(hash && strncmp(s+1,"0#",2)!=0) - return 0; - } - return ipstrtoaddr(buf, port, addr, addrlen); - } - if((s=strchr(str, '#'))) { - char buf[MAX_ADDR_STRLEN]; - size_t len = (size_t)(s-str); - if(len >= MAX_ADDR_STRLEN) { - return 0; - } - (void)strlcpy(buf, str, sizeof(buf)); - buf[len] = 0; - port = UNBOUND_DNS_OVER_TLS_PORT; - *auth_name = s+1; - return ipstrtoaddr(buf, port, addr, addrlen); - } - *auth_name = NULL; - return ipstrtoaddr(str, port, addr, addrlen); -} - -uint8_t* authextstrtodname(char* str, int* port, char** auth_name) -{ - char* s; - uint8_t* dname; - size_t dname_len; - *port = UNBOUND_DNS_PORT; - *auth_name = NULL; - if((s=strchr(str, '@'))) { - char* hash = strchr(s+1, '#'); - if(hash) { - *auth_name = hash+1; - } else { - *auth_name = NULL; - } - *port = atoi(s+1); - if(*port == 0) { - if(!hash && strcmp(s+1,"0")!=0) - return 0; - if(hash && strncmp(s+1,"0#",2)!=0) - return 0; - } - *s = 0; - dname = sldns_str2wire_dname(str, &dname_len); - *s = '@'; - } else if((s=strchr(str, '#'))) { - *port = UNBOUND_DNS_OVER_TLS_PORT; - *auth_name = s+1; - *s = 0; - dname = sldns_str2wire_dname(str, &dname_len); - *s = '#'; - } else { - dname = sldns_str2wire_dname(str, &dname_len); - } - return dname; -} - -/** store port number into sockaddr structure */ -void -sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port) -{ - if(addr_is_ip6(addr, addrlen)) { - struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; - sa->sin6_port = (in_port_t)htons((uint16_t)port); - } else { - struct sockaddr_in* sa = (struct sockaddr_in*)addr; - sa->sin_port = (in_port_t)htons((uint16_t)port); - } -} - -void -log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, - uint16_t type, uint16_t dclass) -{ - char buf[LDNS_MAX_DOMAINLEN+1]; - char t[12], c[12]; - const char *ts, *cs; - if(verbosity < v) - return; - dname_str(name, buf); - if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; - else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; - else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; - else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; - else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; - else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; - else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) - ts = sldns_rr_descript(type)->_name; - else { - snprintf(t, sizeof(t), "TYPE%d", (int)type); - ts = t; - } - if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && - sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) - cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; - else { - snprintf(c, sizeof(c), "CLASS%d", (int)dclass); - cs = c; - } - log_info("%s %s %s %s", str, buf, ts, cs); -} - -void -log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass) -{ - char buf[LDNS_MAX_DOMAINLEN+1]; - char t[12], c[12]; - const char *ts, *cs; - dname_str(name, buf); - if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; - else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; - else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; - else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; - else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; - else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; - else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name) - ts = sldns_rr_descript(type)->_name; - else { - snprintf(t, sizeof(t), "TYPE%d", (int)type); - ts = t; - } - if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) && - sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name) - cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name; - else { - snprintf(c, sizeof(c), "CLASS%d", (int)dclass); - cs = c; - } - if(LOG_TAG_QUERYREPLY) - log_query("%s %s %s %s", str, buf, ts, cs); - else log_info("%s %s %s %s", str, buf, ts, cs); -} - -void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - uint16_t port; - const char* family = "unknown_family "; - char namebuf[LDNS_MAX_DOMAINLEN+1]; - char dest[100]; - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - if(verbosity < v) - return; - switch(af) { - case AF_INET: family=""; break; - case AF_INET6: family=""; - sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; - break; - case AF_LOCAL: family="local "; break; - default: break; - } - if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { - (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); - } - dest[sizeof(dest)-1] = 0; - port = ntohs(((struct sockaddr_in*)addr)->sin_port); - dname_str(zone, namebuf); - if(af != AF_INET && af != AF_INET6) - verbose(v, "%s <%s> %s%s#%d (addrlen %d)", - str, namebuf, family, dest, (int)port, (int)addrlen); - else verbose(v, "%s <%s> %s%s#%d", - str, namebuf, family, dest, (int)port); -} - -void log_err_addr(const char* str, const char* err, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - uint16_t port; - char dest[100]; - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - if(af == AF_INET6) - sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; - if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { - (void)strlcpy(dest, "(inet_ntop error)", sizeof(dest)); - } - dest[sizeof(dest)-1] = 0; - port = ntohs(((struct sockaddr_in*)addr)->sin_port); - if(verbosity >= 4) - log_err("%s: %s for %s port %d (len %d)", str, err, dest, - (int)port, (int)addrlen); - else log_err("%s: %s for %s port %d", str, err, dest, (int)port); -} - -int -sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, - struct sockaddr_storage* addr2, socklen_t len2) -{ - struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; - struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; - struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; - struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; - if(len1 < len2) - return -1; - if(len1 > len2) - return 1; - log_assert(len1 == len2); - if( p1_in->sin_family < p2_in->sin_family) - return -1; - if( p1_in->sin_family > p2_in->sin_family) - return 1; - log_assert( p1_in->sin_family == p2_in->sin_family ); - /* compare ip4 */ - if( p1_in->sin_family == AF_INET ) { - /* just order it, ntohs not required */ - if(p1_in->sin_port < p2_in->sin_port) - return -1; - if(p1_in->sin_port > p2_in->sin_port) - return 1; - log_assert(p1_in->sin_port == p2_in->sin_port); - return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); - } else if (p1_in6->sin6_family == AF_INET6) { - /* just order it, ntohs not required */ - if(p1_in6->sin6_port < p2_in6->sin6_port) - return -1; - if(p1_in6->sin6_port > p2_in6->sin6_port) - return 1; - log_assert(p1_in6->sin6_port == p2_in6->sin6_port); - return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, - INET6_SIZE); - } else { - /* eek unknown type, perform this comparison for sanity. */ - return memcmp(addr1, addr2, len1); - } -} - -int -sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, - struct sockaddr_storage* addr2, socklen_t len2) -{ - struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; - struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; - struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; - struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; - if(len1 < len2) - return -1; - if(len1 > len2) - return 1; - log_assert(len1 == len2); - if( p1_in->sin_family < p2_in->sin_family) - return -1; - if( p1_in->sin_family > p2_in->sin_family) - return 1; - log_assert( p1_in->sin_family == p2_in->sin_family ); - /* compare ip4 */ - if( p1_in->sin_family == AF_INET ) { - return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); - } else if (p1_in6->sin6_family == AF_INET6) { - return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, - INET6_SIZE); - } else { - /* eek unknown type, perform this comparison for sanity. */ - return memcmp(addr1, addr2, len1); - } -} - -int -addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) -{ - if(len == (socklen_t)sizeof(struct sockaddr_in6) && - ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) - return 1; - else return 0; -} - -void -addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) -{ - uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; - int i, max; - uint8_t* s; - if(addr_is_ip6(addr, len)) { - s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; - max = 128; - } else { - s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; - max = 32; - } - if(net >= max) - return; - for(i=net/8+1; isin6_addr; - s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; - to = 16; - } else { - s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; - s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; - to = 4; - } - /* match = bits_in_common(s1, s2, to); */ - for(i=0; i min) match = min; - return match; -} - -void -addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, - char* buf, size_t len) -{ - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - if(addr_is_ip6(addr, addrlen)) - sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; - if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { - snprintf(buf, len, "(inet_ntop_error)"); - } -} - -int -prefixnet_is_nat64(int prefixnet) -{ - return (prefixnet == 32 || prefixnet == 40 || - prefixnet == 48 || prefixnet == 56 || - prefixnet == 64 || prefixnet == 96); -} - -void -addr_to_nat64(const struct sockaddr_storage* addr, - const struct sockaddr_storage* nat64_prefix, - socklen_t nat64_prefixlen, int nat64_prefixnet, - struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen) -{ - struct sockaddr_in *sin = (struct sockaddr_in *)addr; - struct sockaddr_in6 *sin6; - uint8_t *v4_byte; - - /* This needs to be checked by the caller */ - log_assert(addr->ss_family == AF_INET); - /* Current usage is only from config values; prefix lengths enforced - * during config validation */ - log_assert(prefixnet_is_nat64(nat64_prefixnet)); - - *nat64_addr = *nat64_prefix; - *nat64_addrlen = nat64_prefixlen; - - sin6 = (struct sockaddr_in6 *)nat64_addr; - sin6->sin6_flowinfo = 0; - sin6->sin6_port = sin->sin_port; - - nat64_prefixnet = nat64_prefixnet / 8; - - v4_byte = (uint8_t *)&sin->sin_addr.s_addr; - for(int i = 0; i < 4; i++) { - if(nat64_prefixnet == 8) { - /* bits 64...71 are MBZ */ - sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0; - } - sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++; - } -} - -int -addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) -{ - /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ - const uint8_t map_prefix[16] = - {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; - uint8_t* s; - if(!addr_is_ip6(addr, addrlen)) - return 0; - /* s is 16 octet ipv6 address string */ - s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; - return (memcmp(s, map_prefix, 12) == 0); -} - -int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) -{ - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) - && memcmp(sinaddr, "\377\377\377\377", 4) == 0; -} - -int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) -{ - int af = (int)((struct sockaddr_in*)addr)->sin_family; - void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; - void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; - if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) - && memcmp(sinaddr, "\000\000\000\000", 4) == 0) - return 1; - else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) - && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000", 16) == 0) - return 1; - return 0; -} - -void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, - socklen_t len, struct regional* region) -{ - struct sock_list* add = (struct sock_list*)regional_alloc(region, - sizeof(*add) - sizeof(add->addr) + (size_t)len); - if(!add) { - log_err("out of memory in socketlist insert"); - return; - } - log_assert(list); - add->next = *list; - add->len = len; - *list = add; - if(len) memmove(&add->addr, addr, len); -} - -void sock_list_prepend(struct sock_list** list, struct sock_list* add) -{ - struct sock_list* last = add; - if(!last) - return; - while(last->next) - last = last->next; - last->next = *list; - *list = add; -} - -int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, - socklen_t len) -{ - while(list) { - if(len == list->len) { - if(len == 0 || sockaddr_cmp_addr(addr, len, - &list->addr, list->len) == 0) - return 1; - } - list = list->next; - } - return 0; -} - -void sock_list_merge(struct sock_list** list, struct regional* region, - struct sock_list* add) -{ - struct sock_list* p; - for(p=add; p; p=p->next) { - if(!sock_list_find(*list, &p->addr, p->len)) - sock_list_insert(list, &p->addr, p->len, region); - } -} - -void -log_crypto_err(const char* str) -{ -#ifdef HAVE_SSL - log_crypto_err_code(str, ERR_get_error()); -#else - (void)str; -#endif /* HAVE_SSL */ -} - -void log_crypto_err_code(const char* str, unsigned long err) -{ -#ifdef HAVE_SSL - /* error:[error code]:[library name]:[function name]:[reason string] */ - char buf[128]; - unsigned long e; - ERR_error_string_n(err, buf, sizeof(buf)); - log_err("%s crypto %s", str, buf); - while( (e=ERR_get_error()) ) { - ERR_error_string_n(e, buf, sizeof(buf)); - log_err("and additionally crypto %s", buf); - } -#else - (void)str; - (void)err; -#endif /* HAVE_SSL */ -} - -#ifdef HAVE_SSL -/** log certificate details */ -void -log_cert(unsigned level, const char* str, void* cert) -{ - BIO* bio; - char nul = 0; - char* pp = NULL; - long len; - if(verbosity < level) return; - bio = BIO_new(BIO_s_mem()); - if(!bio) return; - X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1 - ^(X509_FLAG_NO_SUBJECT - |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY - |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX - |X509_FLAG_NO_ATTRIBUTES)); - BIO_write(bio, &nul, (int)sizeof(nul)); - len = BIO_get_mem_data(bio, &pp); - if(len != 0 && pp) { - /* reduce size of cert printout */ - char* s; - while((s=strstr(pp, " "))!=NULL) - memmove(s, s+1, strlen(s+1)+1); - while((s=strstr(pp, "\t\t"))!=NULL) - memmove(s, s+1, strlen(s+1)+1); - verbose(level, "%s: \n%s", str, pp); - } - BIO_free(bio); -} -#endif /* HAVE_SSL */ - -#if defined(HAVE_SSL) && defined(HAVE_NGHTTP2) && defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) -static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out, - unsigned char* outlen, const unsigned char* in, unsigned int inlen, - void* ATTR_UNUSED(arg)) -{ - int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, - inlen); - if(rv == -1) { - return SSL_TLSEXT_ERR_NOACK; - } - /* either http/1.1 or h2 selected */ - return SSL_TLSEXT_ERR_OK; -} -#endif - -int -listen_sslctx_setup(void* ctxt) -{ -#ifdef HAVE_SSL - SSL_CTX* ctx = (SSL_CTX*)ctxt; - /* no SSLv2, SSLv3 because has defects */ -#if SSL_OP_NO_SSLv2 != 0 - if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) - != SSL_OP_NO_SSLv2){ - log_crypto_err("could not set SSL_OP_NO_SSLv2"); - return 0; - } -#endif - if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) - != SSL_OP_NO_SSLv3){ - log_crypto_err("could not set SSL_OP_NO_SSLv3"); - return 0; - } -#if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) - /* if we have tls 1.1 disable 1.0 */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) - != SSL_OP_NO_TLSv1){ - log_crypto_err("could not set SSL_OP_NO_TLSv1"); - return 0; - } -#endif -#if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) - /* if we have tls 1.2 disable 1.1 */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) - != SSL_OP_NO_TLSv1_1){ - log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); - return 0; - } -#endif -#if defined(SSL_OP_NO_RENEGOTIATION) - /* disable client renegotiation */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & - SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { - log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); - return 0; - } -#endif -#if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) - /* if we detect system-wide crypto policies, use those */ - if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) { - /* if we have sha256, set the cipher list to have no known vulns */ - if(!SSL_CTX_set_cipher_list(ctx, "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256")) - log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); - } -#endif -#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) - /* ignore errors when peers do not send the mandatory close_notify - * alert on shutdown. - * Relevant for openssl >= 3 */ - if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & - SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { - log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); - return 0; - } -#endif - - if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & - SSL_OP_CIPHER_SERVER_PREFERENCE) != - SSL_OP_CIPHER_SERVER_PREFERENCE) { - log_crypto_err("could not set SSL_OP_CIPHER_SERVER_PREFERENCE"); - return 0; - } - -#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL - SSL_CTX_set_security_level(ctx, 0); -#endif -#if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2) - SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL); -#endif -#else - (void)ctxt; -#endif /* HAVE_SSL */ - return 1; -} - -void -listen_sslctx_setup_2(void* ctxt) -{ -#ifdef HAVE_SSL - SSL_CTX* ctx = (SSL_CTX*)ctxt; - (void)ctx; -#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO - if(!SSL_CTX_set_ecdh_auto(ctx,1)) { - log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE"); - } -#elif defined(USE_ECDSA) - if(1) { - EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); - if (!ecdh) { - log_crypto_err("could not find p256, not enabling ECDHE"); - } else { - if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) { - log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE"); - } - EC_KEY_free (ecdh); - } - } -#endif -#else - (void)ctxt; -#endif /* HAVE_SSL */ -} - -void* listen_sslctx_create(char* key, char* pem, char* verifypem) -{ -#ifdef HAVE_SSL - SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); - if(!ctx) { - log_crypto_err("could not SSL_CTX_new"); - return NULL; - } - if(!key || key[0] == 0) { - log_err("error: no tls-service-key file specified"); - SSL_CTX_free(ctx); - return NULL; - } - if(!pem || pem[0] == 0) { - log_err("error: no tls-service-pem file specified"); - SSL_CTX_free(ctx); - return NULL; - } - if(!listen_sslctx_setup(ctx)) { - SSL_CTX_free(ctx); - return NULL; - } - if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { - log_err("error for cert file: %s", pem); - log_crypto_err("error in SSL_CTX use_certificate_chain_file"); - SSL_CTX_free(ctx); - return NULL; - } - if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { - log_err("error for private key file: %s", key); - log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); - SSL_CTX_free(ctx); - return NULL; - } - if(!SSL_CTX_check_private_key(ctx)) { - log_err("error for key file: %s", key); - log_crypto_err("Error in SSL_CTX check_private_key"); - SSL_CTX_free(ctx); - return NULL; - } - listen_sslctx_setup_2(ctx); - if(verifypem && verifypem[0]) { - if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { - log_crypto_err("Error in SSL_CTX verify locations"); - SSL_CTX_free(ctx); - return NULL; - } - SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( - verifypem)); - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); - } - return ctx; -#else - (void)key; (void)pem; (void)verifypem; - return NULL; -#endif -} - -#ifdef USE_WINSOCK -/* For windows, the CA trust store is not read by openssl. - Add code to open the trust store using wincrypt API and add - the root certs into openssl trust store */ -static int -add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx) -{ - HCERTSTORE hSystemStore; - PCCERT_CONTEXT pTargetCert = NULL; - X509_STORE* store; - - verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store"); - - /* load just once per context lifetime for this version - TODO: dynamically update CA trust changes as they are available */ - if (!tls_ctx) - return 0; - - /* Call wincrypt's CertOpenStore to open the CA root store. */ - - if ((hSystemStore = CertOpenStore( - CERT_STORE_PROV_SYSTEM, - 0, - 0, - /* NOTE: mingw does not have this const: replace with 1 << 16 from code - CERT_SYSTEM_STORE_CURRENT_USER, */ - 1 << 16, - L"root")) == 0) - { - return 0; - } - - store = SSL_CTX_get_cert_store(tls_ctx); - if (!store) - return 0; - - /* failure if the CA store is empty or the call fails */ - if ((pTargetCert = CertEnumCertificatesInStore( - hSystemStore, pTargetCert)) == 0) { - verbose(VERB_ALGO, "CA certificate store for Windows is empty."); - return 0; - } - /* iterate over the windows cert store and add to openssl store */ - do - { - X509 *cert1 = d2i_X509(NULL, - (const unsigned char **)&pTargetCert->pbCertEncoded, - pTargetCert->cbCertEncoded); - if (!cert1) { - unsigned long error = ERR_get_error(); - /* return error if a cert fails */ - verbose(VERB_ALGO, "%s %d:%s", - "Unable to parse certificate in memory", - (int)error, ERR_error_string(error, NULL)); - return 0; - } - else { - /* return error if a cert add to store fails */ - if (X509_STORE_add_cert(store, cert1) == 0) { - unsigned long error = ERR_peek_last_error(); - - /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the - * certificate is already in the store. */ - if(ERR_GET_LIB(error) != ERR_LIB_X509 || - ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { - error = ERR_get_error(); - verbose(VERB_ALGO, "%s %d:%s\n", - "Error adding certificate", (int)error, - ERR_error_string(error, NULL)); - X509_free(cert1); - return 0; - } - } - X509_free(cert1); - } - } while ((pTargetCert = CertEnumCertificatesInStore( - hSystemStore, pTargetCert)) != 0); - - /* Clean up memory and quit. */ - if (pTargetCert) - CertFreeCertificateContext(pTargetCert); - if (hSystemStore) - { - if (!CertCloseStore( - hSystemStore, 0)) - return 0; - } - verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully"); - return 1; -} -#endif /* USE_WINSOCK */ - -void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) -{ -#ifdef HAVE_SSL - SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); - if(!ctx) { - log_crypto_err("could not allocate SSL_CTX pointer"); - return NULL; - } -#if SSL_OP_NO_SSLv2 != 0 - if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) - != SSL_OP_NO_SSLv2) { - log_crypto_err("could not set SSL_OP_NO_SSLv2"); - SSL_CTX_free(ctx); - return NULL; - } -#endif - if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) - != SSL_OP_NO_SSLv3) { - log_crypto_err("could not set SSL_OP_NO_SSLv3"); - SSL_CTX_free(ctx); - return NULL; - } -#if defined(SSL_OP_NO_RENEGOTIATION) - /* disable client renegotiation */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & - SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { - log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); - SSL_CTX_free(ctx); - return 0; - } -#endif -#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) - /* ignore errors when peers do not send the mandatory close_notify - * alert on shutdown. - * Relevant for openssl >= 3 */ - if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) & - SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) { - log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF"); - SSL_CTX_free(ctx); - return 0; - } -#endif - if(key && key[0]) { - if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) { - log_err("error in client certificate %s", pem); - log_crypto_err("error in certificate file"); - SSL_CTX_free(ctx); - return NULL; - } - if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { - log_err("error in client private key %s", key); - log_crypto_err("error in key file"); - SSL_CTX_free(ctx); - return NULL; - } - if(!SSL_CTX_check_private_key(ctx)) { - log_err("error in client key %s", key); - log_crypto_err("error in SSL_CTX_check_private_key"); - SSL_CTX_free(ctx); - return NULL; - } - } - if((verifypem && verifypem[0]) || wincert) { - if(verifypem && verifypem[0]) { - if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { - log_crypto_err("error in SSL_CTX verify"); - SSL_CTX_free(ctx); - return NULL; - } - } -#ifdef USE_WINSOCK - if(wincert) { - if(!add_WIN_cacerts_to_openssl_store(ctx)) { - log_crypto_err("error in add_WIN_cacerts_to_openssl_store"); - SSL_CTX_free(ctx); - return NULL; - } - } -#else - if(wincert) { - if(!SSL_CTX_set_default_verify_paths(ctx)) { - log_crypto_err("error in default_verify_paths"); - SSL_CTX_free(ctx); - return NULL; - } - } -#endif - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); - } - return ctx; -#else - (void)key; (void)pem; (void)verifypem; (void)wincert; - return NULL; -#endif -} - -void* incoming_ssl_fd(void* sslctx, int fd) -{ -#ifdef HAVE_SSL - SSL* ssl = SSL_new((SSL_CTX*)sslctx); - if(!ssl) { - log_crypto_err("could not SSL_new"); - return NULL; - } - SSL_set_accept_state(ssl); - (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); - if(!SSL_set_fd(ssl, fd)) { - log_crypto_err("could not SSL_set_fd"); - SSL_free(ssl); - return NULL; - } - return ssl; -#else - (void)sslctx; (void)fd; - return NULL; -#endif -} - -void* outgoing_ssl_fd(void* sslctx, int fd) -{ -#ifdef HAVE_SSL - SSL* ssl = SSL_new((SSL_CTX*)sslctx); - if(!ssl) { - log_crypto_err("could not SSL_new"); - return NULL; - } - SSL_set_connect_state(ssl); - (void)SSL_set_mode(ssl, (long)SSL_MODE_AUTO_RETRY); - if(!SSL_set_fd(ssl, fd)) { - log_crypto_err("could not SSL_set_fd"); - SSL_free(ssl); - return NULL; - } - return ssl; -#else - (void)sslctx; (void)fd; - return NULL; -#endif -} - -int check_auth_name_for_ssl(char* auth_name) -{ - if(!auth_name) return 1; -#if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - log_err("the query has an auth_name %s, but libssl has no call to " - "perform TLS authentication. Remove that name from config " - "or upgrade the ssl crypto library.", auth_name); - return 0; -#else - return 1; -#endif -} - -/** set the authname on an SSL structure, SSL* ssl */ -int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni) -{ - if(!auth_name) return 1; -#ifdef HAVE_SSL - if(use_sni) { - (void)SSL_set_tlsext_host_name(ssl, auth_name); - } -#else - (void)ssl; - (void)use_sni; -#endif -#ifdef HAVE_SSL_SET1_HOST - SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); - /* setting the hostname makes openssl verify the - * host name in the x509 certificate in the - * SSL connection*/ - if(!SSL_set1_host(ssl, auth_name)) { - log_err("SSL_set1_host failed"); - return 0; - } -#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) - /* openssl 1.0.2 has this function that can be used for - * set1_host like verification */ - if(auth_name) { - X509_VERIFY_PARAM* param = SSL_get0_param(ssl); -# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS - X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); -# endif - if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) { - log_err("X509_VERIFY_PARAM_set1_host failed"); - return 0; - } - SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); - } -#else - verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication"); -#endif /* HAVE_SSL_SET1_HOST */ - return 1; -} - -#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L -/** global lock list for openssl locks */ -static lock_basic_type *ub_openssl_locks = NULL; - -/** callback that gets thread id for openssl */ -#ifdef HAVE_CRYPTO_THREADID_SET_CALLBACK -static void -ub_crypto_id_cb(CRYPTO_THREADID *id) -{ - CRYPTO_THREADID_set_numeric(id, (unsigned long)log_thread_get()); -} -#else -static unsigned long -ub_crypto_id_cb(void) -{ - return (unsigned long)log_thread_get(); -} -#endif - -static void -ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), - int ATTR_UNUSED(line)) -{ - if((mode&CRYPTO_LOCK)) { - lock_basic_lock(&ub_openssl_locks[type]); - } else { - lock_basic_unlock(&ub_openssl_locks[type]); - } -} -#endif /* OPENSSL_THREADS */ - -int ub_openssl_lock_init(void) -{ -#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L - int i; - ub_openssl_locks = (lock_basic_type*)reallocarray( - NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_type)); - if(!ub_openssl_locks) - return 0; - for(i=0; inext) { - s++; - } - keys = calloc(s, sizeof(struct tls_session_ticket_key)); - if(!keys) - return 0; - memset(keys, 0, s*sizeof(*keys)); - ticket_keys = keys; - - for(p = tls_session_ticket_keys; p; p = p->next) { - size_t n; - unsigned char *data; - FILE *f; - - data = (unsigned char *)malloc(80); - if(!data) - return 0; - - f = fopen(p->str, "rb"); - if(!f) { - log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno)); - free(data); - return 0; - } - n = fread(data, 1, 80, f); - fclose(f); - - if(n != 80) { - log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n); - free(data); - return 0; - } - verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str); - - keys->key_name = data; - keys->aes_key = data + 16; - keys->hmac_key = data + 48; - keys++; - } - /* terminate array with NULL key name entry */ - keys->key_name = NULL; -# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) { - log_err("no support for TLS session ticket"); - return 0; - } -# else - if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) { - log_err("no support for TLS session ticket"); - return 0; - } -# endif - return 1; -#else - (void)sslctx; - (void)tls_session_ticket_keys; - return 0; -#endif - -} - -#ifdef HAVE_SSL -int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name, - unsigned char* iv, EVP_CIPHER_CTX *evp_sctx, -#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - EVP_MAC_CTX *hmac_ctx, -#else - HMAC_CTX* hmac_ctx, -#endif - int enc) -{ -#ifdef HAVE_SSL -# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - OSSL_PARAM params[3]; -# else - const EVP_MD *digest; -# endif - const EVP_CIPHER *cipher; - int evp_cipher_length; -# ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - digest = EVP_sha256(); -# endif - cipher = EVP_aes_256_cbc(); - evp_cipher_length = EVP_CIPHER_iv_length(cipher); - if( enc == 1 ) { - /* encrypt */ - verbose(VERB_CLIENT, "start session encrypt"); - memcpy(key_name, ticket_keys->key_name, 16); - if (RAND_bytes(iv, evp_cipher_length) != 1) { - verbose(VERB_CLIENT, "RAND_bytes failed"); - return -1; - } - if (EVP_EncryptInit_ex(evp_sctx, cipher, NULL, ticket_keys->aes_key, iv) != 1) { - verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed"); - return -1; - } -#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - ticket_keys->hmac_key, 32); - params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, - "sha256", 0); - params[2] = OSSL_PARAM_construct_end(); -#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS - EVP_MAC_CTX_set_params(hmac_ctx, params); -#else - EVP_MAC_set_ctx_params(hmac_ctx, params); -#endif -#elif !defined(HMAC_INIT_EX_RETURNS_VOID) - if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) { - verbose(VERB_CLIENT, "HMAC_Init_ex failed"); - return -1; - } -#else - HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL); -#endif - return 1; - } else if (enc == 0) { - /* decrypt */ - struct tls_session_ticket_key *key; - verbose(VERB_CLIENT, "start session decrypt"); - for(key = ticket_keys; key->key_name != NULL; key++) { - if (!memcmp(key_name, key->key_name, 16)) { - verbose(VERB_CLIENT, "Found session_key"); - break; - } - } - if(key->key_name == NULL) { - verbose(VERB_CLIENT, "Not found session_key"); - return 0; - } - -#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB - params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, - key->hmac_key, 32); - params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, - "sha256", 0); - params[2] = OSSL_PARAM_construct_end(); -#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS - EVP_MAC_CTX_set_params(hmac_ctx, params); -#else - EVP_MAC_set_ctx_params(hmac_ctx, params); -#endif -#elif !defined(HMAC_INIT_EX_RETURNS_VOID) - if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) { - verbose(VERB_CLIENT, "HMAC_Init_ex failed"); - return -1; - } -#else - HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL); -#endif - if (EVP_DecryptInit_ex(evp_sctx, cipher, NULL, key->aes_key, iv) != 1) { - log_err("EVP_DecryptInit_ex failed"); - return -1; - } - - return (key == ticket_keys) ? 1 : 2; - } - return -1; -#else - (void)key_name; - (void)iv; - (void)evp_sctx; - (void)hmac_ctx; - (void)enc; - return 0; -#endif -} -#endif /* HAVE_SSL */ - -void -listen_sslctx_delete_ticket_keys(void) -{ - struct tls_session_ticket_key *key; - if(!ticket_keys) return; - for(key = ticket_keys; key->key_name != NULL; key++) { - /* wipe key data from memory*/ -#ifdef HAVE_EXPLICIT_BZERO - explicit_bzero(key->key_name, 80); -#else - memset(key->key_name, 0xdd, 80); -#endif - free(key->key_name); - } - free(ticket_keys); - ticket_keys = NULL; -} - -# ifndef USE_WINSOCK -char* -sock_strerror(int errn) -{ - return strerror(errn); -} - -void -sock_close(int socket) -{ - close(socket); -} - -# else -char* -sock_strerror(int ATTR_UNUSED(errn)) -{ - return wsa_strerror(WSAGetLastError()); -} - -void -sock_close(int socket) -{ - closesocket(socket); -} -# endif /* USE_WINSOCK */ diff --git a/crates/libunbound-sys/unbound/util/net_help.h b/crates/libunbound-sys/unbound/util/net_help.h deleted file mode 100644 index a9de910d..00000000 --- a/crates/libunbound-sys/unbound/util/net_help.h +++ /dev/null @@ -1,549 +0,0 @@ -/* - * util/net_help.h - network help functions - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to perform network related tasks. - */ - -#ifndef NET_HELP_H -#define NET_HELP_H -#include "util/log.h" -#include "util/random.h" -struct sock_list; -struct regional; -struct config_strlist; - -/** DNS constants for uint16_t style flag manipulation. host byteorder. - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ -/** CD flag */ -#define BIT_CD 0x0010 -/** AD flag */ -#define BIT_AD 0x0020 -/** Z flag */ -#define BIT_Z 0x0040 -/** RA flag */ -#define BIT_RA 0x0080 -/** RD flag */ -#define BIT_RD 0x0100 -/** TC flag */ -#define BIT_TC 0x0200 -/** AA flag */ -#define BIT_AA 0x0400 -/** QR flag */ -#define BIT_QR 0x8000 -/** get RCODE bits from uint16 flags */ -#define FLAGS_GET_RCODE(f) ((f) & 0xf) -/** set RCODE bits in uint16 flags */ -#define FLAGS_SET_RCODE(f, r) (f = (((f) & 0xfff0) | (r))) - -/** timeout in milliseconds for UDP queries to auth servers. */ -#define UDP_AUTH_QUERY_TIMEOUT 3000 -/** Advertised version of EDNS capabilities */ -#define EDNS_ADVERTISED_VERSION 0 -/** Advertised size of EDNS capabilities */ -extern uint16_t EDNS_ADVERTISED_SIZE; -/** bits for EDNS bitfield */ -#define EDNS_DO 0x8000 /* Dnssec Ok */ -/** byte size of ip4 address */ -#define INET_SIZE 4 -/** byte size of ip6 address */ -#define INET6_SIZE 16 - -/** DNSKEY zone sign key flag */ -#define DNSKEY_BIT_ZSK 0x0100 -/** DNSKEY secure entry point, KSK flag */ -#define DNSKEY_BIT_SEP 0x0001 - -/** return a random 16-bit number given a random source */ -#define GET_RANDOM_ID(rnd) (((unsigned)ub_random(rnd)>>8) & 0xffff) - -/** define MSG_DONTWAIT for unsupported platforms */ -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 -#endif - -/** minimal responses when positive answer */ -extern int MINIMAL_RESPONSES; - -/** rrset order roundrobin */ -extern int RRSET_ROUNDROBIN; - -/** log tag queries with name instead of 'info' for filtering */ -extern int LOG_TAG_QUERYREPLY; - -/** - * See if string is ip4 or ip6. - * @param str: IP specification. - * @return: true if string addr is an ip6 specced address. - */ -int str_is_ip6(const char* str); - -/** - * Set fd nonblocking. - * @param s: file descriptor. - * @return: 0 on error (error is printed to log). - */ -int fd_set_nonblock(int s); - -/** - * Set fd (back to) blocking. - * @param s: file descriptor. - * @return: 0 on error (error is printed to log). - */ -int fd_set_block(int s); - -/** - * See if number is a power of 2. - * @param num: the value. - * @return: true if the number is a power of 2. - */ -int is_pow2(size_t num); - -/** - * Allocate memory and copy over contents. - * @param data: what to copy over. - * @param len: length of data. - * @return: NULL on malloc failure, or newly malloced data. - */ -void* memdup(void* data, size_t len); - -/** - * Prints the sockaddr in readable format with log_info. Debug helper. - * @param v: at what verbosity level to print this. - * @param str: descriptive string printed with it. - * @param addr: the sockaddr to print. Can be ip4 or ip6. - * @param addrlen: length of addr. - */ -void log_addr(enum verbosity_value v, const char* str, - struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Prints zone name and sockaddr in readable format with log_info. Debug. - * @param v: at what verbosity level to print this. - * @param str: descriptive string printed with it. - * @param zone: DNS domain name, uncompressed wireformat. - * @param addr: the sockaddr to print. Can be ip4 or ip6. - * @param addrlen: length of addr. - */ -void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, - struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Log errno and addr. - * @param str: descriptive string printed with it. - * @param err: errno string to print, i.e. strerror(errno). - * @param addr: the sockaddr to print. Can be ip4 or ip6. - * @param addrlen: length of addr. - */ -void log_err_addr(const char* str, const char* err, - struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Convert address string, with "@port" appendix, to sockaddr. - * Uses DNS port by default. - * @param str: the string - * @param addr: where to store sockaddr. - * @param addrlen: length of stored sockaddr is returned. - * @param port: default port. - * @return 0 on error. - */ -int extstrtoaddr(const char* str, struct sockaddr_storage* addr, - socklen_t* addrlen, int port); - -/** - * Convert ip address string and port to sockaddr. - * @param ip: ip4 or ip6 address string. - * @param port: port number, host format. - * @param addr: where to store sockaddr. - * @param addrlen: length of stored sockaddr is returned. - * @return 0 on error. - */ -int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, - socklen_t* addrlen); - -/** - * Convert ip netblock (ip/netsize) string and port to sockaddr. - * performs a copy internally to avoid writing over 'ip' string. - * @param ip: ip4 or ip6 address string. - * @param port: port number, host format. - * @param addr: where to store sockaddr. - * @param addrlen: length of stored sockaddr is returned. - * @param net: netblock size is returned. - * @return 0 on error. - */ -int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, - socklen_t* addrlen, int* net); - -/** - * Convert address string, with "@port" appendix, to sockaddr. - * It can also have an "#tls-auth-name" appendix (after the port). - * The returned auth_name string is a pointer into the input string. - * Uses DNS port by default; TLS port when a "#tls-auth-name" is configured. - * @param str: the string - * @param addr: where to store sockaddr. - * @param addrlen: length of stored sockaddr is returned. - * @param auth_name: returned pointer to tls_auth_name, or NULL if none. - * @return 0 on error. - */ -int authextstrtoaddr(char* str, struct sockaddr_storage* addr, - socklen_t* addrlen, char** auth_name); - -/** - * Convert domain string, with "@port" appendix, to dname. - * It can also have an "#tls-auth-name" appendix (after the port). - * The return port is the parsed port. - * Uses DNS port by default; TLS port when a "#tls-auth-name" is configured. - * The returned auth_name string is a pointer into the input string. - * @param str: the string - * @param port: pointer to be assigned the parsed port value. - * @param auth_name: returned pointer to tls_auth_name, or NULL if none. - * @return pointer to the dname. - */ -uint8_t* authextstrtodname(char* str, int* port, char** auth_name); - -/** - * Store port number into sockaddr structure - * @param addr: sockaddr structure, ip4 or ip6. - * @param addrlen: length of addr. - * @param port: port number to put into the addr. - */ -void sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, - int port); - -/** - * Print string with neat domain name, type and class. - * @param v: at what verbosity level to print this. - * @param str: string of message. - * @param name: domain name uncompressed wireformat. - * @param type: host format RR type. - * @param dclass: host format RR class. - */ -void log_nametypeclass(enum verbosity_value v, const char* str, - uint8_t* name, uint16_t type, uint16_t dclass); - -/** - * Like log_nametypeclass, but logs with log_query for query logging - */ -void log_query_in(const char* str, uint8_t* name, uint16_t type, - uint16_t dclass); - -/** - * Compare two sockaddrs. Imposes an ordering on the addresses. - * Compares address and port. - * @param addr1: address 1. - * @param len1: lengths of addr1. - * @param addr2: address 2. - * @param len2: lengths of addr2. - * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. - */ -int sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, - struct sockaddr_storage* addr2, socklen_t len2); - -/** - * Compare two sockaddrs. Compares address, not the port. - * @param addr1: address 1. - * @param len1: lengths of addr1. - * @param addr2: address 2. - * @param len2: lengths of addr2. - * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. - */ -int sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, - struct sockaddr_storage* addr2, socklen_t len2); - -/** - * Checkout address family. - * @param addr: the sockaddr to examine. - * @param len: the length of addr. - * @return: true if sockaddr is ip6. - */ -int addr_is_ip6(struct sockaddr_storage* addr, socklen_t len); - -/** - * Make sure the sockaddr ends in zeroes. For tree insertion and subsequent - * comparison. - * @param addr: the ip4 or ip6 addr. - * @param len: length of addr. - * @param net: number of bits to leave untouched, the rest of the netblock - * address is zeroed. - */ -void addr_mask(struct sockaddr_storage* addr, socklen_t len, int net); - -/** - * See how many bits are shared, equal, between two addrs. - * @param addr1: first addr. - * @param net1: netblock size of first addr. - * @param addr2: second addr. - * @param net2: netblock size of second addr. - * @param addrlen: length of first addr and of second addr. - * They must be of the same length (i.e. same type IP4, IP6). - * @return: number of bits the same. - */ -int addr_in_common(struct sockaddr_storage* addr1, int net1, - struct sockaddr_storage* addr2, int net2, socklen_t addrlen); - -/** - * Put address into string, works for IPv4 and IPv6. - * @param addr: address - * @param addrlen: length of address - * @param buf: result string stored here - * @param len: length of buf. - * On failure a string with "error" is stored inside. - */ -void addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, - char* buf, size_t len); - -/** - * Check if the prefix network length is one of the allowed 32, 40, 48, 56, 64, - * or 96. - * @param prefixnet: prefix network length to check. - * @return 1 on success, 0 on failure. - */ -int prefixnet_is_nat64(int prefixnet); - -/** - * Create a NAT64 address from a given address (needs to be IPv4) and a given - * NAT64 prefix. The NAT64 prefix net needs to be one of 32, 40, 48, 56, 64, 96. - * @param addr: IPv4 address. - * @param nat64_prefix: NAT64 prefix. - * @param nat64_prefixlen: NAT64 prefix len. - * @param nat64_prefixnet: NAT64 prefix mask. - * @param nat64_addr: the resulting NAT64 address. - * @param nat64_addrlen: the resulting NAT64 address length. - */ -void addr_to_nat64(const struct sockaddr_storage* addr, - const struct sockaddr_storage* nat64_prefix, - socklen_t nat64_prefixlen, int nat64_prefixnet, - struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen); - -/** - * See if sockaddr is an ipv6 mapped ipv4 address, "::ffff:0.0.0.0" - * @param addr: address - * @param addrlen: length of address - * @return true if so - */ -int addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * See if sockaddr is 255.255.255.255. - * @param addr: address - * @param addrlen: length of address - * @return true if so - */ -int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * See if sockaddr is 0.0.0.0 or ::0. - * @param addr: address - * @param addrlen: length of address - * @return true if so - */ -int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Insert new socket list item. If fails logs error. - * @param list: pointer to pointer to first item. - * @param addr: address or NULL if 'cache'. - * @param len: length of addr, or 0 if 'cache'. - * @param region: where to allocate - */ -void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, - socklen_t len, struct regional* region); - -/** - * Append one list to another. Must both be from same qstate(regional). - * @param list: pointer to result list that is modified. - * @param add: item(s) to add. They are prepended to list. - */ -void sock_list_prepend(struct sock_list** list, struct sock_list* add); - -/** - * Find addr in list. - * @param list: to search in - * @param addr: address to look for. - * @param len: length. Can be 0, look for 'cache entry'. - * @return true if found. - */ -int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, - socklen_t len); - -/** - * Merge socklist into another socket list. Allocates the new entries - * freshly and copies them over, so also performs a region switchover. - * Allocation failures are logged. - * @param list: the destination list (checked for duplicates) - * @param region: where to allocate - * @param add: the list of entries to add. - */ -void sock_list_merge(struct sock_list** list, struct regional* region, - struct sock_list* add); - -/** - * Log libcrypto error with descriptive string. Calls log_err(). - * @param str: what failed. - */ -void log_crypto_err(const char* str); - -/** - * Log libcrypto error from errcode with descriptive string, calls log_err. - * @param str: what failed. - * @param err: error code from ERR_get_error. - */ -void log_crypto_err_code(const char* str, unsigned long err); - -/** - * Log certificate details verbosity, string, of X509 cert - * @param level: verbosity level - * @param str: string to prefix on output - * @param cert: X509* structure. - */ -void log_cert(unsigned level, const char* str, void* cert); - -/** - * Set SSL_OP_NOxxx options on SSL context to disable bad crypto - * @param ctxt: SSL_CTX* - * @return false on failure. - */ -int listen_sslctx_setup(void* ctxt); - -/** - * Further setup of listening SSL context, after keys loaded. - * @param ctxt: SSL_CTX* - */ -void listen_sslctx_setup_2(void* ctxt); - -/** - * create SSL listen context - * @param key: private key file. - * @param pem: public key cert. - * @param verifypem: if nonNULL, verifylocation file. - * return SSL_CTX* or NULL on failure (logged). - */ -void* listen_sslctx_create(char* key, char* pem, char* verifypem); - -/** - * create SSL connect context - * @param key: if nonNULL (also pem nonNULL), the client private key. - * @param pem: client public key (or NULL if key is NULL). - * @param verifypem: if nonNULL used for verifylocation file. - * @param wincert: add system certificate store to ctx (add to verifypem ca - * certs). - * @return SSL_CTX* or NULL on failure (logged). - */ -void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert); - -/** - * accept a new fd and wrap it in a BIO in SSL - * @param sslctx: the SSL_CTX to use (from listen_sslctx_create()). - * @param fd: from accept, nonblocking. - * @return SSL or NULL on alloc failure. - */ -void* incoming_ssl_fd(void* sslctx, int fd); - -/** - * connect a new fd and wrap it in a BIO in SSL - * @param sslctx: the SSL_CTX to use (from connect_sslctx_create()) - * @param fd: from connect. - * @return SSL or NULL on alloc failure - */ -void* outgoing_ssl_fd(void* sslctx, int fd); - -/** - * check if authname SSL functionality is available, false if not - * @param auth_name: the name for the remote server, used for error print. - * @return false if SSL functionality to check the SSL name is not available. - */ -int check_auth_name_for_ssl(char* auth_name); - -/** - * set auth name on SSL for verification - * @param ssl: SSL* to set - * @param auth_name: if NULL nothing happens, otherwise the name to check. - * @param use_sni: if SNI will be used. - * @return 1 on success or NULL auth_name, 0 on failure. - */ -int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni); - -/** - * Initialize openssl locking for thread safety - * @return false on failure (alloc failure). - */ -int ub_openssl_lock_init(void); - -/** - * De-init the allocated openssl locks - */ -void ub_openssl_lock_delete(void); - -/** - * setup TLS session ticket - * @param sslctx: the SSL_CTX to use (from connect_sslctx_create()) - * @param tls_session_ticket_keys: TLS ticket secret filenames - * @return false on failure (alloc failure). - */ -int listen_sslctx_setup_ticket_keys(void* sslctx, - struct config_strlist* tls_session_ticket_keys); - -/** Free memory used for TLS session ticket keys */ -void listen_sslctx_delete_ticket_keys(void); - -/** - * RPZ format netblock to network byte order address and netblock - * example RPZ netblock format dnames: - * - 24.10.100.51.198.rpz-ip -> 198.51.100.10/24 - * - 32.10.zz.db8.2001.rpz-ip -> 2001:db8:0:0:0:0:0:10/32 - * @param dname: the dname containing RPZ format netblock - * @param dnamelen: length of dname - * @param addr: where to store sockaddr. - * @param addrlen: length of stored sockaddr is returned. - * @param net: where to store netmask - * @param af: where to store address family. - * @return 0 on error. - */ -int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, - struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af); - -/** Return strerror or wsastrerror for socket error printout */ -char* sock_strerror(int errn); -/** close the socket with close, or wsa closesocket */ -void sock_close(int socket); - -#endif /* NET_HELP_H */ diff --git a/crates/libunbound-sys/unbound/util/netevent.c b/crates/libunbound-sys/unbound/util/netevent.c deleted file mode 100644 index 204e4883..00000000 --- a/crates/libunbound-sys/unbound/util/netevent.c +++ /dev/null @@ -1,4981 +0,0 @@ -/* - * util/netevent.c - event notification - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains event notification functions. - */ -#include "config.h" -#include "util/netevent.h" -#include "util/ub_event.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/tcp_conn_limit.h" -#include "util/fptr_wlist.h" -#include "util/proxy_protocol.h" -#include "util/timeval_func.h" -#include "sldns/pkthdr.h" -#include "sldns/sbuffer.h" -#include "sldns/str2wire.h" -#include "dnstap/dnstap.h" -#include "dnscrypt/dnscrypt.h" -#include "services/listen_dnsport.h" -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_POLL_H -#include -#endif - -#ifdef HAVE_OPENSSL_SSL_H -#include -#endif -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif -#ifdef HAVE_LINUX_NET_TSTAMP_H -#include -#endif -/* -------- Start of local definitions -------- */ -/** if CMSG_ALIGN is not defined on this platform, a workaround */ -#ifndef CMSG_ALIGN -# ifdef __CMSG_ALIGN -# define CMSG_ALIGN(n) __CMSG_ALIGN(n) -# elif defined(CMSG_DATA_ALIGN) -# define CMSG_ALIGN _CMSG_DATA_ALIGN -# else -# define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) -# endif -#endif - -/** if CMSG_LEN is not defined on this platform, a workaround */ -#ifndef CMSG_LEN -# define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len)) -#endif - -/** if CMSG_SPACE is not defined on this platform, a workaround */ -#ifndef CMSG_SPACE -# ifdef _CMSG_HDR_ALIGN -# define CMSG_SPACE(l) (CMSG_ALIGN(l)+_CMSG_HDR_ALIGN(sizeof(struct cmsghdr))) -# else -# define CMSG_SPACE(l) (CMSG_ALIGN(l)+CMSG_ALIGN(sizeof(struct cmsghdr))) -# endif -#endif - -/** The TCP writing query timeout in milliseconds */ -#define TCP_QUERY_TIMEOUT 120000 -/** The minimum actual TCP timeout to use, regardless of what we advertise, - * in msec */ -#define TCP_QUERY_TIMEOUT_MINIMUM 200 - -#ifndef NONBLOCKING_IS_BROKEN -/** number of UDP reads to perform per read indication from select */ -#define NUM_UDP_PER_SELECT 100 -#else -#define NUM_UDP_PER_SELECT 1 -#endif - -/** timeout in millisec to wait for write to unblock, packets dropped after.*/ -#define SEND_BLOCKED_WAIT_TIMEOUT 200 - -/** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */ -#ifndef SO_TIMESTAMP -#define SO_TIMESTAMP 29 -#endif -#ifndef SO_TIMESTAMPNS -#define SO_TIMESTAMPNS 35 -#endif -#ifndef SO_TIMESTAMPING -#define SO_TIMESTAMPING 37 -#endif -/** - * The internal event structure for keeping ub_event info for the event. - * Possibly other structures (list, tree) this is part of. - */ -struct internal_event { - /** the comm base */ - struct comm_base* base; - /** ub_event event type */ - struct ub_event* ev; -}; - -/** - * Internal base structure, so that every thread has its own events. - */ -struct internal_base { - /** ub_event event_base type. */ - struct ub_event_base* base; - /** seconds time pointer points here */ - time_t secs; - /** timeval with current time */ - struct timeval now; - /** the event used for slow_accept timeouts */ - struct ub_event* slow_accept; - /** true if slow_accept is enabled */ - int slow_accept_enabled; - /** last log time for slow logging of file descriptor errors */ - time_t last_slow_log; - /** last log time for slow logging of write wait failures */ - time_t last_writewait_log; -}; - -/** - * Internal timer structure, to store timer event in. - */ -struct internal_timer { - /** the super struct from which derived */ - struct comm_timer super; - /** the comm base */ - struct comm_base* base; - /** ub_event event type */ - struct ub_event* ev; - /** is timer enabled */ - uint8_t enabled; -}; - -/** - * Internal signal structure, to store signal event in. - */ -struct internal_signal { - /** ub_event event type */ - struct ub_event* ev; - /** next in signal list */ - struct internal_signal* next; -}; - -/** create a tcp handler with a parent */ -static struct comm_point* comm_point_create_tcp_handler( - struct comm_base *base, struct comm_point* parent, size_t bufsize, - struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, - void* callback_arg, struct unbound_socket* socket); - -/* -------- End of local definitions -------- */ - -struct comm_base* -comm_base_create(int sigs) -{ - struct comm_base* b = (struct comm_base*)calloc(1, - sizeof(struct comm_base)); - const char *evnm="event", *evsys="", *evmethod=""; - - if(!b) - return NULL; - b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); - if(!b->eb) { - free(b); - return NULL; - } - b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now); - if(!b->eb->base) { - free(b->eb); - free(b); - return NULL; - } - ub_comm_base_now(b); - ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod); - verbose(VERB_ALGO, "%s %s uses %s method.", evnm, evsys, evmethod); - return b; -} - -struct comm_base* -comm_base_create_event(struct ub_event_base* base) -{ - struct comm_base* b = (struct comm_base*)calloc(1, - sizeof(struct comm_base)); - if(!b) - return NULL; - b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); - if(!b->eb) { - free(b); - return NULL; - } - b->eb->base = base; - ub_comm_base_now(b); - return b; -} - -void -comm_base_delete(struct comm_base* b) -{ - if(!b) - return; - if(b->eb->slow_accept_enabled) { - if(ub_event_del(b->eb->slow_accept) != 0) { - log_err("could not event_del slow_accept"); - } - ub_event_free(b->eb->slow_accept); - } - ub_event_base_free(b->eb->base); - b->eb->base = NULL; - free(b->eb); - free(b); -} - -void -comm_base_delete_no_base(struct comm_base* b) -{ - if(!b) - return; - if(b->eb->slow_accept_enabled) { - if(ub_event_del(b->eb->slow_accept) != 0) { - log_err("could not event_del slow_accept"); - } - ub_event_free(b->eb->slow_accept); - } - b->eb->base = NULL; - free(b->eb); - free(b); -} - -void -comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv) -{ - *tt = &b->eb->secs; - *tv = &b->eb->now; -} - -void -comm_base_dispatch(struct comm_base* b) -{ - int retval; - retval = ub_event_base_dispatch(b->eb->base); - if(retval < 0) { - fatal_exit("event_dispatch returned error %d, " - "errno is %s", retval, strerror(errno)); - } -} - -void comm_base_exit(struct comm_base* b) -{ - if(ub_event_base_loopexit(b->eb->base) != 0) { - log_err("Could not loopexit"); - } -} - -void comm_base_set_slow_accept_handlers(struct comm_base* b, - void (*stop_acc)(void*), void (*start_acc)(void*), void* arg) -{ - b->stop_accept = stop_acc; - b->start_accept = start_acc; - b->cb_arg = arg; -} - -struct ub_event_base* comm_base_internal(struct comm_base* b) -{ - return b->eb->base; -} - -/** see if errno for udp has to be logged or not uses globals */ -static int -udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) -{ - /* do not log transient errors (unless high verbosity) */ -#if defined(ENETUNREACH) || defined(EHOSTDOWN) || defined(EHOSTUNREACH) || defined(ENETDOWN) - switch(errno) { -# ifdef ENETUNREACH - case ENETUNREACH: -# endif -# ifdef EHOSTDOWN - case EHOSTDOWN: -# endif -# ifdef EHOSTUNREACH - case EHOSTUNREACH: -# endif -# ifdef ENETDOWN - case ENETDOWN: -# endif - case EPERM: - case EACCES: - if(verbosity < VERB_ALGO) - return 0; - default: - break; - } -#endif - /* permission denied is gotten for every send if the - * network is disconnected (on some OS), squelch it */ - if( ((errno == EPERM) -# ifdef EADDRNOTAVAIL - /* 'Cannot assign requested address' also when disconnected */ - || (errno == EADDRNOTAVAIL) -# endif - ) && verbosity < VERB_ALGO) - return 0; -# ifdef EADDRINUSE - /* If SO_REUSEADDR is set, we could try to connect to the same server - * from the same source port twice. */ - if(errno == EADDRINUSE && verbosity < VERB_DETAIL) - return 0; -# endif - /* squelch errors where people deploy AAAA ::ffff:bla for - * authority servers, which we try for intranets. */ - if(errno == EINVAL && addr_is_ip4mapped( - (struct sockaddr_storage*)addr, addrlen) && - verbosity < VERB_DETAIL) - return 0; - /* SO_BROADCAST sockopt can give access to 255.255.255.255, - * but a dns cache does not need it. */ - if(errno == EACCES && addr_is_broadcast( - (struct sockaddr_storage*)addr, addrlen) && - verbosity < VERB_DETAIL) - return 0; - return 1; -} - -int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) -{ - return udp_send_errno_needs_log(addr, addrlen); -} - -/* send a UDP reply */ -int -comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, - struct sockaddr* addr, socklen_t addrlen, int is_connected) -{ - ssize_t sent; - log_assert(c->fd != -1); -#ifdef UNBOUND_DEBUG - if(sldns_buffer_remaining(packet) == 0) - log_err("error: send empty UDP packet"); -#endif - log_assert(addr && addrlen > 0); - if(!is_connected) { - sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), - sldns_buffer_remaining(packet), 0, - addr, addrlen); - } else { - sent = send(c->fd, (void*)sldns_buffer_begin(packet), - sldns_buffer_remaining(packet), 0); - } - if(sent == -1) { - /* try again and block, waiting for IO to complete, - * we want to send the answer, and we will wait for - * the ethernet interface buffer to have space. */ -#ifndef USE_WINSOCK - if(errno == EAGAIN || errno == EINTR || -# ifdef EWOULDBLOCK - errno == EWOULDBLOCK || -# endif - errno == ENOBUFS) { -#else - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAENOBUFS || - WSAGetLastError() == WSAEWOULDBLOCK) { -#endif - /* if we set the fd blocking, other threads suddenly - * have a blocking fd that they operate on */ - while(sent == -1 && ( -#ifndef USE_WINSOCK - errno == EAGAIN || errno == EINTR || -# ifdef EWOULDBLOCK - errno == EWOULDBLOCK || -# endif - errno == ENOBUFS -#else - WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAENOBUFS || - WSAGetLastError() == WSAEWOULDBLOCK -#endif - )) { -#if defined(HAVE_POLL) || defined(USE_WINSOCK) - struct pollfd p; - int pret; - memset(&p, 0, sizeof(p)); - p.fd = c->fd; - p.events = POLLOUT | POLLERR | POLLHUP; -# ifndef USE_WINSOCK - pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); -# else - pret = WSAPoll(&p, 1, - SEND_BLOCKED_WAIT_TIMEOUT); -# endif - if(pret == 0) { - /* timer expired */ - struct comm_base* b = c->ev->base; - if(b->eb->last_writewait_log+SLOW_LOG_TIME <= - b->eb->secs) { - b->eb->last_writewait_log = b->eb->secs; - verbose(VERB_OPS, "send udp blocked " - "for long, dropping packet."); - } - return 0; - } else if(pret < 0 && -#ifndef USE_WINSOCK - errno != EAGAIN && errno != EINTR && -# ifdef EWOULDBLOCK - errno != EWOULDBLOCK && -# endif - errno != ENOBUFS -#else - WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEINTR && - WSAGetLastError() != WSAENOBUFS && - WSAGetLastError() != WSAEWOULDBLOCK -#endif - ) { - log_err("poll udp out failed: %s", - sock_strerror(errno)); - return 0; - } -#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ - if (!is_connected) { - sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), - sldns_buffer_remaining(packet), 0, - addr, addrlen); - } else { - sent = send(c->fd, (void*)sldns_buffer_begin(packet), - sldns_buffer_remaining(packet), 0); - } - } - } - } - if(sent == -1) { - if(!udp_send_errno_needs_log(addr, addrlen)) - return 0; - if (!is_connected) { - verbose(VERB_OPS, "sendto failed: %s", sock_strerror(errno)); - } else { - verbose(VERB_OPS, "send failed: %s", sock_strerror(errno)); - } - if(addr) - log_addr(VERB_OPS, "remote address is", - (struct sockaddr_storage*)addr, addrlen); - return 0; - } else if((size_t)sent != sldns_buffer_remaining(packet)) { - log_err("sent %d in place of %d bytes", - (int)sent, (int)sldns_buffer_remaining(packet)); - return 0; - } - return 1; -} - -#if defined(AF_INET6) && defined(IPV6_PKTINFO) && (defined(HAVE_RECVMSG) || defined(HAVE_SENDMSG)) -/** print debug ancillary info */ -static void p_ancil(const char* str, struct comm_reply* r) -{ - if(r->srctype != 4 && r->srctype != 6) { - log_info("%s: unknown srctype %d", str, r->srctype); - return; - } - - if(r->srctype == 6) { -#ifdef IPV6_PKTINFO - char buf[1024]; - if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, - buf, (socklen_t)sizeof(buf)) == 0) { - (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); - } - buf[sizeof(buf)-1]=0; - log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); -#endif - } else if(r->srctype == 4) { -#ifdef IP_PKTINFO - char buf1[1024], buf2[1024]; - if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, - buf1, (socklen_t)sizeof(buf1)) == 0) { - (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); - } - buf1[sizeof(buf1)-1]=0; -#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST - if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst, - buf2, (socklen_t)sizeof(buf2)) == 0) { - (void)strlcpy(buf2, "(inet_ntop error)", sizeof(buf2)); - } - buf2[sizeof(buf2)-1]=0; -#else - buf2[0]=0; -#endif - log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex, - buf1, buf2); -#elif defined(IP_RECVDSTADDR) - char buf1[1024]; - if(inet_ntop(AF_INET, &r->pktinfo.v4addr, - buf1, (socklen_t)sizeof(buf1)) == 0) { - (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); - } - buf1[sizeof(buf1)-1]=0; - log_info("%s: %s", str, buf1); -#endif /* IP_PKTINFO or PI_RECVDSTDADDR */ - } -} -#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG||HAVE_SENDMSG */ - -/** send a UDP reply over specified interface*/ -static int -comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet, - struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) -{ -#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG) - ssize_t sent; - struct msghdr msg; - struct iovec iov[1]; - union { - struct cmsghdr hdr; - char buf[256]; - } control; -#ifndef S_SPLINT_S - struct cmsghdr *cmsg; -#endif /* S_SPLINT_S */ - - log_assert(c->fd != -1); -#ifdef UNBOUND_DEBUG - if(sldns_buffer_remaining(packet) == 0) - log_err("error: send empty UDP packet"); -#endif - log_assert(addr && addrlen > 0); - - msg.msg_name = addr; - msg.msg_namelen = addrlen; - iov[0].iov_base = sldns_buffer_begin(packet); - iov[0].iov_len = sldns_buffer_remaining(packet); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control.buf; -#ifndef S_SPLINT_S - msg.msg_controllen = sizeof(control.buf); -#endif /* S_SPLINT_S */ - msg.msg_flags = 0; - -#ifndef S_SPLINT_S - cmsg = CMSG_FIRSTHDR(&msg); - if(r->srctype == 4) { -#ifdef IP_PKTINFO - void* cmsg_data; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); - log_assert(msg.msg_controllen <= sizeof(control.buf)); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_PKTINFO; - memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info, - sizeof(struct in_pktinfo)); - /* unset the ifindex to not bypass the routing tables */ - cmsg_data = CMSG_DATA(cmsg); - ((struct in_pktinfo *) cmsg_data)->ipi_ifindex = 0; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - /* zero the padding bytes inserted by the CMSG_LEN */ - if(sizeof(struct in_pktinfo) < cmsg->cmsg_len) - memset(((uint8_t*)(CMSG_DATA(cmsg))) + - sizeof(struct in_pktinfo), 0, cmsg->cmsg_len - - sizeof(struct in_pktinfo)); -#elif defined(IP_SENDSRCADDR) - msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); - log_assert(msg.msg_controllen <= sizeof(control.buf)); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_SENDSRCADDR; - memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr, - sizeof(struct in_addr)); - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); - /* zero the padding bytes inserted by the CMSG_LEN */ - if(sizeof(struct in_addr) < cmsg->cmsg_len) - memset(((uint8_t*)(CMSG_DATA(cmsg))) + - sizeof(struct in_addr), 0, cmsg->cmsg_len - - sizeof(struct in_addr)); -#else - verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR"); - msg.msg_control = NULL; -#endif /* IP_PKTINFO or IP_SENDSRCADDR */ - } else if(r->srctype == 6) { - void* cmsg_data; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - log_assert(msg.msg_controllen <= sizeof(control.buf)); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info, - sizeof(struct in6_pktinfo)); - /* unset the ifindex to not bypass the routing tables */ - cmsg_data = CMSG_DATA(cmsg); - ((struct in6_pktinfo *) cmsg_data)->ipi6_ifindex = 0; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - /* zero the padding bytes inserted by the CMSG_LEN */ - if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) - memset(((uint8_t*)(CMSG_DATA(cmsg))) + - sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len - - sizeof(struct in6_pktinfo)); - } else { - /* try to pass all 0 to use default route */ - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - log_assert(msg.msg_controllen <= sizeof(control.buf)); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo)); - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - /* zero the padding bytes inserted by the CMSG_LEN */ - if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) - memset(((uint8_t*)(CMSG_DATA(cmsg))) + - sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len - - sizeof(struct in6_pktinfo)); - } -#endif /* S_SPLINT_S */ - if(verbosity >= VERB_ALGO && r->srctype != 0) - p_ancil("send_udp over interface", r); - sent = sendmsg(c->fd, &msg, 0); - if(sent == -1) { - /* try again and block, waiting for IO to complete, - * we want to send the answer, and we will wait for - * the ethernet interface buffer to have space. */ -#ifndef USE_WINSOCK - if(errno == EAGAIN || errno == EINTR || -# ifdef EWOULDBLOCK - errno == EWOULDBLOCK || -# endif - errno == ENOBUFS) { -#else - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAENOBUFS || - WSAGetLastError() == WSAEWOULDBLOCK) { -#endif - while(sent == -1 && ( -#ifndef USE_WINSOCK - errno == EAGAIN || errno == EINTR || -# ifdef EWOULDBLOCK - errno == EWOULDBLOCK || -# endif - errno == ENOBUFS -#else - WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEINTR || - WSAGetLastError() == WSAENOBUFS || - WSAGetLastError() == WSAEWOULDBLOCK -#endif - )) { -#if defined(HAVE_POLL) || defined(USE_WINSOCK) - struct pollfd p; - int pret; - memset(&p, 0, sizeof(p)); - p.fd = c->fd; - p.events = POLLOUT | POLLERR | POLLHUP; -# ifndef USE_WINSOCK - pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); -# else - pret = WSAPoll(&p, 1, - SEND_BLOCKED_WAIT_TIMEOUT); -# endif - if(pret == 0) { - /* timer expired */ - struct comm_base* b = c->ev->base; - if(b->eb->last_writewait_log+SLOW_LOG_TIME <= - b->eb->secs) { - b->eb->last_writewait_log = b->eb->secs; - verbose(VERB_OPS, "send udp blocked " - "for long, dropping packet."); - } - return 0; - } else if(pret < 0 && -#ifndef USE_WINSOCK - errno != EAGAIN && errno != EINTR && -# ifdef EWOULDBLOCK - errno != EWOULDBLOCK && -# endif - errno != ENOBUFS -#else - WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAEINTR && - WSAGetLastError() != WSAENOBUFS && - WSAGetLastError() != WSAEWOULDBLOCK -#endif - ) { - log_err("poll udp out failed: %s", - sock_strerror(errno)); - return 0; - } -#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ - sent = sendmsg(c->fd, &msg, 0); - } - } - } - if(sent == -1) { - if(!udp_send_errno_needs_log(addr, addrlen)) - return 0; - verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno)); - log_addr(VERB_OPS, "remote address is", - (struct sockaddr_storage*)addr, addrlen); -#ifdef __NetBSD__ - /* netbsd 7 has IP_PKTINFO for recv but not send */ - if(errno == EINVAL && r->srctype == 4) - log_err("sendmsg: No support for sendmsg(IP_PKTINFO). " - "Please disable interface-automatic"); -#endif - return 0; - } else if((size_t)sent != sldns_buffer_remaining(packet)) { - log_err("sent %d in place of %d bytes", - (int)sent, (int)sldns_buffer_remaining(packet)); - return 0; - } - return 1; -#else - (void)c; - (void)packet; - (void)addr; - (void)addrlen; - (void)r; - log_err("sendmsg: IPV6_PKTINFO not supported"); - return 0; -#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_SENDMSG */ -} - -/** return true is UDP receive error needs to be logged */ -static int udp_recv_needs_log(int err) -{ - switch(err) { - case EACCES: /* some hosts send ICMP 'Permission Denied' */ -#ifndef USE_WINSOCK - case ECONNREFUSED: -# ifdef ENETUNREACH - case ENETUNREACH: -# endif -# ifdef EHOSTDOWN - case EHOSTDOWN: -# endif -# ifdef EHOSTUNREACH - case EHOSTUNREACH: -# endif -# ifdef ENETDOWN - case ENETDOWN: -# endif -#else /* USE_WINSOCK */ - case WSAECONNREFUSED: - case WSAENETUNREACH: - case WSAEHOSTDOWN: - case WSAEHOSTUNREACH: - case WSAENETDOWN: -#endif - if(verbosity >= VERB_ALGO) - return 1; - return 0; - default: - break; - } - return 1; -} - -/** Parses the PROXYv2 header from buf and updates the comm_reply struct. - * Returns 1 on success, 0 on failure. */ -static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, - int stream) { - size_t size; - struct pp2_header *header = pp2_read_header(buf); - if(header == NULL) return 0; - size = PP2_HEADER_SIZE + ntohs(header->len); - if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) { - /* A connection from the proxy itself. - * No need to do anything with addresses. */ - goto done; - } - if(header->fam_prot == 0x00) { - /* Unspecified family and protocol. This could be used for - * health checks by proxies. - * No need to do anything with addresses. */ - goto done; - } - /* Read the proxied address */ - switch(header->fam_prot) { - case 0x11: /* AF_INET|STREAM */ - case 0x12: /* AF_INET|DGRAM */ - { - struct sockaddr_in* addr = - (struct sockaddr_in*)&rep->client_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = header->addr.addr4.src_addr; - addr->sin_port = header->addr.addr4.src_port; - rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in); - } - /* Ignore the destination address; it should be us. */ - break; - case 0x21: /* AF_INET6|STREAM */ - case 0x22: /* AF_INET6|DGRAM */ - { - struct sockaddr_in6* addr = - (struct sockaddr_in6*)&rep->client_addr; - memset(addr, 0, sizeof(*addr)); - addr->sin6_family = AF_INET6; - memcpy(&addr->sin6_addr, - header->addr.addr6.src_addr, 16); - addr->sin6_port = header->addr.addr6.src_port; - rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in6); - } - /* Ignore the destination address; it should be us. */ - break; - } - rep->is_proxied = 1; -done: - if(!stream) { - /* We are reading a whole packet; - * Move the rest of the data to overwrite the PROXYv2 header */ - /* XXX can we do better to avoid memmove? */ - memmove(header, ((char*)header)+size, - sldns_buffer_limit(buf)-size); - sldns_buffer_set_limit(buf, sldns_buffer_limit(buf)-size); - } - return 1; -} - -void -comm_point_udp_ancil_callback(int fd, short event, void* arg) -{ -#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) - struct comm_reply rep; - struct msghdr msg; - struct iovec iov[1]; - ssize_t rcv; - union { - struct cmsghdr hdr; - char buf[256]; - } ancil; - int i; -#ifndef S_SPLINT_S - struct cmsghdr* cmsg; -#endif /* S_SPLINT_S */ -#ifdef HAVE_LINUX_NET_TSTAMP_H - struct timespec *ts; -#endif /* HAVE_LINUX_NET_TSTAMP_H */ - - rep.c = (struct comm_point*)arg; - log_assert(rep.c->type == comm_udp); - - if(!(event&UB_EV_READ)) - return; - log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); - ub_comm_base_now(rep.c->ev->base); - for(i=0; ibuffer); - timeval_clear(&rep.c->recv_tv); - rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); - log_assert(fd != -1); - log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); - msg.msg_name = &rep.remote_addr; - msg.msg_namelen = (socklen_t)sizeof(rep.remote_addr); - iov[0].iov_base = sldns_buffer_begin(rep.c->buffer); - iov[0].iov_len = sldns_buffer_remaining(rep.c->buffer); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = ancil.buf; -#ifndef S_SPLINT_S - msg.msg_controllen = sizeof(ancil.buf); -#endif /* S_SPLINT_S */ - msg.msg_flags = 0; - rcv = recvmsg(fd, &msg, MSG_DONTWAIT); - if(rcv == -1) { - if(errno != EAGAIN && errno != EINTR - && udp_recv_needs_log(errno)) { - log_err("recvmsg failed: %s", strerror(errno)); - } - return; - } - rep.remote_addrlen = msg.msg_namelen; - sldns_buffer_skip(rep.c->buffer, rcv); - sldns_buffer_flip(rep.c->buffer); - rep.srctype = 0; - rep.is_proxied = 0; -#ifndef S_SPLINT_S - for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if( cmsg->cmsg_level == IPPROTO_IPV6 && - cmsg->cmsg_type == IPV6_PKTINFO) { - rep.srctype = 6; - memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), - sizeof(struct in6_pktinfo)); - break; -#ifdef IP_PKTINFO - } else if( cmsg->cmsg_level == IPPROTO_IP && - cmsg->cmsg_type == IP_PKTINFO) { - rep.srctype = 4; - memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), - sizeof(struct in_pktinfo)); - break; -#elif defined(IP_RECVDSTADDR) - } else if( cmsg->cmsg_level == IPPROTO_IP && - cmsg->cmsg_type == IP_RECVDSTADDR) { - rep.srctype = 4; - memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg), - sizeof(struct in_addr)); - break; -#endif /* IP_PKTINFO or IP_RECVDSTADDR */ -#ifdef HAVE_LINUX_NET_TSTAMP_H - } else if( cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SO_TIMESTAMPNS) { - ts = (struct timespec *)CMSG_DATA(cmsg); - TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); - } else if( cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SO_TIMESTAMPING) { - ts = (struct timespec *)CMSG_DATA(cmsg); - TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); - } else if( cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SO_TIMESTAMP) { - memmove(&rep.c->recv_tv, CMSG_DATA(cmsg), sizeof(struct timeval)); -#endif /* HAVE_LINUX_NET_TSTAMP_H */ - } - } - - if(verbosity >= VERB_ALGO && rep.srctype != 0) - p_ancil("receive_udp on interface", &rep); -#endif /* S_SPLINT_S */ - - if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, - &rep, 0)) { - log_err("proxy_protocol: could not consume PROXYv2 header"); - return; - } - if(!rep.is_proxied) { - rep.client_addrlen = rep.remote_addrlen; - memmove(&rep.client_addr, &rep.remote_addr, - rep.remote_addrlen); - } - - fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); - if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { - /* send back immediate reply */ - (void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer, - (struct sockaddr*)&rep.remote_addr, - rep.remote_addrlen, &rep); - } - if(!rep.c || rep.c->fd == -1) /* commpoint closed */ - break; - } -#else - (void)fd; - (void)event; - (void)arg; - fatal_exit("recvmsg: No support for IPV6_PKTINFO; IP_PKTINFO or IP_RECVDSTADDR. " - "Please disable interface-automatic"); -#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ -} - -void -comm_point_udp_callback(int fd, short event, void* arg) -{ - struct comm_reply rep; - ssize_t rcv; - int i; - struct sldns_buffer *buffer; - - rep.c = (struct comm_point*)arg; - log_assert(rep.c->type == comm_udp); - - if(!(event&UB_EV_READ)) - return; - log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); - ub_comm_base_now(rep.c->ev->base); - for(i=0; ibuffer); - rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); - log_assert(fd != -1); - log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); - rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer), - sldns_buffer_remaining(rep.c->buffer), MSG_DONTWAIT, - (struct sockaddr*)&rep.remote_addr, &rep.remote_addrlen); - if(rcv == -1) { -#ifndef USE_WINSOCK - if(errno != EAGAIN && errno != EINTR - && udp_recv_needs_log(errno)) - log_err("recvfrom %d failed: %s", - fd, strerror(errno)); -#else - if(WSAGetLastError() != WSAEINPROGRESS && - WSAGetLastError() != WSAECONNRESET && - WSAGetLastError()!= WSAEWOULDBLOCK && - udp_recv_needs_log(WSAGetLastError())) - log_err("recvfrom failed: %s", - wsa_strerror(WSAGetLastError())); -#endif - return; - } - sldns_buffer_skip(rep.c->buffer, rcv); - sldns_buffer_flip(rep.c->buffer); - rep.srctype = 0; - rep.is_proxied = 0; - - if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, - &rep, 0)) { - log_err("proxy_protocol: could not consume PROXYv2 header"); - return; - } - if(!rep.is_proxied) { - rep.client_addrlen = rep.remote_addrlen; - memmove(&rep.client_addr, &rep.remote_addr, - rep.remote_addrlen); - } - - fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); - if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { - /* send back immediate reply */ -#ifdef USE_DNSCRYPT - buffer = rep.c->dnscrypt_buffer; -#else - buffer = rep.c->buffer; -#endif - (void)comm_point_send_udp_msg(rep.c, buffer, - (struct sockaddr*)&rep.remote_addr, - rep.remote_addrlen, 0); - } - if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for - another UDP port. Note rep.c cannot be reused with TCP fd. */ - break; - } -} - -int adjusted_tcp_timeout(struct comm_point* c) -{ - if(c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM) - return TCP_QUERY_TIMEOUT_MINIMUM; - return c->tcp_timeout_msec; -} - -/** Use a new tcp handler for new query fd, set to read query */ -static void -setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) -{ - int handler_usage; - log_assert(c->type == comm_tcp || c->type == comm_http); - log_assert(c->fd == -1); - sldns_buffer_clear(c->buffer); -#ifdef USE_DNSCRYPT - if (c->dnscrypt) - sldns_buffer_clear(c->dnscrypt_buffer); -#endif - c->tcp_is_reading = 1; - c->tcp_byte_count = 0; - c->tcp_keepalive = 0; - /* if more than half the tcp handlers are in use, use a shorter - * timeout for this TCP connection, we need to make space for - * other connections to be able to get attention */ - /* If > 50% TCP handler structures in use, set timeout to 1/100th - * configured value. - * If > 65%TCP handler structures in use, set to 1/500th configured - * value. - * If > 80% TCP handler structures in use, set to 0. - * - * If the timeout to use falls below 200 milliseconds, an actual - * timeout of 200ms is used. - */ - handler_usage = (cur * 100) / max; - if(handler_usage > 50 && handler_usage <= 65) - c->tcp_timeout_msec /= 100; - else if (handler_usage > 65 && handler_usage <= 80) - c->tcp_timeout_msec /= 500; - else if (handler_usage > 80) - c->tcp_timeout_msec = 0; - comm_point_start_listening(c, fd, adjusted_tcp_timeout(c)); -} - -void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), - short ATTR_UNUSED(event), void* arg) -{ - struct comm_base* b = (struct comm_base*)arg; - /* timeout for the slow accept, re-enable accepts again */ - if(b->start_accept) { - verbose(VERB_ALGO, "wait is over, slow accept disabled"); - fptr_ok(fptr_whitelist_start_accept(b->start_accept)); - (*b->start_accept)(b->cb_arg); - b->eb->slow_accept_enabled = 0; - } -} - -int comm_point_perform_accept(struct comm_point* c, - struct sockaddr_storage* addr, socklen_t* addrlen) -{ - int new_fd; - *addrlen = (socklen_t)sizeof(*addr); -#ifndef HAVE_ACCEPT4 - new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen); -#else - /* SOCK_NONBLOCK saves extra calls to fcntl for the same result */ - new_fd = accept4(c->fd, (struct sockaddr*)addr, addrlen, SOCK_NONBLOCK); -#endif - if(new_fd == -1) { -#ifndef USE_WINSOCK - /* EINTR is signal interrupt. others are closed connection. */ - if( errno == EINTR || errno == EAGAIN -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif -#ifdef ECONNABORTED - || errno == ECONNABORTED -#endif -#ifdef EPROTO - || errno == EPROTO -#endif /* EPROTO */ - ) - return -1; -#if defined(ENFILE) && defined(EMFILE) - if(errno == ENFILE || errno == EMFILE) { - /* out of file descriptors, likely outside of our - * control. stop accept() calls for some time */ - if(c->ev->base->stop_accept) { - struct comm_base* b = c->ev->base; - struct timeval tv; - verbose(VERB_ALGO, "out of file descriptors: " - "slow accept"); - ub_comm_base_now(b); - if(b->eb->last_slow_log+SLOW_LOG_TIME <= - b->eb->secs) { - b->eb->last_slow_log = b->eb->secs; - verbose(VERB_OPS, "accept failed, " - "slow down accept for %d " - "msec: %s", - NETEVENT_SLOW_ACCEPT_TIME, - sock_strerror(errno)); - } - b->eb->slow_accept_enabled = 1; - fptr_ok(fptr_whitelist_stop_accept( - b->stop_accept)); - (*b->stop_accept)(b->cb_arg); - /* set timeout, no mallocs */ - tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000; - tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000; - b->eb->slow_accept = ub_event_new(b->eb->base, - -1, UB_EV_TIMEOUT, - comm_base_handle_slow_accept, b); - if(b->eb->slow_accept == NULL) { - /* we do not want to log here, because - * that would spam the logfiles. - * error: "event_base_set failed." */ - } - else if(ub_event_add(b->eb->slow_accept, &tv) - != 0) { - /* we do not want to log here, - * error: "event_add failed." */ - } - } else { - log_err("accept, with no slow down, " - "failed: %s", sock_strerror(errno)); - } - return -1; - } -#endif -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAECONNRESET) - return -1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); - return -1; - } -#endif - log_err_addr("accept failed", sock_strerror(errno), addr, - *addrlen); - return -1; - } - if(c->tcp_conn_limit && c->type == comm_tcp_accept) { - c->tcl_addr = tcl_addr_lookup(c->tcp_conn_limit, addr, *addrlen); - if(!tcl_new_connection(c->tcl_addr)) { - if(verbosity >= 3) - log_err_addr("accept rejected", - "connection limit exceeded", addr, *addrlen); - close(new_fd); - return -1; - } - } -#ifndef HAVE_ACCEPT4 - fd_set_nonblock(new_fd); -#endif - return new_fd; -} - -#ifdef USE_WINSOCK -static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), -#ifdef HAVE_BIO_SET_CALLBACK_EX - size_t ATTR_UNUSED(len), -#endif - int ATTR_UNUSED(argi), long argl, -#ifndef HAVE_BIO_SET_CALLBACK_EX - long retvalue -#else - int retvalue, size_t* ATTR_UNUSED(processed) -#endif - ) -{ - int wsa_err = WSAGetLastError(); /* store errcode before it is gone */ - verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper, - (oper&BIO_CB_RETURN)?"return":"before", - (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"), - wsa_err==WSAEWOULDBLOCK?"wsawb":""); - /* on windows, check if previous operation caused EWOULDBLOCK */ - if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) || - (oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) { - if(wsa_err == WSAEWOULDBLOCK) - ub_winsock_tcp_wouldblock((struct ub_event*) - BIO_get_callback_arg(b), UB_EV_READ); - } - if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) || - (oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) { - if(wsa_err == WSAEWOULDBLOCK) - ub_winsock_tcp_wouldblock((struct ub_event*) - BIO_get_callback_arg(b), UB_EV_WRITE); - } - /* return original return value */ - return retvalue; -} - -/** set win bio callbacks for nonblocking operations */ -void -comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl) -{ - SSL* ssl = (SSL*)thessl; - /* set them both just in case, but usually they are the same BIO */ -#ifdef HAVE_BIO_SET_CALLBACK_EX - BIO_set_callback_ex(SSL_get_rbio(ssl), &win_bio_cb); -#else - BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb); -#endif - BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev); -#ifdef HAVE_BIO_SET_CALLBACK_EX - BIO_set_callback_ex(SSL_get_wbio(ssl), &win_bio_cb); -#else - BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb); -#endif - BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev); -} -#endif - -#ifdef HAVE_NGHTTP2 -/** Create http2 session server. Per connection, after TCP accepted.*/ -static int http2_session_server_create(struct http2_session* h2_session) -{ - log_assert(h2_session->callbacks); - h2_session->is_drop = 0; - if(nghttp2_session_server_new(&h2_session->session, - h2_session->callbacks, - h2_session) == NGHTTP2_ERR_NOMEM) { - log_err("failed to create nghttp2 session server"); - return 0; - } - - return 1; -} - -/** Submit http2 setting to session. Once per session. */ -static int http2_submit_settings(struct http2_session* h2_session) -{ - int ret; - nghttp2_settings_entry settings[1] = { - {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - h2_session->c->http2_max_streams}}; - - ret = nghttp2_submit_settings(h2_session->session, NGHTTP2_FLAG_NONE, - settings, 1); - if(ret) { - verbose(VERB_QUERY, "http2: submit_settings failed, " - "error: %s", nghttp2_strerror(ret)); - return 0; - } - return 1; -} -#endif /* HAVE_NGHTTP2 */ - - -void -comm_point_tcp_accept_callback(int fd, short event, void* arg) -{ - struct comm_point* c = (struct comm_point*)arg, *c_hdl; - int new_fd; - log_assert(c->type == comm_tcp_accept); - if(!(event & UB_EV_READ)) { - log_info("ignoring tcp accept event %d", (int)event); - return; - } - ub_comm_base_now(c->ev->base); - /* find free tcp handler. */ - if(!c->tcp_free) { - log_warn("accepted too many tcp, connections full"); - return; - } - /* accept incoming connection. */ - c_hdl = c->tcp_free; - /* clear leftover flags from previous use, and then set the - * correct event base for the event structure for libevent */ - ub_event_free(c_hdl->ev->ev); - c_hdl->ev->ev = NULL; - if((c_hdl->type == comm_tcp && c_hdl->tcp_req_info) || - c_hdl->type == comm_local || c_hdl->type == comm_raw) - c_hdl->tcp_do_toggle_rw = 0; - else c_hdl->tcp_do_toggle_rw = 1; - - if(c_hdl->type == comm_http) { -#ifdef HAVE_NGHTTP2 - if(!c_hdl->h2_session || - !http2_session_server_create(c_hdl->h2_session)) { - log_warn("failed to create nghttp2"); - return; - } - if(!c_hdl->h2_session || - !http2_submit_settings(c_hdl->h2_session)) { - log_warn("failed to submit http2 settings"); - return; - } - if(!c->ssl) { - c_hdl->tcp_do_toggle_rw = 0; - c_hdl->use_h2 = 1; - } -#endif - c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, - UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, - comm_point_http_handle_callback, c_hdl); - } else { - c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, - UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, - comm_point_tcp_handle_callback, c_hdl); - } - if(!c_hdl->ev->ev) { - log_warn("could not ub_event_new, dropped tcp"); - return; - } - log_assert(fd != -1); - (void)fd; - new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.remote_addr, - &c_hdl->repinfo.remote_addrlen); - if(new_fd == -1) - return; - /* Copy remote_address to client_address. - * Simplest way/time for streams to do that. */ - c_hdl->repinfo.client_addrlen = c_hdl->repinfo.remote_addrlen; - memmove(&c_hdl->repinfo.client_addr, - &c_hdl->repinfo.remote_addr, - c_hdl->repinfo.remote_addrlen); - if(c->ssl) { - c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); - if(!c_hdl->ssl) { - c_hdl->fd = new_fd; - comm_point_close(c_hdl); - return; - } - c_hdl->ssl_shake_state = comm_ssl_shake_read; -#ifdef USE_WINSOCK - comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl); -#endif - } - - /* grab the tcp handler buffers */ - c->cur_tcp_count++; - c->tcp_free = c_hdl->tcp_free; - c_hdl->tcp_free = NULL; - if(!c->tcp_free) { - /* stop accepting incoming queries for now. */ - comm_point_stop_listening(c); - } - setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count); -} - -/** Make tcp handler free for next assignment */ -static void -reclaim_tcp_handler(struct comm_point* c) -{ - log_assert(c->type == comm_tcp); - if(c->ssl) { -#ifdef HAVE_SSL - SSL_shutdown(c->ssl); - SSL_free(c->ssl); - c->ssl = NULL; -#endif - } - comm_point_close(c); - if(c->tcp_parent) { - if(c != c->tcp_parent->tcp_free) { - c->tcp_parent->cur_tcp_count--; - c->tcp_free = c->tcp_parent->tcp_free; - c->tcp_parent->tcp_free = c; - } - if(!c->tcp_free) { - /* re-enable listening on accept socket */ - comm_point_start_listening(c->tcp_parent, -1, -1); - } - } - c->tcp_more_read_again = NULL; - c->tcp_more_write_again = NULL; - c->tcp_byte_count = 0; - c->pp2_header_state = pp2_header_none; - sldns_buffer_clear(c->buffer); -} - -/** do the callback when writing is done */ -static void -tcp_callback_writer(struct comm_point* c) -{ - log_assert(c->type == comm_tcp); - if(!c->tcp_write_and_read) { - sldns_buffer_clear(c->buffer); - c->tcp_byte_count = 0; - } - if(c->tcp_do_toggle_rw) - c->tcp_is_reading = 1; - /* switch from listening(write) to listening(read) */ - if(c->tcp_req_info) { - tcp_req_info_handle_writedone(c->tcp_req_info); - } else { - comm_point_stop_listening(c); - if(c->tcp_write_and_read) { - fptr_ok(fptr_whitelist_comm_point(c->callback)); - if( (*c->callback)(c, c->cb_arg, NETEVENT_PKT_WRITTEN, - &c->repinfo) ) { - comm_point_start_listening(c, -1, - adjusted_tcp_timeout(c)); - } - } else { - comm_point_start_listening(c, -1, - adjusted_tcp_timeout(c)); - } - } -} - -/** do the callback when reading is done */ -static void -tcp_callback_reader(struct comm_point* c) -{ - log_assert(c->type == comm_tcp || c->type == comm_local); - sldns_buffer_flip(c->buffer); - if(c->tcp_do_toggle_rw) - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - if(c->tcp_req_info) { - tcp_req_info_handle_readdone(c->tcp_req_info); - } else { - if(c->type == comm_tcp) - comm_point_stop_listening(c); - fptr_ok(fptr_whitelist_comm_point(c->callback)); - if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) { - comm_point_start_listening(c, -1, - adjusted_tcp_timeout(c)); - } - } -} - -#ifdef HAVE_SSL -/** true if the ssl handshake error has to be squelched from the logs */ -int -squelch_err_ssl_handshake(unsigned long err) -{ - if(verbosity >= VERB_QUERY) - return 0; /* only squelch on low verbosity */ - if(ERR_GET_LIB(err) == ERR_LIB_SSL && - (ERR_GET_REASON(err) == SSL_R_HTTPS_PROXY_REQUEST || - ERR_GET_REASON(err) == SSL_R_HTTP_REQUEST || - ERR_GET_REASON(err) == SSL_R_WRONG_VERSION_NUMBER || - ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE -#ifdef SSL_F_TLS_POST_PROCESS_CLIENT_HELLO - || ERR_GET_REASON(err) == SSL_R_NO_SHARED_CIPHER -#endif -#ifdef SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO - || ERR_GET_REASON(err) == SSL_R_UNKNOWN_PROTOCOL - || ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL -# ifdef SSL_R_VERSION_TOO_LOW - || ERR_GET_REASON(err) == SSL_R_VERSION_TOO_LOW -# endif -#endif - )) - return 1; - return 0; -} -#endif /* HAVE_SSL */ - -/** continue ssl handshake */ -#ifdef HAVE_SSL -static int -ssl_handshake(struct comm_point* c) -{ - int r; - if(c->ssl_shake_state == comm_ssl_shake_hs_read) { - /* read condition satisfied back to writing */ - comm_point_listen_for_rw(c, 0, 1); - c->ssl_shake_state = comm_ssl_shake_none; - return 1; - } - if(c->ssl_shake_state == comm_ssl_shake_hs_write) { - /* write condition satisfied, back to reading */ - comm_point_listen_for_rw(c, 1, 0); - c->ssl_shake_state = comm_ssl_shake_none; - return 1; - } - - ERR_clear_error(); - r = SSL_do_handshake(c->ssl); - if(r != 1) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_WANT_READ) { - if(c->ssl_shake_state == comm_ssl_shake_read) - return 1; - c->ssl_shake_state = comm_ssl_shake_read; - comm_point_listen_for_rw(c, 1, 0); - return 1; - } else if(want == SSL_ERROR_WANT_WRITE) { - if(c->ssl_shake_state == comm_ssl_shake_write) - return 1; - c->ssl_shake_state = comm_ssl_shake_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(r == 0) { - return 0; /* closed */ - } else if(want == SSL_ERROR_SYSCALL) { - /* SYSCALL and errno==0 means closed uncleanly */ -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return 0; /* silence 'broken pipe' */ -#endif -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(!tcp_connect_errno_needs_log( - (struct sockaddr*)&c->repinfo.remote_addr, - c->repinfo.remote_addrlen)) - return 0; /* silence connect failures that - show up because after connect this is the - first system call that accesses the socket */ - if(errno != 0) - log_err("SSL_handshake syscall: %s", - strerror(errno)); - return 0; - } else { - unsigned long err = ERR_get_error(); - if(!squelch_err_ssl_handshake(err)) { - log_crypto_err_code("ssl handshake failed", err); - log_addr(VERB_OPS, "ssl handshake failed", - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - } - return 0; - } - } - /* this is where peer verification could take place */ - if((SSL_get_verify_mode(c->ssl)&SSL_VERIFY_PEER)) { - /* verification */ - if(SSL_get_verify_result(c->ssl) == X509_V_OK) { -#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE - X509* x = SSL_get1_peer_certificate(c->ssl); -#else - X509* x = SSL_get_peer_certificate(c->ssl); -#endif - if(!x) { - log_addr(VERB_ALGO, "SSL connection failed: " - "no certificate", - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - log_cert(VERB_ALGO, "peer certificate", x); -#ifdef HAVE_SSL_GET0_PEERNAME - if(SSL_get0_peername(c->ssl)) { - char buf[255]; - snprintf(buf, sizeof(buf), "SSL connection " - "to %s authenticated", - SSL_get0_peername(c->ssl)); - log_addr(VERB_ALGO, buf, &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - } else { -#endif - log_addr(VERB_ALGO, "SSL connection " - "authenticated", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -#ifdef HAVE_SSL_GET0_PEERNAME - } -#endif - X509_free(x); - } else { -#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE - X509* x = SSL_get1_peer_certificate(c->ssl); -#else - X509* x = SSL_get_peer_certificate(c->ssl); -#endif - if(x) { - log_cert(VERB_ALGO, "peer certificate", x); - X509_free(x); - } - log_addr(VERB_ALGO, "SSL connection failed: " - "failed to authenticate", - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - } else { - /* unauthenticated, the verify peer flag was not set - * in c->ssl when the ssl object was created from ssl_ctx */ - log_addr(VERB_ALGO, "SSL connection", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - } - -#ifdef HAVE_SSL_GET0_ALPN_SELECTED - /* check if http2 use is negotiated */ - if(c->type == comm_http && c->h2_session) { - const unsigned char *alpn; - unsigned int alpnlen = 0; - SSL_get0_alpn_selected(c->ssl, &alpn, &alpnlen); - if(alpnlen == 2 && memcmp("h2", alpn, 2) == 0) { - /* connection upgraded to HTTP2 */ - c->tcp_do_toggle_rw = 0; - c->use_h2 = 1; - } - } -#endif - - /* setup listen rw correctly */ - if(c->tcp_is_reading) { - if(c->ssl_shake_state != comm_ssl_shake_read) - comm_point_listen_for_rw(c, 1, 0); - } else { - comm_point_listen_for_rw(c, 0, 1); - } - c->ssl_shake_state = comm_ssl_shake_none; - return 1; -} -#endif /* HAVE_SSL */ - -/** ssl read callback on TCP */ -static int -ssl_handle_read(struct comm_point* c) -{ -#ifdef HAVE_SSL - int r; - if(c->ssl_shake_state != comm_ssl_shake_none) { - if(!ssl_handshake(c)) - return 0; - if(c->ssl_shake_state != comm_ssl_shake_none) - return 1; - } - if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { - struct pp2_header* header = NULL; - size_t want_read_size = 0; - size_t current_read_size = 0; - if(c->pp2_header_state == pp2_header_none) { - want_read_size = PP2_HEADER_SIZE; - if(sldns_buffer_remaining(c->buffer)repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: reading fixed " - "part of PROXYv2 header (len %lu)", - (unsigned long)want_read_size); - current_read_size = want_read_size; - if(c->tcp_byte_count < current_read_size) { - ERR_clear_error(); - if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( - c->buffer, c->tcp_byte_count), - current_read_size - - c->tcp_byte_count)) <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; /* shutdown, closed */ - } else if(want == SSL_ERROR_WANT_READ) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); -#endif - return 1; /* read more later */ - } else if(want == SSL_ERROR_WANT_WRITE) { - c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_read"); - return 0; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count != current_read_size) return 1; - c->pp2_header_state = pp2_header_init; - } - } - if(c->pp2_header_state == pp2_header_init) { - header = pp2_read_header(c->buffer); - if(!header) { - log_err("proxy_protocol: could not parse " - "PROXYv2 header"); - return 0; - } - want_read_size = ntohs(header->len); - if(sldns_buffer_remaining(c->buffer) < - PP2_HEADER_SIZE + want_read_size) { - log_err_addr("proxy_protocol: not enough " - "buffer size to read PROXYv2 header", "", - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: reading variable " - "part of PROXYv2 header (len %lu)", - (unsigned long)want_read_size); - current_read_size = PP2_HEADER_SIZE + want_read_size; - if(want_read_size == 0) { - /* nothing more to read; header is complete */ - c->pp2_header_state = pp2_header_done; - } else if(c->tcp_byte_count < current_read_size) { - ERR_clear_error(); - if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( - c->buffer, c->tcp_byte_count), - current_read_size - - c->tcp_byte_count)) <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; /* shutdown, closed */ - } else if(want == SSL_ERROR_WANT_READ) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); -#endif - return 1; /* read more later */ - } else if(want == SSL_ERROR_WANT_WRITE) { - c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_read"); - return 0; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count != current_read_size) return 1; - c->pp2_header_state = pp2_header_done; - } - } - if(c->pp2_header_state != pp2_header_done || !header) { - log_err_addr("proxy_protocol: wrong state for the " - "PROXYv2 header", "", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { - log_err_addr("proxy_protocol: could not consume " - "PROXYv2 header", "", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: successful read of " - "PROXYv2 header"); - /* Clear and reset the buffer to read the following - * DNS packet(s). */ - sldns_buffer_clear(c->buffer); - c->tcp_byte_count = 0; - return 1; - } - if(c->tcp_byte_count < sizeof(uint16_t)) { - /* read length bytes */ - ERR_clear_error(); - if((r=SSL_read(c->ssl, (void*)sldns_buffer_at(c->buffer, - c->tcp_byte_count), (int)(sizeof(uint16_t) - - c->tcp_byte_count))) <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; /* shutdown, closed */ - } else if(want == SSL_ERROR_WANT_READ) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); -#endif - return 1; /* read more later */ - } else if(want == SSL_ERROR_WANT_WRITE) { - c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_read"); - return 0; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count < sizeof(uint16_t)) - return 1; - if(sldns_buffer_read_u16_at(c->buffer, 0) > - sldns_buffer_capacity(c->buffer)) { - verbose(VERB_QUERY, "ssl: dropped larger than buffer"); - return 0; - } - sldns_buffer_set_limit(c->buffer, - sldns_buffer_read_u16_at(c->buffer, 0)); - if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { - verbose(VERB_QUERY, "ssl: dropped bogus too short."); - return 0; - } - sldns_buffer_skip(c->buffer, (ssize_t)(c->tcp_byte_count-sizeof(uint16_t))); - verbose(VERB_ALGO, "Reading ssl tcp query of length %d", - (int)sldns_buffer_limit(c->buffer)); - } - if(sldns_buffer_remaining(c->buffer) > 0) { - ERR_clear_error(); - r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), - (int)sldns_buffer_remaining(c->buffer)); - if(r <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; /* shutdown, closed */ - } else if(want == SSL_ERROR_WANT_READ) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); -#endif - return 1; /* read more later */ - } else if(want == SSL_ERROR_WANT_WRITE) { - c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_read"); - return 0; - } - sldns_buffer_skip(c->buffer, (ssize_t)r); - } - if(sldns_buffer_remaining(c->buffer) <= 0) { - tcp_callback_reader(c); - } - return 1; -#else - (void)c; - return 0; -#endif /* HAVE_SSL */ -} - -/** ssl write callback on TCP */ -static int -ssl_handle_write(struct comm_point* c) -{ -#ifdef HAVE_SSL - int r; - if(c->ssl_shake_state != comm_ssl_shake_none) { - if(!ssl_handshake(c)) - return 0; - if(c->ssl_shake_state != comm_ssl_shake_none) - return 1; - } - /* ignore return, if fails we may simply block */ - (void)SSL_set_mode(c->ssl, (long)SSL_MODE_ENABLE_PARTIAL_WRITE); - if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { - uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(c->buffer)); - ERR_clear_error(); - if(c->tcp_write_and_read) { - if(c->tcp_write_pkt_len + 2 < LDNS_RR_BUF_SIZE) { - /* combine the tcp length and the query for - * write, this emulates writev */ - uint8_t buf[LDNS_RR_BUF_SIZE]; - memmove(buf, &len, sizeof(uint16_t)); - memmove(buf+sizeof(uint16_t), - c->tcp_write_pkt, - c->tcp_write_pkt_len); - r = SSL_write(c->ssl, - (void*)(buf+c->tcp_write_byte_count), - c->tcp_write_pkt_len + 2 - - c->tcp_write_byte_count); - } else { - r = SSL_write(c->ssl, - (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), - (int)(sizeof(uint16_t)-c->tcp_write_byte_count)); - } - } else if(sizeof(uint16_t)+sldns_buffer_remaining(c->buffer) < - LDNS_RR_BUF_SIZE) { - /* combine the tcp length and the query for write, - * this emulates writev */ - uint8_t buf[LDNS_RR_BUF_SIZE]; - memmove(buf, &len, sizeof(uint16_t)); - memmove(buf+sizeof(uint16_t), - sldns_buffer_current(c->buffer), - sldns_buffer_remaining(c->buffer)); - r = SSL_write(c->ssl, (void*)(buf+c->tcp_byte_count), - (int)(sizeof(uint16_t)+ - sldns_buffer_remaining(c->buffer) - - c->tcp_byte_count)); - } else { - r = SSL_write(c->ssl, - (void*)(((uint8_t*)&len)+c->tcp_byte_count), - (int)(sizeof(uint16_t)-c->tcp_byte_count)); - } - if(r <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return 0; /* closed */ - } else if(want == SSL_ERROR_WANT_READ) { - c->ssl_shake_state = comm_ssl_shake_hs_read; - comm_point_listen_for_rw(c, 1, 0); - return 1; /* wait for read condition */ - } else if(want == SSL_ERROR_WANT_WRITE) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); -#endif - return 1; /* write more later */ - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return 0; /* silence 'broken pipe' */ -#endif - if(errno != 0) - log_err("SSL_write syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_write"); - return 0; - } - if(c->tcp_write_and_read) { - c->tcp_write_byte_count += r; - if(c->tcp_write_byte_count < sizeof(uint16_t)) - return 1; - } else { - c->tcp_byte_count += r; - if(c->tcp_byte_count < sizeof(uint16_t)) - return 1; - sldns_buffer_set_position(c->buffer, c->tcp_byte_count - - sizeof(uint16_t)); - } - if((!c->tcp_write_and_read && sldns_buffer_remaining(c->buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { - tcp_callback_writer(c); - return 1; - } - } - log_assert(c->tcp_write_and_read || sldns_buffer_remaining(c->buffer) > 0); - log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); - ERR_clear_error(); - if(c->tcp_write_and_read) { - r = SSL_write(c->ssl, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), - (int)(c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count)); - } else { - r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), - (int)sldns_buffer_remaining(c->buffer)); - } - if(r <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return 0; /* closed */ - } else if(want == SSL_ERROR_WANT_READ) { - c->ssl_shake_state = comm_ssl_shake_hs_read; - comm_point_listen_for_rw(c, 1, 0); - return 1; /* wait for read condition */ - } else if(want == SSL_ERROR_WANT_WRITE) { -#ifdef USE_WINSOCK - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); -#endif - return 1; /* write more later */ - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return 0; /* silence 'broken pipe' */ -#endif - if(errno != 0) - log_err("SSL_write syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_write"); - return 0; - } - if(c->tcp_write_and_read) { - c->tcp_write_byte_count += r; - } else { - sldns_buffer_skip(c->buffer, (ssize_t)r); - } - - if((!c->tcp_write_and_read && sldns_buffer_remaining(c->buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { - tcp_callback_writer(c); - } - return 1; -#else - (void)c; - return 0; -#endif /* HAVE_SSL */ -} - -/** handle ssl tcp connection with dns contents */ -static int -ssl_handle_it(struct comm_point* c, int is_write) -{ - /* handle case where renegotiation wants read during write call - * or write during read calls */ - if(is_write && c->ssl_shake_state == comm_ssl_shake_hs_write) - return ssl_handle_read(c); - else if(!is_write && c->ssl_shake_state == comm_ssl_shake_hs_read) - return ssl_handle_write(c); - /* handle read events for read operation and write events for a - * write operation */ - else if(!is_write) - return ssl_handle_read(c); - return ssl_handle_write(c); -} - -/** - * Handle tcp reading callback. - * @param fd: file descriptor of socket. - * @param c: comm point to read from into buffer. - * @param short_ok: if true, very short packets are OK (for comm_local). - * @return: 0 on error - */ -static int -comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) -{ - ssize_t r; - int recv_initial = 0; - log_assert(c->type == comm_tcp || c->type == comm_local); - if(c->ssl) - return ssl_handle_it(c, 0); - if(!c->tcp_is_reading && !c->tcp_write_and_read) - return 0; - - log_assert(fd != -1); - if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { - struct pp2_header* header = NULL; - size_t want_read_size = 0; - size_t current_read_size = 0; - if(c->pp2_header_state == pp2_header_none) { - want_read_size = PP2_HEADER_SIZE; - if(sldns_buffer_remaining(c->buffer)repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: reading fixed " - "part of PROXYv2 header (len %lu)", - (unsigned long)want_read_size); - current_read_size = want_read_size; - if(c->tcp_byte_count < current_read_size) { - r = recv(fd, (void*)sldns_buffer_at(c->buffer, - c->tcp_byte_count), - current_read_size-c->tcp_byte_count, MSG_DONTWAIT); - if(r == 0) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; - } else if(r == -1) { - goto recv_error_initial; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count != current_read_size) return 1; - c->pp2_header_state = pp2_header_init; - } - } - if(c->pp2_header_state == pp2_header_init) { - header = pp2_read_header(c->buffer); - if(!header) { - log_err("proxy_protocol: could not parse " - "PROXYv2 header"); - return 0; - } - want_read_size = ntohs(header->len); - if(sldns_buffer_remaining(c->buffer) < - PP2_HEADER_SIZE + want_read_size) { - log_err_addr("proxy_protocol: not enough " - "buffer size to read PROXYv2 header", "", - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: reading variable " - "part of PROXYv2 header (len %lu)", - (unsigned long)want_read_size); - current_read_size = PP2_HEADER_SIZE + want_read_size; - if(want_read_size == 0) { - /* nothing more to read; header is complete */ - c->pp2_header_state = pp2_header_done; - } else if(c->tcp_byte_count < current_read_size) { - r = recv(fd, (void*)sldns_buffer_at(c->buffer, - c->tcp_byte_count), - current_read_size-c->tcp_byte_count, MSG_DONTWAIT); - if(r == 0) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; - } else if(r == -1) { - goto recv_error; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count != current_read_size) return 1; - c->pp2_header_state = pp2_header_done; - } - } - if(c->pp2_header_state != pp2_header_done || !header) { - log_err_addr("proxy_protocol: wrong state for the " - "PROXYv2 header", "", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { - log_err_addr("proxy_protocol: could not consume " - "PROXYv2 header", "", &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "proxy_protocol: successful read of " - "PROXYv2 header"); - /* Clear and reset the buffer to read the following - * DNS packet(s). */ - sldns_buffer_clear(c->buffer); - c->tcp_byte_count = 0; - return 1; - } - - if(c->tcp_byte_count < sizeof(uint16_t)) { - /* read length bytes */ - r = recv(fd,(void*)sldns_buffer_at(c->buffer,c->tcp_byte_count), - sizeof(uint16_t)-c->tcp_byte_count, MSG_DONTWAIT); - if(r == 0) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; - } else if(r == -1) { - if(c->pp2_enabled) goto recv_error; - goto recv_error_initial; - } - c->tcp_byte_count += r; - if(c->tcp_byte_count != sizeof(uint16_t)) - return 1; - if(sldns_buffer_read_u16_at(c->buffer, 0) > - sldns_buffer_capacity(c->buffer)) { - verbose(VERB_QUERY, "tcp: dropped larger than buffer"); - return 0; - } - sldns_buffer_set_limit(c->buffer, - sldns_buffer_read_u16_at(c->buffer, 0)); - if(!short_ok && - sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { - verbose(VERB_QUERY, "tcp: dropped bogus too short."); - return 0; - } - verbose(VERB_ALGO, "Reading tcp query of length %d", - (int)sldns_buffer_limit(c->buffer)); - } - - if(sldns_buffer_remaining(c->buffer) == 0) - log_err("in comm_point_tcp_handle_read buffer_remaining is " - "not > 0 as expected, continuing with (harmless) 0 " - "length recv"); - r = recv(fd, (void*)sldns_buffer_current(c->buffer), - sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); - if(r == 0) { - if(c->tcp_req_info) - return tcp_req_info_handle_read_close(c->tcp_req_info); - return 0; - } else if(r == -1) { - goto recv_error; - } - sldns_buffer_skip(c->buffer, r); - if(sldns_buffer_remaining(c->buffer) <= 0) { - tcp_callback_reader(c); - } - return 1; - -recv_error_initial: - recv_initial = 1; -recv_error: -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 1; - if(recv_initial) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif -#ifdef ECONNREFUSED - if(errno == ECONNREFUSED && verbosity < 2) - return 0; /* silence reset by peer */ -#endif -#ifdef ENETUNREACH - if(errno == ENETUNREACH && verbosity < 2) - return 0; /* silence it */ -#endif -#ifdef EHOSTDOWN - if(errno == EHOSTDOWN && verbosity < 2) - return 0; /* silence it */ -#endif -#ifdef EHOSTUNREACH - if(errno == EHOSTUNREACH && verbosity < 2) - return 0; /* silence it */ -#endif -#ifdef ENETDOWN - if(errno == ENETDOWN && verbosity < 2) - return 0; /* silence it */ -#endif -#ifdef EACCES - if(errno == EACCES && verbosity < 2) - return 0; /* silence it */ -#endif -#ifdef ENOTCONN - if(errno == ENOTCONN) { - log_err_addr("read (in tcp s) failed and this " - "could be because TCP Fast Open is " - "enabled [--disable-tfo-client " - "--disable-tfo-server] but does not " - "work", sock_strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } -#endif - } -#else /* USE_WINSOCK */ - if(recv_initial) { - if(WSAGetLastError() == WSAECONNREFUSED && verbosity < 2) - return 0; - if(WSAGetLastError() == WSAEHOSTDOWN && verbosity < 2) - return 0; - if(WSAGetLastError() == WSAEHOSTUNREACH && verbosity < 2) - return 0; - if(WSAGetLastError() == WSAENETDOWN && verbosity < 2) - return 0; - if(WSAGetLastError() == WSAENETUNREACH && verbosity < 2) - return 0; - } - if(WSAGetLastError() == WSAECONNRESET) - return 0; - if(WSAGetLastError() == WSAEINPROGRESS) - return 1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, - UB_EV_READ); - return 1; - } -#endif - log_err_addr("read (in tcp s)", sock_strerror(errno), - &c->repinfo.remote_addr, c->repinfo.remote_addrlen); - return 0; -} - -/** - * Handle tcp writing callback. - * @param fd: file descriptor of socket. - * @param c: comm point to write buffer out of. - * @return: 0 on error - */ -static int -comm_point_tcp_handle_write(int fd, struct comm_point* c) -{ - ssize_t r; - struct sldns_buffer *buffer; - log_assert(c->type == comm_tcp); -#ifdef USE_DNSCRYPT - buffer = c->dnscrypt_buffer; -#else - buffer = c->buffer; -#endif - if(c->tcp_is_reading && !c->ssl && !c->tcp_write_and_read) - return 0; - log_assert(fd != -1); - if(((!c->tcp_write_and_read && c->tcp_byte_count == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == 0)) && c->tcp_check_nb_connect) { - /* check for pending error from nonblocking connect */ - /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ - int error = 0; - socklen_t len = (socklen_t)sizeof(error); - if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, - &len) < 0){ -#ifndef USE_WINSOCK - error = errno; /* on solaris errno is error */ -#else /* USE_WINSOCK */ - error = WSAGetLastError(); -#endif - } -#ifndef USE_WINSOCK -#if defined(EINPROGRESS) && defined(EWOULDBLOCK) - if(error == EINPROGRESS || error == EWOULDBLOCK) - return 1; /* try again later */ - else -#endif - if(error != 0 && verbosity < 2) - return 0; /* silence lots of chatter in the logs */ - else if(error != 0) { - log_err_addr("tcp connect", strerror(error), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -#else /* USE_WINSOCK */ - /* examine error */ - if(error == WSAEINPROGRESS) - return 1; - else if(error == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); - return 1; - } else if(error != 0 && verbosity < 2) - return 0; - else if(error != 0) { - log_err_addr("tcp connect", wsa_strerror(error), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -#endif /* USE_WINSOCK */ - return 0; - } - } - if(c->ssl) - return ssl_handle_it(c, 1); - -#ifdef USE_MSG_FASTOPEN - /* Only try this on first use of a connection that uses tfo, - otherwise fall through to normal write */ - /* Also, TFO support on WINDOWS not implemented at the moment */ - if(c->tcp_do_fastopen == 1) { - /* this form of sendmsg() does both a connect() and send() so need to - look for various flavours of error*/ - uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); - struct msghdr msg; - struct iovec iov[2]; - c->tcp_do_fastopen = 0; - memset(&msg, 0, sizeof(msg)); - if(c->tcp_write_and_read) { - iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; - iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; - iov[1].iov_base = c->tcp_write_pkt; - iov[1].iov_len = c->tcp_write_pkt_len; - } else { - iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; - iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; - iov[1].iov_base = sldns_buffer_begin(buffer); - iov[1].iov_len = sldns_buffer_limit(buffer); - } - log_assert(iov[0].iov_len > 0); - msg.msg_name = &c->repinfo.remote_addr; - msg.msg_namelen = c->repinfo.remote_addrlen; - msg.msg_iov = iov; - msg.msg_iovlen = 2; - r = sendmsg(fd, &msg, MSG_FASTOPEN); - if (r == -1) { -#if defined(EINPROGRESS) && defined(EWOULDBLOCK) - /* Handshake is underway, maybe because no TFO cookie available. - Come back to write the message*/ - if(errno == EINPROGRESS || errno == EWOULDBLOCK) - return 1; -#endif - if(errno == EINTR || errno == EAGAIN) - return 1; - /* Not handling EISCONN here as shouldn't ever hit that case.*/ - if(errno != EPIPE -#ifdef EOPNOTSUPP - /* if /proc/sys/net/ipv4/tcp_fastopen is - * disabled on Linux, sendmsg may return - * 'Operation not supported', if so - * fallthrough to ordinary connect. */ - && errno != EOPNOTSUPP -#endif - && errno != 0) { - if(verbosity < 2) - return 0; /* silence lots of chatter in the logs */ - log_err_addr("tcp sendmsg", strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "tcp sendmsg for fastopen failed (with %s), try normal connect", strerror(errno)); - /* fallthrough to nonFASTOPEN - * (MSG_FASTOPEN on Linux 3 produces EPIPE) - * we need to perform connect() */ - if(connect(fd, (struct sockaddr *)&c->repinfo.remote_addr, - c->repinfo.remote_addrlen) == -1) { -#ifdef EINPROGRESS - if(errno == EINPROGRESS) - return 1; /* wait until connect done*/ -#endif -#ifdef USE_WINSOCK - if(WSAGetLastError() == WSAEINPROGRESS || - WSAGetLastError() == WSAEWOULDBLOCK) - return 1; /* wait until connect done*/ -#endif - if(tcp_connect_errno_needs_log( - (struct sockaddr *)&c->repinfo.remote_addr, - c->repinfo.remote_addrlen)) { - log_err_addr("outgoing tcp: connect after EPIPE for fastopen", - strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - } - return 0; - } - - } else { - if(c->tcp_write_and_read) { - c->tcp_write_byte_count += r; - if(c->tcp_write_byte_count < sizeof(uint16_t)) - return 1; - } else { - c->tcp_byte_count += r; - if(c->tcp_byte_count < sizeof(uint16_t)) - return 1; - sldns_buffer_set_position(buffer, c->tcp_byte_count - - sizeof(uint16_t)); - } - if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { - tcp_callback_writer(c); - return 1; - } - } - } -#endif /* USE_MSG_FASTOPEN */ - - if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { - uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); -#ifdef HAVE_WRITEV - struct iovec iov[2]; - if(c->tcp_write_and_read) { - iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; - iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; - iov[1].iov_base = c->tcp_write_pkt; - iov[1].iov_len = c->tcp_write_pkt_len; - } else { - iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; - iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; - iov[1].iov_base = sldns_buffer_begin(buffer); - iov[1].iov_len = sldns_buffer_limit(buffer); - } - log_assert(iov[0].iov_len > 0); - r = writev(fd, iov, 2); -#else /* HAVE_WRITEV */ - if(c->tcp_write_and_read) { - r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), - sizeof(uint16_t)-c->tcp_write_byte_count, 0); - } else { - r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count), - sizeof(uint16_t)-c->tcp_byte_count, 0); - } -#endif /* HAVE_WRITEV */ - if(r == -1) { -#ifndef USE_WINSOCK -# ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return 0; /* silence 'broken pipe' */ - #endif - if(errno == EINTR || errno == EAGAIN) - return 1; -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif -# ifdef HAVE_WRITEV - log_err_addr("tcp writev", strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -# else /* HAVE_WRITEV */ - log_err_addr("tcp send s", strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -# endif /* HAVE_WRITEV */ -#else - if(WSAGetLastError() == WSAENOTCONN) - return 1; - if(WSAGetLastError() == WSAEINPROGRESS) - return 1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, - UB_EV_WRITE); - return 1; - } - if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ - log_err_addr("tcp send s", - wsa_strerror(WSAGetLastError()), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); -#endif - return 0; - } - if(c->tcp_write_and_read) { - c->tcp_write_byte_count += r; - if(c->tcp_write_byte_count < sizeof(uint16_t)) - return 1; - } else { - c->tcp_byte_count += r; - if(c->tcp_byte_count < sizeof(uint16_t)) - return 1; - sldns_buffer_set_position(buffer, c->tcp_byte_count - - sizeof(uint16_t)); - } - if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { - tcp_callback_writer(c); - return 1; - } - } - log_assert(c->tcp_write_and_read || sldns_buffer_remaining(buffer) > 0); - log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); - if(c->tcp_write_and_read) { - r = send(fd, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), - c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count, 0); - } else { - r = send(fd, (void*)sldns_buffer_current(buffer), - sldns_buffer_remaining(buffer), 0); - } - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 1; -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif -#else - if(WSAGetLastError() == WSAEINPROGRESS) - return 1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); - return 1; - } - if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - log_err_addr("tcp send r", sock_strerror(errno), - &c->repinfo.remote_addr, - c->repinfo.remote_addrlen); - return 0; - } - if(c->tcp_write_and_read) { - c->tcp_write_byte_count += r; - } else { - sldns_buffer_skip(buffer, r); - } - - if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { - tcp_callback_writer(c); - } - - return 1; -} - -/** read again to drain buffers when there could be more to read, returns 0 - * on failure which means the comm point is closed. */ -static int -tcp_req_info_read_again(int fd, struct comm_point* c) -{ - while(c->tcp_req_info->read_again) { - int r; - c->tcp_req_info->read_again = 0; - if(c->tcp_is_reading) - r = comm_point_tcp_handle_read(fd, c, 0); - else r = comm_point_tcp_handle_write(fd, c); - if(!r) { - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return 0; - } - } - return 1; -} - -/** read again to drain buffers when there could be more to read */ -static void -tcp_more_read_again(int fd, struct comm_point* c) -{ - /* if the packet is done, but another one could be waiting on - * the connection, the callback signals this, and we try again */ - /* this continues until the read routines get EAGAIN or so, - * and thus does not call the callback, and the bool is 0 */ - int* moreread = c->tcp_more_read_again; - while(moreread && *moreread) { - *moreread = 0; - if(!comm_point_tcp_handle_read(fd, c, 0)) { - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return; - } - } -} - -/** write again to fill up when there could be more to write */ -static void -tcp_more_write_again(int fd, struct comm_point* c) -{ - /* if the packet is done, but another is waiting to be written, - * the callback signals it and we try again. */ - /* this continues until the write routines get EAGAIN or so, - * and thus does not call the callback, and the bool is 0 */ - int* morewrite = c->tcp_more_write_again; - while(morewrite && *morewrite) { - *morewrite = 0; - if(!comm_point_tcp_handle_write(fd, c)) { - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return; - } - } -} - -void -comm_point_tcp_handle_callback(int fd, short event, void* arg) -{ - struct comm_point* c = (struct comm_point*)arg; - log_assert(c->type == comm_tcp); - ub_comm_base_now(c->ev->base); - - if(c->fd == -1 || c->fd != fd) - return; /* duplicate event, but commpoint closed. */ - -#ifdef USE_DNSCRYPT - /* Initialize if this is a dnscrypt socket */ - if(c->tcp_parent) { - c->dnscrypt = c->tcp_parent->dnscrypt; - } - if(c->dnscrypt && c->dnscrypt_buffer == c->buffer) { - c->dnscrypt_buffer = sldns_buffer_new(sldns_buffer_capacity(c->buffer)); - if(!c->dnscrypt_buffer) { - log_err("Could not allocate dnscrypt buffer"); - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return; - } - } -#endif - - if(event&UB_EV_TIMEOUT) { - verbose(VERB_QUERY, "tcp took too long, dropped"); - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_TIMEOUT, NULL); - } - return; - } - if(event&UB_EV_READ -#ifdef USE_MSG_FASTOPEN - && !(c->tcp_do_fastopen && (event&UB_EV_WRITE)) -#endif - ) { - int has_tcpq = (c->tcp_req_info != NULL); - int* moreread = c->tcp_more_read_again; - if(!comm_point_tcp_handle_read(fd, c, 0)) { - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return; - } - if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { - if(!tcp_req_info_read_again(fd, c)) - return; - } - if(moreread && *moreread) - tcp_more_read_again(fd, c); - return; - } - if(event&UB_EV_WRITE) { - int has_tcpq = (c->tcp_req_info != NULL); - int* morewrite = c->tcp_more_write_again; - if(!comm_point_tcp_handle_write(fd, c)) { - reclaim_tcp_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - return; - } - if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { - if(!tcp_req_info_read_again(fd, c)) - return; - } - if(morewrite && *morewrite) - tcp_more_write_again(fd, c); - return; - } - log_err("Ignored event %d for tcphdl.", event); -} - -/** Make http handler free for next assignment */ -static void -reclaim_http_handler(struct comm_point* c) -{ - log_assert(c->type == comm_http); - if(c->ssl) { -#ifdef HAVE_SSL - SSL_shutdown(c->ssl); - SSL_free(c->ssl); - c->ssl = NULL; -#endif - } - comm_point_close(c); - if(c->tcp_parent) { - if(c != c->tcp_parent->tcp_free) { - c->tcp_parent->cur_tcp_count--; - c->tcp_free = c->tcp_parent->tcp_free; - c->tcp_parent->tcp_free = c; - } - if(!c->tcp_free) { - /* re-enable listening on accept socket */ - comm_point_start_listening(c->tcp_parent, -1, -1); - } - } -} - -/** read more data for http (with ssl) */ -static int -ssl_http_read_more(struct comm_point* c) -{ -#ifdef HAVE_SSL - int r; - log_assert(sldns_buffer_remaining(c->buffer) > 0); - ERR_clear_error(); - r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), - (int)sldns_buffer_remaining(c->buffer)); - if(r <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return 0; /* shutdown, closed */ - } else if(want == SSL_ERROR_WANT_READ) { - return 1; /* read more later */ - } else if(want == SSL_ERROR_WANT_WRITE) { - c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(c, 0, 1); - return 1; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return 0; /* silence reset by peer */ -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_read"); - return 0; - } - verbose(VERB_ALGO, "ssl http read more skip to %d + %d", - (int)sldns_buffer_position(c->buffer), (int)r); - sldns_buffer_skip(c->buffer, (ssize_t)r); - return 1; -#else - (void)c; - return 0; -#endif /* HAVE_SSL */ -} - -/** read more data for http */ -static int -http_read_more(int fd, struct comm_point* c) -{ - ssize_t r; - log_assert(sldns_buffer_remaining(c->buffer) > 0); - r = recv(fd, (void*)sldns_buffer_current(c->buffer), - sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); - if(r == 0) { - return 0; - } else if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 1; -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAECONNRESET) - return 0; - if(WSAGetLastError() == WSAEINPROGRESS) - return 1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); - return 1; - } -#endif - log_err_addr("read (in http r)", sock_strerror(errno), - &c->repinfo.remote_addr, c->repinfo.remote_addrlen); - return 0; - } - verbose(VERB_ALGO, "http read more skip to %d + %d", - (int)sldns_buffer_position(c->buffer), (int)r); - sldns_buffer_skip(c->buffer, r); - return 1; -} - -/** return true if http header has been read (one line complete) */ -static int -http_header_done(sldns_buffer* buf) -{ - size_t i; - for(i=sldns_buffer_position(buf); ibuffer); - if(!line) return 1; - verbose(VERB_ALGO, "http header: %s", line); - if(strncasecmp(line, "HTTP/1.1 ", 9) == 0) { - /* check returncode */ - if(line[9] != '2') { - verbose(VERB_ALGO, "http bad status %s", line+9); - return 0; - } - } else if(strncasecmp(line, "Content-Length: ", 16) == 0) { - if(!c->http_is_chunked) - c->tcp_byte_count = (size_t)atoi(line+16); - } else if(strncasecmp(line, "Transfer-Encoding: chunked", 19+7) == 0) { - c->tcp_byte_count = 0; - c->http_is_chunked = 1; - } else if(line[0] == 0) { - /* end of initial headers */ - c->http_in_headers = 0; - if(c->http_is_chunked) - c->http_in_chunk_headers = 1; - /* remove header text from front of buffer - * the buffer is going to be used to return the data segment - * itself and we don't want the header to get returned - * prepended with it */ - http_moveover_buffer(c->buffer); - sldns_buffer_flip(c->buffer); - return 1; - } - /* ignore other headers */ - return 1; -} - -/** a chunk header is complete, process it, return 0=fail, 1=continue next - * header line, 2=done with chunked transfer*/ -static int -http_process_chunk_header(struct comm_point* c) -{ - char* line = http_header_line(c->buffer); - if(!line) return 1; - if(c->http_in_chunk_headers == 3) { - verbose(VERB_ALGO, "http chunk trailer: %s", line); - /* are we done ? */ - if(line[0] == 0 && c->tcp_byte_count == 0) { - /* callback of http reader when NETEVENT_DONE, - * end of data, with no data in buffer */ - sldns_buffer_set_position(c->buffer, 0); - sldns_buffer_set_limit(c->buffer, 0); - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); - /* return that we are done */ - return 2; - } - if(line[0] == 0) { - /* continue with header of the next chunk */ - c->http_in_chunk_headers = 1; - /* remove header text from front of buffer */ - http_moveover_buffer(c->buffer); - sldns_buffer_flip(c->buffer); - return 1; - } - /* ignore further trail headers */ - return 1; - } - verbose(VERB_ALGO, "http chunk header: %s", line); - if(c->http_in_chunk_headers == 1) { - /* read chunked start line */ - char* end = NULL; - c->tcp_byte_count = (size_t)strtol(line, &end, 16); - if(end == line) - return 0; - c->http_in_chunk_headers = 0; - /* remove header text from front of buffer */ - http_moveover_buffer(c->buffer); - sldns_buffer_flip(c->buffer); - if(c->tcp_byte_count == 0) { - /* done with chunks, process chunk_trailer lines */ - c->http_in_chunk_headers = 3; - } - return 1; - } - /* ignore other headers */ - return 1; -} - -/** handle nonchunked data segment, 0=fail, 1=wait */ -static int -http_nonchunk_segment(struct comm_point* c) -{ - /* c->buffer at position..limit has new data we read in. - * the buffer itself is full of nonchunked data. - * we are looking to read tcp_byte_count more data - * and then the transfer is done. */ - size_t remainbufferlen; - size_t got_now = sldns_buffer_limit(c->buffer); - if(c->tcp_byte_count <= got_now) { - /* done, this is the last data fragment */ - c->http_stored = 0; - sldns_buffer_set_position(c->buffer, 0); - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); - return 1; - } - /* if we have the buffer space, - * read more data collected into the buffer */ - remainbufferlen = sldns_buffer_capacity(c->buffer) - - sldns_buffer_limit(c->buffer); - if(remainbufferlen+got_now >= c->tcp_byte_count || - remainbufferlen >= (size_t)(c->ssl?16384:2048)) { - size_t total = sldns_buffer_limit(c->buffer); - sldns_buffer_clear(c->buffer); - sldns_buffer_set_position(c->buffer, total); - c->http_stored = total; - /* return and wait to read more */ - return 1; - } - /* call callback with this data amount, then - * wait for more */ - c->tcp_byte_count -= got_now; - c->http_stored = 0; - sldns_buffer_set_position(c->buffer, 0); - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); - /* c->callback has to buffer_clear(c->buffer). */ - /* return and wait to read more */ - return 1; -} - -/** handle chunked data segment, return 0=fail, 1=wait, 2=process more */ -static int -http_chunked_segment(struct comm_point* c) -{ - /* the c->buffer has from position..limit new data we read. */ - /* the current chunk has length tcp_byte_count. - * once we read that read more chunk headers. - */ - size_t remainbufferlen; - size_t got_now = sldns_buffer_limit(c->buffer) - c->http_stored; - verbose(VERB_ALGO, "http_chunked_segment: got now %d, tcpbytcount %d, http_stored %d, buffer pos %d, buffer limit %d", (int)got_now, (int)c->tcp_byte_count, (int)c->http_stored, (int)sldns_buffer_position(c->buffer), (int)sldns_buffer_limit(c->buffer)); - if(c->tcp_byte_count <= got_now) { - /* the chunk has completed (with perhaps some extra data - * from next chunk header and next chunk) */ - /* save too much info into temp buffer */ - size_t fraglen; - struct comm_reply repinfo; - c->http_stored = 0; - sldns_buffer_skip(c->buffer, (ssize_t)c->tcp_byte_count); - sldns_buffer_clear(c->http_temp); - sldns_buffer_write(c->http_temp, - sldns_buffer_current(c->buffer), - sldns_buffer_remaining(c->buffer)); - sldns_buffer_flip(c->http_temp); - - /* callback with this fragment */ - fraglen = sldns_buffer_position(c->buffer); - sldns_buffer_set_position(c->buffer, 0); - sldns_buffer_set_limit(c->buffer, fraglen); - repinfo = c->repinfo; - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &repinfo); - /* c->callback has to buffer_clear(). */ - - /* is commpoint deleted? */ - if(!repinfo.c) { - return 1; - } - /* copy waiting info */ - sldns_buffer_clear(c->buffer); - sldns_buffer_write(c->buffer, - sldns_buffer_begin(c->http_temp), - sldns_buffer_remaining(c->http_temp)); - sldns_buffer_flip(c->buffer); - /* process end of chunk trailer header lines, until - * an empty line */ - c->http_in_chunk_headers = 3; - /* process more data in buffer (if any) */ - return 2; - } - c->tcp_byte_count -= got_now; - - /* if we have the buffer space, - * read more data collected into the buffer */ - remainbufferlen = sldns_buffer_capacity(c->buffer) - - sldns_buffer_limit(c->buffer); - if(remainbufferlen >= c->tcp_byte_count || - remainbufferlen >= 2048) { - size_t total = sldns_buffer_limit(c->buffer); - sldns_buffer_clear(c->buffer); - sldns_buffer_set_position(c->buffer, total); - c->http_stored = total; - /* return and wait to read more */ - return 1; - } - - /* callback of http reader for a new part of the data */ - c->http_stored = 0; - sldns_buffer_set_position(c->buffer, 0); - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); - /* c->callback has to buffer_clear(c->buffer). */ - /* return and wait to read more */ - return 1; -} - -#ifdef HAVE_NGHTTP2 -/** Create new http2 session. Called when creating handling comm point. */ -static struct http2_session* http2_session_create(struct comm_point* c) -{ - struct http2_session* session = calloc(1, sizeof(*session)); - if(!session) { - log_err("malloc failure while creating http2 session"); - return NULL; - } - session->c = c; - - return session; -} -#endif - -/** Delete http2 session. After closing connection or on error */ -static void http2_session_delete(struct http2_session* h2_session) -{ -#ifdef HAVE_NGHTTP2 - if(h2_session->callbacks) - nghttp2_session_callbacks_del(h2_session->callbacks); - free(h2_session); -#else - (void)h2_session; -#endif -} - -#ifdef HAVE_NGHTTP2 -struct http2_stream* http2_stream_create(int32_t stream_id) -{ - struct http2_stream* h2_stream = calloc(1, sizeof(*h2_stream)); - if(!h2_stream) { - log_err("malloc failure while creating http2 stream"); - return NULL; - } - h2_stream->stream_id = stream_id; - return h2_stream; -} - -/** Delete http2 stream. After session delete or stream close callback */ -static void http2_stream_delete(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - if(h2_stream->mesh_state) { - mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state, - h2_session->c); - h2_stream->mesh_state = NULL; - } - http2_req_stream_clear(h2_stream); - free(h2_stream); -} -#endif - -void http2_stream_add_meshstate(struct http2_stream* h2_stream, - struct mesh_area* mesh, struct mesh_state* m) -{ - h2_stream->mesh = mesh; - h2_stream->mesh_state = m; -} - -/** delete http2 session server. After closing connection. */ -static void http2_session_server_delete(struct http2_session* h2_session) -{ -#ifdef HAVE_NGHTTP2 - struct http2_stream* h2_stream, *next; - nghttp2_session_del(h2_session->session); /* NULL input is fine */ - h2_session->session = NULL; - for(h2_stream = h2_session->first_stream; h2_stream;) { - next = h2_stream->next; - http2_stream_delete(h2_session, h2_stream); - h2_stream = next; - } - h2_session->first_stream = NULL; - h2_session->is_drop = 0; - h2_session->postpone_drop = 0; - h2_session->c->h2_stream = NULL; -#endif - (void)h2_session; -} - -#ifdef HAVE_NGHTTP2 -void http2_session_add_stream(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - if(h2_session->first_stream) - h2_session->first_stream->prev = h2_stream; - h2_stream->next = h2_session->first_stream; - h2_session->first_stream = h2_stream; -} - -/** remove stream from session linked list. After stream close callback or - * closing connection */ -static void http2_session_remove_stream(struct http2_session* h2_session, - struct http2_stream* h2_stream) -{ - if(h2_stream->prev) - h2_stream->prev->next = h2_stream->next; - else - h2_session->first_stream = h2_stream->next; - if(h2_stream->next) - h2_stream->next->prev = h2_stream->prev; - -} - -int http2_stream_close_cb(nghttp2_session* ATTR_UNUSED(session), - int32_t stream_id, uint32_t ATTR_UNUSED(error_code), void* cb_arg) -{ - struct http2_stream* h2_stream; - struct http2_session* h2_session = (struct http2_session*)cb_arg; - if(!(h2_stream = nghttp2_session_get_stream_user_data( - h2_session->session, stream_id))) { - return 0; - } - http2_session_remove_stream(h2_session, h2_stream); - http2_stream_delete(h2_session, h2_stream); - return 0; -} - -ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf, - size_t len, int ATTR_UNUSED(flags), void* cb_arg) -{ - struct http2_session* h2_session = (struct http2_session*)cb_arg; - ssize_t ret; - - log_assert(h2_session->c->type == comm_http); - log_assert(h2_session->c->h2_session); - -#ifdef HAVE_SSL - if(h2_session->c->ssl) { - int r; - ERR_clear_error(); - r = SSL_read(h2_session->c->ssl, buf, len); - if(r <= 0) { - int want = SSL_get_error(h2_session->c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return NGHTTP2_ERR_EOF; - } else if(want == SSL_ERROR_WANT_READ) { - return NGHTTP2_ERR_WOULDBLOCK; - } else if(want == SSL_ERROR_WANT_WRITE) { - h2_session->c->ssl_shake_state = comm_ssl_shake_hs_write; - comm_point_listen_for_rw(h2_session->c, 0, 1); - return NGHTTP2_ERR_WOULDBLOCK; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; -#endif - if(errno != 0) - log_err("SSL_read syscall: %s", - strerror(errno)); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - log_crypto_err("could not SSL_read"); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return r; - } -#endif /* HAVE_SSL */ - - ret = recv(h2_session->c->fd, buf, len, MSG_DONTWAIT); - if(ret == 0) { - return NGHTTP2_ERR_EOF; - } else if(ret < 0) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return NGHTTP2_ERR_WOULDBLOCK; -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; -#endif - log_err_addr("could not http2 recv: %s", strerror(errno), - &h2_session->c->repinfo.remote_addr, - h2_session->c->repinfo.remote_addrlen); -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAECONNRESET) - return NGHTTP2_ERR_CALLBACK_FAILURE; - if(WSAGetLastError() == WSAEINPROGRESS) - return NGHTTP2_ERR_WOULDBLOCK; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, - UB_EV_READ); - return NGHTTP2_ERR_WOULDBLOCK; - } - log_err_addr("could not http2 recv: %s", - wsa_strerror(WSAGetLastError()), - &h2_session->c->repinfo.remote_addr, - h2_session->c->repinfo.remote_addrlen); -#endif - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return ret; -} -#endif /* HAVE_NGHTTP2 */ - -/** Handle http2 read */ -static int -comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c) -{ -#ifdef HAVE_NGHTTP2 - int ret; - log_assert(c->h2_session); - - /* reading until recv cb returns NGHTTP2_ERR_WOULDBLOCK */ - ret = nghttp2_session_recv(c->h2_session->session); - if(ret) { - if(ret != NGHTTP2_ERR_EOF && - ret != NGHTTP2_ERR_CALLBACK_FAILURE) { - char a[256]; - addr_to_str(&c->repinfo.remote_addr, - c->repinfo.remote_addrlen, a, sizeof(a)); - verbose(VERB_QUERY, "http2: session_recv from %s failed, " - "error: %s", a, nghttp2_strerror(ret)); - } - return 0; - } - if(nghttp2_session_want_write(c->h2_session->session)) { - c->tcp_is_reading = 0; - comm_point_stop_listening(c); - comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); - } else if(!nghttp2_session_want_read(c->h2_session->session)) - return 0; /* connection can be closed */ - return 1; -#else - (void)c; - return 0; -#endif -} - -/** - * Handle http reading callback. - * @param fd: file descriptor of socket. - * @param c: comm point to read from into buffer. - * @return: 0 on error - */ -static int -comm_point_http_handle_read(int fd, struct comm_point* c) -{ - log_assert(c->type == comm_http); - log_assert(fd != -1); - - /* if we are in ssl handshake, handle SSL handshake */ -#ifdef HAVE_SSL - if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { - if(!ssl_handshake(c)) - return 0; - if(c->ssl_shake_state != comm_ssl_shake_none) - return 1; - } -#endif /* HAVE_SSL */ - - if(!c->tcp_is_reading) - return 1; - - if(c->use_h2) { - return comm_point_http2_handle_read(fd, c); - } - - /* http version is <= http/1.1 */ - - if(c->http_min_version >= http_version_2) { - /* HTTP/2 failed, not allowed to use lower version. */ - return 0; - } - - /* read more data */ - if(c->ssl) { - if(!ssl_http_read_more(c)) - return 0; - } else { - if(!http_read_more(fd, c)) - return 0; - } - - if(c->http_stored >= sldns_buffer_position(c->buffer)) { - /* read did not work but we wanted more data, there is - * no bytes to process now. */ - return 1; - } - sldns_buffer_flip(c->buffer); - /* if we are partway in a segment of data, position us at the point - * where we left off previously */ - if(c->http_stored < sldns_buffer_limit(c->buffer)) - sldns_buffer_set_position(c->buffer, c->http_stored); - else sldns_buffer_set_position(c->buffer, sldns_buffer_limit(c->buffer)); - - while(sldns_buffer_remaining(c->buffer) > 0) { - /* Handle HTTP/1.x data */ - /* if we are reading headers, read more headers */ - if(c->http_in_headers || c->http_in_chunk_headers) { - /* if header is done, process the header */ - if(!http_header_done(c->buffer)) { - /* copy remaining data to front of buffer - * and set rest for writing into it */ - http_moveover_buffer(c->buffer); - /* return and wait to read more */ - return 1; - } - if(!c->http_in_chunk_headers) { - /* process initial headers */ - if(!http_process_initial_header(c)) - return 0; - } else { - /* process chunk headers */ - int r = http_process_chunk_header(c); - if(r == 0) return 0; - if(r == 2) return 1; /* done */ - /* r == 1, continue */ - } - /* see if we have more to process */ - continue; - } - - if(!c->http_is_chunked) { - /* if we are reading nonchunks, process that*/ - return http_nonchunk_segment(c); - } else { - /* if we are reading chunks, read the chunk */ - int r = http_chunked_segment(c); - if(r == 0) return 0; - if(r == 1) return 1; - continue; - } - } - /* broke out of the loop; could not process header instead need - * to read more */ - /* moveover any remaining data and read more data */ - http_moveover_buffer(c->buffer); - /* return and wait to read more */ - return 1; -} - -/** check pending connect for http */ -static int -http_check_connect(int fd, struct comm_point* c) -{ - /* check for pending error from nonblocking connect */ - /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ - int error = 0; - socklen_t len = (socklen_t)sizeof(error); - if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, - &len) < 0){ -#ifndef USE_WINSOCK - error = errno; /* on solaris errno is error */ -#else /* USE_WINSOCK */ - error = WSAGetLastError(); -#endif - } -#ifndef USE_WINSOCK -#if defined(EINPROGRESS) && defined(EWOULDBLOCK) - if(error == EINPROGRESS || error == EWOULDBLOCK) - return 1; /* try again later */ - else -#endif - if(error != 0 && verbosity < 2) - return 0; /* silence lots of chatter in the logs */ - else if(error != 0) { - log_err_addr("http connect", strerror(error), - &c->repinfo.remote_addr, c->repinfo.remote_addrlen); -#else /* USE_WINSOCK */ - /* examine error */ - if(error == WSAEINPROGRESS) - return 1; - else if(error == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); - return 1; - } else if(error != 0 && verbosity < 2) - return 0; - else if(error != 0) { - log_err_addr("http connect", wsa_strerror(error), - &c->repinfo.remote_addr, c->repinfo.remote_addrlen); -#endif /* USE_WINSOCK */ - return 0; - } - /* keep on processing this socket */ - return 2; -} - -/** write more data for http (with ssl) */ -static int -ssl_http_write_more(struct comm_point* c) -{ -#ifdef HAVE_SSL - int r; - log_assert(sldns_buffer_remaining(c->buffer) > 0); - ERR_clear_error(); - r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), - (int)sldns_buffer_remaining(c->buffer)); - if(r <= 0) { - int want = SSL_get_error(c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return 0; /* closed */ - } else if(want == SSL_ERROR_WANT_READ) { - c->ssl_shake_state = comm_ssl_shake_hs_read; - comm_point_listen_for_rw(c, 1, 0); - return 1; /* wait for read condition */ - } else if(want == SSL_ERROR_WANT_WRITE) { - return 1; /* write more later */ - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return 0; /* silence 'broken pipe' */ -#endif - if(errno != 0) - log_err("SSL_write syscall: %s", - strerror(errno)); - return 0; - } - log_crypto_err("could not SSL_write"); - return 0; - } - sldns_buffer_skip(c->buffer, (ssize_t)r); - return 1; -#else - (void)c; - return 0; -#endif /* HAVE_SSL */ -} - -/** write more data for http */ -static int -http_write_more(int fd, struct comm_point* c) -{ - ssize_t r; - log_assert(sldns_buffer_remaining(c->buffer) > 0); - r = send(fd, (void*)sldns_buffer_current(c->buffer), - sldns_buffer_remaining(c->buffer), 0); - if(r == -1) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return 1; -#else - if(WSAGetLastError() == WSAEINPROGRESS) - return 1; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); - return 1; - } -#endif - log_err_addr("http send r", sock_strerror(errno), - &c->repinfo.remote_addr, c->repinfo.remote_addrlen); - return 0; - } - sldns_buffer_skip(c->buffer, r); - return 1; -} - -#ifdef HAVE_NGHTTP2 -ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf, - size_t len, int ATTR_UNUSED(flags), void* cb_arg) -{ - ssize_t ret; - struct http2_session* h2_session = (struct http2_session*)cb_arg; - log_assert(h2_session->c->type == comm_http); - log_assert(h2_session->c->h2_session); - -#ifdef HAVE_SSL - if(h2_session->c->ssl) { - int r; - ERR_clear_error(); - r = SSL_write(h2_session->c->ssl, buf, len); - if(r <= 0) { - int want = SSL_get_error(h2_session->c->ssl, r); - if(want == SSL_ERROR_ZERO_RETURN) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } else if(want == SSL_ERROR_WANT_READ) { - h2_session->c->ssl_shake_state = comm_ssl_shake_hs_read; - comm_point_listen_for_rw(h2_session->c, 1, 0); - return NGHTTP2_ERR_WOULDBLOCK; - } else if(want == SSL_ERROR_WANT_WRITE) { - return NGHTTP2_ERR_WOULDBLOCK; - } else if(want == SSL_ERROR_SYSCALL) { -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; -#endif - if(errno != 0) - log_err("SSL_write syscall: %s", - strerror(errno)); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - log_crypto_err("could not SSL_write"); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return r; - } -#endif /* HAVE_SSL */ - - ret = send(h2_session->c->fd, buf, len, 0); - if(ret == 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } else if(ret < 0) { -#ifndef USE_WINSOCK - if(errno == EINTR || errno == EAGAIN) - return NGHTTP2_ERR_WOULDBLOCK; -#ifdef EPIPE - if(errno == EPIPE && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; -#endif -#ifdef ECONNRESET - if(errno == ECONNRESET && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; -#endif - log_err_addr("could not http2 write: %s", strerror(errno), - &h2_session->c->repinfo.remote_addr, - h2_session->c->repinfo.remote_addrlen); -#else /* USE_WINSOCK */ - if(WSAGetLastError() == WSAENOTCONN) - return NGHTTP2_ERR_WOULDBLOCK; - if(WSAGetLastError() == WSAEINPROGRESS) - return NGHTTP2_ERR_WOULDBLOCK; - if(WSAGetLastError() == WSAEWOULDBLOCK) { - ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, - UB_EV_WRITE); - return NGHTTP2_ERR_WOULDBLOCK; - } - if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) - return NGHTTP2_ERR_CALLBACK_FAILURE; - log_err_addr("could not http2 write: %s", - wsa_strerror(WSAGetLastError()), - &h2_session->c->repinfo.remote_addr, - h2_session->c->repinfo.remote_addrlen); -#endif - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return ret; -} -#endif /* HAVE_NGHTTP2 */ - -/** Handle http2 writing */ -static int -comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c) -{ -#ifdef HAVE_NGHTTP2 - int ret; - log_assert(c->h2_session); - - ret = nghttp2_session_send(c->h2_session->session); - if(ret) { - verbose(VERB_QUERY, "http2: session_send failed, " - "error: %s", nghttp2_strerror(ret)); - return 0; - } - - if(nghttp2_session_want_read(c->h2_session->session)) { - c->tcp_is_reading = 1; - comm_point_stop_listening(c); - comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); - } else if(!nghttp2_session_want_write(c->h2_session->session)) - return 0; /* connection can be closed */ - return 1; -#else - (void)c; - return 0; -#endif -} - -/** - * Handle http writing callback. - * @param fd: file descriptor of socket. - * @param c: comm point to write buffer out of. - * @return: 0 on error - */ -static int -comm_point_http_handle_write(int fd, struct comm_point* c) -{ - log_assert(c->type == comm_http); - log_assert(fd != -1); - - /* check pending connect errors, if that fails, we wait for more, - * or we can continue to write contents */ - if(c->tcp_check_nb_connect) { - int r = http_check_connect(fd, c); - if(r == 0) return 0; - if(r == 1) return 1; - c->tcp_check_nb_connect = 0; - } - /* if we are in ssl handshake, handle SSL handshake */ -#ifdef HAVE_SSL - if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { - if(!ssl_handshake(c)) - return 0; - if(c->ssl_shake_state != comm_ssl_shake_none) - return 1; - } -#endif /* HAVE_SSL */ - if(c->tcp_is_reading) - return 1; - - if(c->use_h2) { - return comm_point_http2_handle_write(fd, c); - } - - /* http version is <= http/1.1 */ - - if(c->http_min_version >= http_version_2) { - /* HTTP/2 failed, not allowed to use lower version. */ - return 0; - } - - /* if we are writing, write more */ - if(c->ssl) { - if(!ssl_http_write_more(c)) - return 0; - } else { - if(!http_write_more(fd, c)) - return 0; - } - - /* we write a single buffer contents, that can contain - * the http request, and then flip to read the results */ - /* see if write is done */ - if(sldns_buffer_remaining(c->buffer) == 0) { - sldns_buffer_clear(c->buffer); - if(c->tcp_do_toggle_rw) - c->tcp_is_reading = 1; - c->tcp_byte_count = 0; - /* switch from listening(write) to listening(read) */ - comm_point_stop_listening(c); - comm_point_start_listening(c, -1, -1); - } - return 1; -} - -void -comm_point_http_handle_callback(int fd, short event, void* arg) -{ - struct comm_point* c = (struct comm_point*)arg; - log_assert(c->type == comm_http); - ub_comm_base_now(c->ev->base); - - if(event&UB_EV_TIMEOUT) { - verbose(VERB_QUERY, "http took too long, dropped"); - reclaim_http_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_TIMEOUT, NULL); - } - return; - } - if(event&UB_EV_READ) { - if(!comm_point_http_handle_read(fd, c)) { - reclaim_http_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - } - return; - } - if(event&UB_EV_WRITE) { - if(!comm_point_http_handle_write(fd, c)) { - reclaim_http_handler(c); - if(!c->tcp_do_close) { - fptr_ok(fptr_whitelist_comm_point( - c->callback)); - (void)(*c->callback)(c, c->cb_arg, - NETEVENT_CLOSED, NULL); - } - } - return; - } - log_err("Ignored event %d for httphdl.", event); -} - -void comm_point_local_handle_callback(int fd, short event, void* arg) -{ - struct comm_point* c = (struct comm_point*)arg; - log_assert(c->type == comm_local); - ub_comm_base_now(c->ev->base); - - if(event&UB_EV_READ) { - if(!comm_point_tcp_handle_read(fd, c, 1)) { - fptr_ok(fptr_whitelist_comm_point(c->callback)); - (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, - NULL); - } - return; - } - log_err("Ignored event %d for localhdl.", event); -} - -void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), - short event, void* arg) -{ - struct comm_point* c = (struct comm_point*)arg; - int err = NETEVENT_NOERROR; - log_assert(c->type == comm_raw); - ub_comm_base_now(c->ev->base); - - if(event&UB_EV_TIMEOUT) - err = NETEVENT_TIMEOUT; - fptr_ok(fptr_whitelist_comm_point_raw(c->callback)); - (void)(*c->callback)(c, c->cb_arg, err, NULL); -} - -struct comm_point* -comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, - int pp2_enabled, comm_point_callback_type* callback, - void* callback_arg, struct unbound_socket* socket) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = fd; - c->buffer = buffer; - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_udp; - c->tcp_do_close = 0; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 0; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = buffer; -#endif - c->inuse = 0; - c->callback = callback; - c->cb_arg = callback_arg; - c->socket = socket; - c->pp2_enabled = pp2_enabled; - c->pp2_header_state = pp2_header_none; - evbits = UB_EV_READ | UB_EV_PERSIST; - /* ub_event stuff */ - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, -#ifdef USE_WINSOCK - comm_point_udp_callback, c); -#else - comm_point_udp_ancil_callback, c); -#endif - if(c->ev->ev == NULL) { - log_err("could not baseset udp event"); - comm_point_delete(c); - return NULL; - } - if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { - log_err("could not add udp event"); - comm_point_delete(c); - return NULL; - } - c->event_added = 1; - return c; -} - -struct comm_point* -comm_point_create_udp_ancil(struct comm_base *base, int fd, - sldns_buffer* buffer, int pp2_enabled, - comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = fd; - c->buffer = buffer; - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_udp; - c->tcp_do_close = 0; - c->do_not_close = 0; -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = buffer; -#endif - c->inuse = 0; - c->tcp_do_toggle_rw = 0; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif - c->callback = callback; - c->cb_arg = callback_arg; - c->socket = socket; - c->pp2_enabled = pp2_enabled; - c->pp2_header_state = pp2_header_none; - evbits = UB_EV_READ | UB_EV_PERSIST; - /* ub_event stuff */ - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_udp_ancil_callback, c); - if(c->ev->ev == NULL) { - log_err("could not baseset udp event"); - comm_point_delete(c); - return NULL; - } - if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { - log_err("could not add udp event"); - comm_point_delete(c); - return NULL; - } - c->event_added = 1; - return c; -} - -static struct comm_point* -comm_point_create_tcp_handler(struct comm_base *base, - struct comm_point* parent, size_t bufsize, - struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, - void* callback_arg, struct unbound_socket* socket) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = -1; - c->buffer = sldns_buffer_new(bufsize); - if(!c->buffer) { - free(c->ev); - free(c); - return NULL; - } - c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); - if(!c->timeout) { - sldns_buffer_free(c->buffer); - free(c->ev); - free(c); - return NULL; - } - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = parent; - c->tcp_timeout_msec = parent->tcp_timeout_msec; - c->tcp_conn_limit = parent->tcp_conn_limit; - c->tcl_addr = NULL; - c->tcp_keepalive = 0; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_tcp; - c->tcp_do_close = 0; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 1; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - /* We don't know just yet if this is a dnscrypt channel. Allocation - * will be done when handling the callback. */ - c->dnscrypt_buffer = c->buffer; -#endif - c->repinfo.c = c; - c->callback = callback; - c->cb_arg = callback_arg; - c->socket = socket; - c->pp2_enabled = parent->pp2_enabled; - c->pp2_header_state = pp2_header_none; - if(spoolbuf) { - c->tcp_req_info = tcp_req_info_create(spoolbuf); - if(!c->tcp_req_info) { - log_err("could not create tcp commpoint"); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } - c->tcp_req_info->cp = c; - c->tcp_do_close = 1; - c->tcp_do_toggle_rw = 0; - } - /* add to parent free list */ - c->tcp_free = parent->tcp_free; - parent->tcp_free = c; - /* ub_event stuff */ - evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_tcp_handle_callback, c); - if(c->ev->ev == NULL) - { - log_err("could not basetset tcphdl event"); - parent->tcp_free = c->tcp_free; - tcp_req_info_delete(c->tcp_req_info); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } - return c; -} - -static struct comm_point* -comm_point_create_http_handler(struct comm_base *base, - struct comm_point* parent, size_t bufsize, int harden_large_queries, - uint32_t http_max_streams, char* http_endpoint, - comm_point_callback_type* callback, void* callback_arg, - struct unbound_socket* socket) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = -1; - c->buffer = sldns_buffer_new(bufsize); - if(!c->buffer) { - free(c->ev); - free(c); - return NULL; - } - c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); - if(!c->timeout) { - sldns_buffer_free(c->buffer); - free(c->ev); - free(c); - return NULL; - } - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = parent; - c->tcp_timeout_msec = parent->tcp_timeout_msec; - c->tcp_conn_limit = parent->tcp_conn_limit; - c->tcl_addr = NULL; - c->tcp_keepalive = 0; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_http; - c->tcp_do_close = 1; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 1; /* will be set to 0 after http2 upgrade */ - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = NULL; -#endif - c->repinfo.c = c; - c->callback = callback; - c->cb_arg = callback_arg; - c->socket = socket; - c->pp2_enabled = 0; - c->pp2_header_state = pp2_header_none; - - c->http_min_version = http_version_2; - c->http2_stream_max_qbuffer_size = bufsize; - if(harden_large_queries && bufsize > 512) - c->http2_stream_max_qbuffer_size = 512; - c->http2_max_streams = http_max_streams; - if(!(c->http_endpoint = strdup(http_endpoint))) { - log_err("could not strdup http_endpoint"); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } - c->use_h2 = 0; -#ifdef HAVE_NGHTTP2 - if(!(c->h2_session = http2_session_create(c))) { - log_err("could not create http2 session"); - free(c->http_endpoint); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } - if(!(c->h2_session->callbacks = http2_req_callbacks_create())) { - log_err("could not create http2 callbacks"); - http2_session_delete(c->h2_session); - free(c->http_endpoint); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } -#endif - - /* add to parent free list */ - c->tcp_free = parent->tcp_free; - parent->tcp_free = c; - /* ub_event stuff */ - evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_http_handle_callback, c); - if(c->ev->ev == NULL) - { - log_err("could not set http handler event"); - parent->tcp_free = c->tcp_free; - http2_session_delete(c->h2_session); - sldns_buffer_free(c->buffer); - free(c->timeout); - free(c->ev); - free(c); - return NULL; - } - return c; -} - -struct comm_point* -comm_point_create_tcp(struct comm_base *base, int fd, int num, - int idle_timeout, int harden_large_queries, - uint32_t http_max_streams, char* http_endpoint, - struct tcl_list* tcp_conn_limit, size_t bufsize, - struct sldns_buffer* spoolbuf, enum listen_type port_type, - int pp2_enabled, comm_point_callback_type* callback, - void* callback_arg, struct unbound_socket* socket) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - int i; - /* first allocate the TCP accept listener */ - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = fd; - c->buffer = NULL; - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_timeout_msec = idle_timeout; - c->tcp_conn_limit = tcp_conn_limit; - c->tcl_addr = NULL; - c->tcp_keepalive = 0; - c->tcp_parent = NULL; - c->max_tcp_count = num; - c->cur_tcp_count = 0; - c->tcp_handlers = (struct comm_point**)calloc((size_t)num, - sizeof(struct comm_point*)); - if(!c->tcp_handlers) { - free(c->ev); - free(c); - return NULL; - } - c->tcp_free = NULL; - c->type = comm_tcp_accept; - c->tcp_do_close = 0; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 0; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = NULL; -#endif - c->callback = NULL; - c->cb_arg = NULL; - c->socket = socket; - c->pp2_enabled = (port_type==listen_type_http?0:pp2_enabled); - c->pp2_header_state = pp2_header_none; - evbits = UB_EV_READ | UB_EV_PERSIST; - /* ub_event stuff */ - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_tcp_accept_callback, c); - if(c->ev->ev == NULL) { - log_err("could not baseset tcpacc event"); - comm_point_delete(c); - return NULL; - } - if (ub_event_add(c->ev->ev, c->timeout) != 0) { - log_err("could not add tcpacc event"); - comm_point_delete(c); - return NULL; - } - c->event_added = 1; - /* now prealloc the handlers */ - for(i=0; itcp_handlers[i] = comm_point_create_tcp_handler(base, - c, bufsize, spoolbuf, callback, callback_arg, socket); - } else if(port_type == listen_type_http) { - c->tcp_handlers[i] = comm_point_create_http_handler( - base, c, bufsize, harden_large_queries, - http_max_streams, http_endpoint, - callback, callback_arg, socket); - } - else { - log_err("could not create tcp handler, unknown listen " - "type"); - return NULL; - } - if(!c->tcp_handlers[i]) { - comm_point_delete(c); - return NULL; - } - } - - return c; -} - -struct comm_point* -comm_point_create_tcp_out(struct comm_base *base, size_t bufsize, - comm_point_callback_type* callback, void* callback_arg) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = -1; - c->buffer = sldns_buffer_new(bufsize); - if(!c->buffer) { - free(c->ev); - free(c); - return NULL; - } - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_timeout_msec = TCP_QUERY_TIMEOUT; - c->tcp_conn_limit = NULL; - c->tcl_addr = NULL; - c->tcp_keepalive = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_tcp; - c->tcp_do_close = 0; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 1; - c->tcp_check_nb_connect = 1; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 1; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = c->buffer; -#endif - c->repinfo.c = c; - c->callback = callback; - c->cb_arg = callback_arg; - c->pp2_enabled = 0; - c->pp2_header_state = pp2_header_none; - evbits = UB_EV_PERSIST | UB_EV_WRITE; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_tcp_handle_callback, c); - if(c->ev->ev == NULL) - { - log_err("could not baseset tcpout event"); - sldns_buffer_free(c->buffer); - free(c->ev); - free(c); - return NULL; - } - - return c; -} - -struct comm_point* -comm_point_create_http_out(struct comm_base *base, size_t bufsize, - comm_point_callback_type* callback, void* callback_arg, - sldns_buffer* temp) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = -1; - c->buffer = sldns_buffer_new(bufsize); - if(!c->buffer) { - free(c->ev); - free(c); - return NULL; - } - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_http; - c->tcp_do_close = 0; - c->do_not_close = 0; - c->tcp_do_toggle_rw = 1; - c->tcp_check_nb_connect = 1; - c->http_in_headers = 1; - c->http_in_chunk_headers = 0; - c->http_is_chunked = 0; - c->http_temp = temp; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 1; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = c->buffer; -#endif - c->repinfo.c = c; - c->callback = callback; - c->cb_arg = callback_arg; - c->pp2_enabled = 0; - c->pp2_header_state = pp2_header_none; - evbits = UB_EV_PERSIST | UB_EV_WRITE; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_http_handle_callback, c); - if(c->ev->ev == NULL) - { - log_err("could not baseset tcpout event"); -#ifdef HAVE_SSL - SSL_free(c->ssl); -#endif - sldns_buffer_free(c->buffer); - free(c->ev); - free(c); - return NULL; - } - - return c; -} - -struct comm_point* -comm_point_create_local(struct comm_base *base, int fd, size_t bufsize, - comm_point_callback_type* callback, void* callback_arg) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = fd; - c->buffer = sldns_buffer_new(bufsize); - if(!c->buffer) { - free(c->ev); - free(c); - return NULL; - } - c->timeout = NULL; - c->tcp_is_reading = 1; - c->tcp_byte_count = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_local; - c->tcp_do_close = 0; - c->do_not_close = 1; - c->tcp_do_toggle_rw = 0; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = c->buffer; -#endif - c->callback = callback; - c->cb_arg = callback_arg; - c->pp2_enabled = 0; - c->pp2_header_state = pp2_header_none; - /* ub_event stuff */ - evbits = UB_EV_PERSIST | UB_EV_READ; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_local_handle_callback, c); - if(c->ev->ev == NULL) { - log_err("could not baseset localhdl event"); - free(c->ev); - free(c); - return NULL; - } - if (ub_event_add(c->ev->ev, c->timeout) != 0) { - log_err("could not add localhdl event"); - ub_event_free(c->ev->ev); - free(c->ev); - free(c); - return NULL; - } - c->event_added = 1; - return c; -} - -struct comm_point* -comm_point_create_raw(struct comm_base* base, int fd, int writing, - comm_point_callback_type* callback, void* callback_arg) -{ - struct comm_point* c = (struct comm_point*)calloc(1, - sizeof(struct comm_point)); - short evbits; - if(!c) - return NULL; - c->ev = (struct internal_event*)calloc(1, - sizeof(struct internal_event)); - if(!c->ev) { - free(c); - return NULL; - } - c->ev->base = base; - c->fd = fd; - c->buffer = NULL; - c->timeout = NULL; - c->tcp_is_reading = 0; - c->tcp_byte_count = 0; - c->tcp_parent = NULL; - c->max_tcp_count = 0; - c->cur_tcp_count = 0; - c->tcp_handlers = NULL; - c->tcp_free = NULL; - c->type = comm_raw; - c->tcp_do_close = 0; - c->do_not_close = 1; - c->tcp_do_toggle_rw = 0; - c->tcp_check_nb_connect = 0; -#ifdef USE_MSG_FASTOPEN - c->tcp_do_fastopen = 0; -#endif -#ifdef USE_DNSCRYPT - c->dnscrypt = 0; - c->dnscrypt_buffer = c->buffer; -#endif - c->callback = callback; - c->cb_arg = callback_arg; - c->pp2_enabled = 0; - c->pp2_header_state = pp2_header_none; - /* ub_event stuff */ - if(writing) - evbits = UB_EV_PERSIST | UB_EV_WRITE; - else evbits = UB_EV_PERSIST | UB_EV_READ; - c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, - comm_point_raw_handle_callback, c); - if(c->ev->ev == NULL) { - log_err("could not baseset rawhdl event"); - free(c->ev); - free(c); - return NULL; - } - if (ub_event_add(c->ev->ev, c->timeout) != 0) { - log_err("could not add rawhdl event"); - ub_event_free(c->ev->ev); - free(c->ev); - free(c); - return NULL; - } - c->event_added = 1; - return c; -} - -void -comm_point_close(struct comm_point* c) -{ - if(!c) - return; - if(c->fd != -1) { - verbose(5, "comm_point_close of %d: event_del", c->fd); - if(c->event_added) { - if(ub_event_del(c->ev->ev) != 0) { - log_err("could not event_del on close"); - } - c->event_added = 0; - } - } - tcl_close_connection(c->tcl_addr); - if(c->tcp_req_info) - tcp_req_info_clear(c->tcp_req_info); - if(c->h2_session) - http2_session_server_delete(c->h2_session); - /* stop the comm point from reading or writing after it is closed. */ - if(c->tcp_more_read_again && *c->tcp_more_read_again) - *c->tcp_more_read_again = 0; - if(c->tcp_more_write_again && *c->tcp_more_write_again) - *c->tcp_more_write_again = 0; - - /* close fd after removing from event lists, or epoll.. is messed up */ - if(c->fd != -1 && !c->do_not_close) { -#ifdef USE_WINSOCK - if(c->type == comm_tcp || c->type == comm_http) { - /* delete sticky events for the fd, it gets closed */ - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); - ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); - } -#endif - verbose(VERB_ALGO, "close fd %d", c->fd); - sock_close(c->fd); - } - c->fd = -1; -} - -void -comm_point_delete(struct comm_point* c) -{ - if(!c) - return; - if((c->type == comm_tcp || c->type == comm_http) && c->ssl) { -#ifdef HAVE_SSL - SSL_shutdown(c->ssl); - SSL_free(c->ssl); -#endif - } - if(c->type == comm_http && c->http_endpoint) { - free(c->http_endpoint); - c->http_endpoint = NULL; - } - comm_point_close(c); - if(c->tcp_handlers) { - int i; - for(i=0; imax_tcp_count; i++) - comm_point_delete(c->tcp_handlers[i]); - free(c->tcp_handlers); - } - free(c->timeout); - if(c->type == comm_tcp || c->type == comm_local || c->type == comm_http) { - sldns_buffer_free(c->buffer); -#ifdef USE_DNSCRYPT - if(c->dnscrypt && c->dnscrypt_buffer != c->buffer) { - sldns_buffer_free(c->dnscrypt_buffer); - } -#endif - if(c->tcp_req_info) { - tcp_req_info_delete(c->tcp_req_info); - } - if(c->h2_session) { - http2_session_delete(c->h2_session); - } - } - ub_event_free(c->ev->ev); - free(c->ev); - free(c); -} - -void -comm_point_send_reply(struct comm_reply *repinfo) -{ - struct sldns_buffer* buffer; - log_assert(repinfo && repinfo->c); -#ifdef USE_DNSCRYPT - buffer = repinfo->c->dnscrypt_buffer; - if(!dnsc_handle_uncurved_request(repinfo)) { - return; - } -#else - buffer = repinfo->c->buffer; -#endif - if(repinfo->c->type == comm_udp) { - if(repinfo->srctype) - comm_point_send_udp_msg_if(repinfo->c, buffer, - (struct sockaddr*)&repinfo->remote_addr, - repinfo->remote_addrlen, repinfo); - else - comm_point_send_udp_msg(repinfo->c, buffer, - (struct sockaddr*)&repinfo->remote_addr, - repinfo->remote_addrlen, 0); -#ifdef USE_DNSTAP - /* - * sending src (client)/dst (local service) addresses over DNSTAP from udp callback - */ - if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) { - log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); - log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); - dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->buffer); - } -#endif - } else { -#ifdef USE_DNSTAP - /* - * sending src (client)/dst (local service) addresses over DNSTAP from TCP callback - */ - if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) { - log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); - log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); - dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, - ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); - } -#endif - if(repinfo->c->tcp_req_info) { - tcp_req_info_send_reply(repinfo->c->tcp_req_info); - } else if(repinfo->c->use_h2) { - if(!http2_submit_dns_response(repinfo->c->h2_session)) { - comm_point_drop_reply(repinfo); - return; - } - repinfo->c->h2_stream = NULL; - repinfo->c->tcp_is_reading = 0; - comm_point_stop_listening(repinfo->c); - comm_point_start_listening(repinfo->c, -1, - adjusted_tcp_timeout(repinfo->c)); - return; - } else { - comm_point_start_listening(repinfo->c, -1, - adjusted_tcp_timeout(repinfo->c)); - } - } -} - -void -comm_point_drop_reply(struct comm_reply* repinfo) -{ - if(!repinfo) - return; - log_assert(repinfo->c); - log_assert(repinfo->c->type != comm_tcp_accept); - if(repinfo->c->type == comm_udp) - return; - if(repinfo->c->tcp_req_info) - repinfo->c->tcp_req_info->is_drop = 1; - if(repinfo->c->type == comm_http) { - if(repinfo->c->h2_session) { - repinfo->c->h2_session->is_drop = 1; - if(!repinfo->c->h2_session->postpone_drop) - reclaim_http_handler(repinfo->c); - return; - } - reclaim_http_handler(repinfo->c); - return; - } - reclaim_tcp_handler(repinfo->c); -} - -void -comm_point_stop_listening(struct comm_point* c) -{ - verbose(VERB_ALGO, "comm point stop listening %d", c->fd); - if(c->event_added) { - if(ub_event_del(c->ev->ev) != 0) { - log_err("event_del error to stoplisten"); - } - c->event_added = 0; - } -} - -void -comm_point_start_listening(struct comm_point* c, int newfd, int msec) -{ - verbose(VERB_ALGO, "comm point start listening %d (%d msec)", - c->fd==-1?newfd:c->fd, msec); - if(c->type == comm_tcp_accept && !c->tcp_free) { - /* no use to start listening no free slots. */ - return; - } - if(c->event_added) { - if(ub_event_del(c->ev->ev) != 0) { - log_err("event_del error to startlisten"); - } - c->event_added = 0; - } - if(msec != -1 && msec != 0) { - if(!c->timeout) { - c->timeout = (struct timeval*)malloc(sizeof( - struct timeval)); - if(!c->timeout) { - log_err("cpsl: malloc failed. No net read."); - return; - } - } - ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT); -#ifndef S_SPLINT_S /* splint fails on struct timeval. */ - c->timeout->tv_sec = msec/1000; - c->timeout->tv_usec = (msec%1000)*1000; -#endif /* S_SPLINT_S */ - } else { - if(msec == 0 || !c->timeout) { - ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); - } - } - if(c->type == comm_tcp || c->type == comm_http) { - ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); - if(c->tcp_write_and_read) { - verbose(5, "startlistening %d mode rw", (newfd==-1?c->fd:newfd)); - ub_event_add_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); - } else if(c->tcp_is_reading) { - verbose(5, "startlistening %d mode r", (newfd==-1?c->fd:newfd)); - ub_event_add_bits(c->ev->ev, UB_EV_READ); - } else { - verbose(5, "startlistening %d mode w", (newfd==-1?c->fd:newfd)); - ub_event_add_bits(c->ev->ev, UB_EV_WRITE); - } - } - if(newfd != -1) { - if(c->fd != -1 && c->fd != newfd) { - verbose(5, "cpsl close of fd %d for %d", c->fd, newfd); - sock_close(c->fd); - } - c->fd = newfd; - ub_event_set_fd(c->ev->ev, c->fd); - } - if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) { - log_err("event_add failed. in cpsl."); - return; - } - c->event_added = 1; -} - -void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr) -{ - verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr); - if(c->event_added) { - if(ub_event_del(c->ev->ev) != 0) { - log_err("event_del error to cplf"); - } - c->event_added = 0; - } - if(!c->timeout) { - ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); - } - ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); - if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ); - if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE); - if(ub_event_add(c->ev->ev, c->timeout) != 0) { - log_err("event_add failed. in cplf."); - return; - } - c->event_added = 1; -} - -size_t comm_point_get_mem(struct comm_point* c) -{ - size_t s; - if(!c) - return 0; - s = sizeof(*c) + sizeof(*c->ev); - if(c->timeout) - s += sizeof(*c->timeout); - if(c->type == comm_tcp || c->type == comm_local) { - s += sizeof(*c->buffer) + sldns_buffer_capacity(c->buffer); -#ifdef USE_DNSCRYPT - s += sizeof(*c->dnscrypt_buffer); - if(c->buffer != c->dnscrypt_buffer) { - s += sldns_buffer_capacity(c->dnscrypt_buffer); - } -#endif - } - if(c->type == comm_tcp_accept) { - int i; - for(i=0; imax_tcp_count; i++) - s += comm_point_get_mem(c->tcp_handlers[i]); - } - return s; -} - -struct comm_timer* -comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg) -{ - struct internal_timer *tm = (struct internal_timer*)calloc(1, - sizeof(struct internal_timer)); - if(!tm) { - log_err("malloc failed"); - return NULL; - } - tm->super.ev_timer = tm; - tm->base = base; - tm->super.callback = cb; - tm->super.cb_arg = cb_arg; - tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT, - comm_timer_callback, &tm->super); - if(tm->ev == NULL) { - log_err("timer_create: event_base_set failed."); - free(tm); - return NULL; - } - return &tm->super; -} - -void -comm_timer_disable(struct comm_timer* timer) -{ - if(!timer) - return; - ub_timer_del(timer->ev_timer->ev); - timer->ev_timer->enabled = 0; -} - -void -comm_timer_set(struct comm_timer* timer, struct timeval* tv) -{ - log_assert(tv); - if(timer->ev_timer->enabled) - comm_timer_disable(timer); - if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base, - comm_timer_callback, timer, tv) != 0) - log_err("comm_timer_set: evtimer_add failed."); - timer->ev_timer->enabled = 1; -} - -void -comm_timer_delete(struct comm_timer* timer) -{ - if(!timer) - return; - comm_timer_disable(timer); - /* Free the sub struct timer->ev_timer derived from the super struct timer. - * i.e. assert(timer == timer->ev_timer) - */ - ub_event_free(timer->ev_timer->ev); - free(timer->ev_timer); -} - -void -comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg) -{ - struct comm_timer* tm = (struct comm_timer*)arg; - if(!(event&UB_EV_TIMEOUT)) - return; - ub_comm_base_now(tm->ev_timer->base); - tm->ev_timer->enabled = 0; - fptr_ok(fptr_whitelist_comm_timer(tm->callback)); - (*tm->callback)(tm->cb_arg); -} - -int -comm_timer_is_set(struct comm_timer* timer) -{ - return (int)timer->ev_timer->enabled; -} - -size_t -comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer)) -{ - return sizeof(struct internal_timer); -} - -struct comm_signal* -comm_signal_create(struct comm_base* base, - void (*callback)(int, void*), void* cb_arg) -{ - struct comm_signal* com = (struct comm_signal*)malloc( - sizeof(struct comm_signal)); - if(!com) { - log_err("malloc failed"); - return NULL; - } - com->base = base; - com->callback = callback; - com->cb_arg = cb_arg; - com->ev_signal = NULL; - return com; -} - -void -comm_signal_callback(int sig, short event, void* arg) -{ - struct comm_signal* comsig = (struct comm_signal*)arg; - if(!(event & UB_EV_SIGNAL)) - return; - ub_comm_base_now(comsig->base); - fptr_ok(fptr_whitelist_comm_signal(comsig->callback)); - (*comsig->callback)(sig, comsig->cb_arg); -} - -int -comm_signal_bind(struct comm_signal* comsig, int sig) -{ - struct internal_signal* entry = (struct internal_signal*)calloc(1, - sizeof(struct internal_signal)); - if(!entry) { - log_err("malloc failed"); - return 0; - } - log_assert(comsig); - /* add signal event */ - entry->ev = ub_signal_new(comsig->base->eb->base, sig, - comm_signal_callback, comsig); - if(entry->ev == NULL) { - log_err("Could not create signal event"); - free(entry); - return 0; - } - if(ub_signal_add(entry->ev, NULL) != 0) { - log_err("Could not add signal handler"); - ub_event_free(entry->ev); - free(entry); - return 0; - } - /* link into list */ - entry->next = comsig->ev_signal; - comsig->ev_signal = entry; - return 1; -} - -void -comm_signal_delete(struct comm_signal* comsig) -{ - struct internal_signal* p, *np; - if(!comsig) - return; - p=comsig->ev_signal; - while(p) { - np = p->next; - ub_signal_del(p->ev); - ub_event_free(p->ev); - free(p); - p = np; - } - free(comsig); -} diff --git a/crates/libunbound-sys/unbound/util/netevent.h b/crates/libunbound-sys/unbound/util/netevent.h deleted file mode 100644 index dc9619c1..00000000 --- a/crates/libunbound-sys/unbound/util/netevent.h +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * util/netevent.h - event notification - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains event notification functions. - * - * There are three types of communication points - * o UDP socket - perthread buffer. - * o TCP-accept socket - array of TCP-sockets, socketcount. - * o TCP socket - own buffer, parent-TCPaccept, read/write state, - * number of bytes read/written, timeout. - * - * There are sockets aimed towards our clients and towards the internet. - * o frontside - aimed towards our clients, queries come in, answers back. - * o behind - aimed towards internet, to the authoritative DNS servers. - * - * Several event types are available: - * o comm_base - for thread safety of the comm points, one per thread. - * o comm_point - udp and tcp networking, with callbacks. - * o comm_timer - a timeout with callback. - * o comm_signal - callbacks when signal is caught. - * o comm_reply - holds reply info during networking callback. - * - */ - -#ifndef NET_EVENT_H -#define NET_EVENT_H - -#include -#include "dnscrypt/dnscrypt.h" -#ifdef HAVE_NGHTTP2_NGHTTP2_H -#include -#endif - -struct sldns_buffer; -struct comm_point; -struct comm_reply; -struct tcl_list; -struct ub_event_base; -struct unbound_socket; - -struct mesh_state; -struct mesh_area; - -/* internal event notification data storage structure. */ -struct internal_event; -struct internal_base; -struct internal_timer; /* A sub struct of the comm_timer super struct */ - -enum listen_type; - -/** callback from communication point function type */ -typedef int comm_point_callback_type(struct comm_point*, void*, int, - struct comm_reply*); - -/** to pass no_error to callback function */ -#define NETEVENT_NOERROR 0 -/** to pass closed connection to callback function */ -#define NETEVENT_CLOSED -1 -/** to pass timeout happened to callback function */ -#define NETEVENT_TIMEOUT -2 -/** to pass fallback from capsforID to callback function; 0x20 failed */ -#define NETEVENT_CAPSFAIL -3 -/** to pass done transfer to callback function; http file is complete */ -#define NETEVENT_DONE -4 -/** to pass write of the write packet is done to callback function - * used when tcp_write_and_read is enabled */ -#define NETEVENT_PKT_WRITTEN -5 - -/** timeout to slow accept calls when not possible, in msec. */ -#define NETEVENT_SLOW_ACCEPT_TIME 2000 -/** timeout to slow down log print, so it does not spam the logs, in sec */ -#define SLOW_LOG_TIME 10 - -/** - * A communication point dispatcher. Thread specific. - */ -struct comm_base { - /** behind the scenes structure. with say libevent info. alloced */ - struct internal_base* eb; - /** callback to stop listening on accept sockets, - * performed when accept() will not function properly */ - void (*stop_accept)(void*); - /** callback to start listening on accept sockets, performed - * after stop_accept() then a timeout has passed. */ - void (*start_accept)(void*); - /** user argument for stop_accept and start_accept functions */ - void* cb_arg; -}; - -/** - * Reply information for a communication point. - */ -struct comm_reply { - /** the comm_point with fd to send reply on to. */ - struct comm_point* c; - /** the address (for UDP based communication) */ - struct sockaddr_storage remote_addr; - /** length of address */ - socklen_t remote_addrlen; - /** return type 0 (none), 4(IP4), 6(IP6) - * used only with listen_type_udp_ancil* */ - int srctype; - /* DnsCrypt context */ -#ifdef USE_DNSCRYPT - uint8_t client_nonce[crypto_box_HALF_NONCEBYTES]; - uint8_t nmkey[crypto_box_BEFORENMBYTES]; - const dnsccert *dnsc_cert; - int is_dnscrypted; -#endif - /** the return source interface data */ - union { -#ifdef IPV6_PKTINFO - struct in6_pktinfo v6info; -#endif -#ifdef IP_PKTINFO - struct in_pktinfo v4info; -#elif defined(IP_RECVDSTADDR) - struct in_addr v4addr; -#endif - } - /** variable with return source data */ - pktinfo; - /** max udp size for udp packets */ - size_t max_udp_size; - /* if set, the request came through a proxy */ - int is_proxied; - /** the client address - * the same as remote_addr if not proxied */ - struct sockaddr_storage client_addr; - /** the original address length */ - socklen_t client_addrlen; -}; - -/** - * Communication point to the network - * These behaviours can be accomplished by setting the flags - * and passing return values from the callback. - * udp frontside: called after readdone. sendafter. - * tcp frontside: called readdone, sendafter. close. - * udp behind: called after readdone. No send after. - * tcp behind: write done, read done, then called. No send after. - */ -struct comm_point { - /** behind the scenes structure, with say libevent info. alloced. */ - struct internal_event* ev; - /** if the event is added or not */ - int event_added; - - struct unbound_socket* socket; - - /** file descriptor for communication point */ - int fd; - - /** timeout (NULL if it does not). Malloced. */ - struct timeval* timeout; - - /** buffer pointer. Either to perthread, or own buffer or NULL */ - struct sldns_buffer* buffer; - - /* -------- TCP Handler -------- */ - /** Read/Write state for TCP */ - int tcp_is_reading; - /** The current read/write count for TCP */ - size_t tcp_byte_count; - /** parent communication point (for TCP sockets) */ - struct comm_point* tcp_parent; - /** sockaddr from peer, for TCP handlers */ - struct comm_reply repinfo; - - /* -------- TCP Accept -------- */ - /** the number of TCP handlers for this tcp-accept socket */ - int max_tcp_count; - /** current number of tcp handler in-use for this accept socket */ - int cur_tcp_count; - /** malloced array of tcp handlers for a tcp-accept, - of size max_tcp_count. */ - struct comm_point** tcp_handlers; - /** linked list of free tcp_handlers to use for new queries. - For tcp_accept the first entry, for tcp_handlers the next one. */ - struct comm_point* tcp_free; - - /* -------- SSL TCP DNS ------- */ - /** the SSL object with rw bio (owned) or for commaccept ctx ref */ - void* ssl; - /** handshake state for init and renegotiate */ - enum { - /** no handshake, it has been done */ - comm_ssl_shake_none = 0, - /** ssl initial handshake wants to read */ - comm_ssl_shake_read, - /** ssl initial handshake wants to write */ - comm_ssl_shake_write, - /** ssl_write wants to read */ - comm_ssl_shake_hs_read, - /** ssl_read wants to write */ - comm_ssl_shake_hs_write - } ssl_shake_state; - - /* -------- HTTP ------- */ - /** Do not allow connection to use HTTP version lower than this. 0=no - * minimum. */ - enum { - http_version_none = 0, - http_version_2 = 2 - } http_min_version; - /** http endpoint */ - char* http_endpoint; - /* -------- HTTP/1.1 ------- */ - /** Currently reading in http headers */ - int http_in_headers; - /** Currently reading in chunk headers, 0=not, 1=firstline, 2=unused - * (more lines), 3=trailer headers after chunk */ - int http_in_chunk_headers; - /** chunked transfer */ - int http_is_chunked; - /** http temp buffer (shared buffer for temporary work) */ - struct sldns_buffer* http_temp; - /** http stored content in buffer */ - size_t http_stored; - /* -------- HTTP/2 ------- */ - /** http2 session */ - struct http2_session* h2_session; - /** set to 1 if h2 is negotiated to be used (using alpn) */ - int use_h2; - /** stream currently being handled */ - struct http2_stream* h2_stream; - /** maximum allowed query buffer size, per stream */ - size_t http2_stream_max_qbuffer_size; - /** maximum number of HTTP/2 streams per connection. Send in HTTP/2 - * SETTINGS frame. */ - uint32_t http2_max_streams; - - /* -------- dnstap ------- */ - /** the dnstap environment */ - struct dt_env* dtenv; - - /** is this a UDP, TCP-accept or TCP socket. */ - enum comm_point_type { - /** UDP socket - handle datagrams. */ - comm_udp, - /** TCP accept socket - only creates handlers if readable. */ - comm_tcp_accept, - /** TCP handler socket - handle byteperbyte readwrite. */ - comm_tcp, - /** HTTP handler socket */ - comm_http, - /** AF_UNIX socket - for internal commands. */ - comm_local, - /** raw - not DNS format - for pipe readers and writers */ - comm_raw - } - /** variable with type of socket, UDP,TCP-accept,TCP,pipe */ - type; - - /* -------- PROXYv2 ------- */ - /** if set, PROXYv2 is expected on this connection */ - int pp2_enabled; - /** header state for the PROXYv2 header (for TCP) */ - enum { - /** no header encounter yet */ - pp2_header_none = 0, - /** read the static part of the header */ - pp2_header_init, - /** read the full header */ - pp2_header_done - } pp2_header_state; - - /* ---------- Behaviour ----------- */ - /** if set the connection is NOT closed on delete. */ - int do_not_close; - - /** if set, the connection is closed on error, on timeout, - and after read/write completes. No callback is done. */ - int tcp_do_close; - - /** flag that indicates the stream is both written and read from. */ - int tcp_write_and_read; - - /** byte count for written length over write channel, for when - * tcp_write_and_read is enabled. When tcp_write_and_read is enabled, - * this is the counter for writing, the one for reading is in the - * commpoint.buffer sldns buffer. The counter counts from 0 to - * 2+tcp_write_pkt_len, and includes the tcp length bytes. */ - size_t tcp_write_byte_count; - - /** packet to write currently over the write channel. for when - * tcp_write_and_read is enabled. When tcp_write_and_read is enabled, - * this is the buffer for the written packet, the commpoint.buffer - * sldns buffer is the buffer for the received packet. */ - uint8_t* tcp_write_pkt; - /** length of tcp_write_pkt in bytes */ - size_t tcp_write_pkt_len; - - /** if set try to read another packet again (over connection with - * multiple packets), once set, tries once, then zero again, - * so set it in the packet complete section. - * The pointer itself has to be set before the callback is invoked, - * when you set things up, and continue to exist also after the - * commpoint is closed and deleted in your callback. So that after - * the callback cleans up netevent can see what it has to do. - * Or leave NULL if it is not used at all. */ - int* tcp_more_read_again; - - /** if set try to write another packet (over connection with - * multiple packets), once set, tries once, then zero again, - * so set it in the packet complete section. - * The pointer itself has to be set before the callback is invoked, - * when you set things up, and continue to exist also after the - * commpoint is closed and deleted in your callback. So that after - * the callback cleans up netevent can see what it has to do. - * Or leave NULL if it is not used at all. */ - int* tcp_more_write_again; - - /** if set, read/write completes: - read/write state of tcp is toggled. - buffer reset/bytecount reset. - this flag cleared. - So that when that is done the callback is called. */ - int tcp_do_toggle_rw; - - /** timeout in msec for TCP wait times for this connection */ - int tcp_timeout_msec; - - /** if set, tcp keepalive is enabled on this connection */ - int tcp_keepalive; - - /** if set, checks for pending error from nonblocking connect() call.*/ - int tcp_check_nb_connect; - - /** if set, check for connection limit on tcp accept. */ - struct tcl_list* tcp_conn_limit; - /** the entry for the connection. */ - struct tcl_addr* tcl_addr; - - /** the structure to keep track of open requests on this channel */ - struct tcp_req_info* tcp_req_info; - -#ifdef USE_MSG_FASTOPEN - /** used to track if the sendto() call should be done when using TFO. */ - int tcp_do_fastopen; -#endif - -#ifdef USE_DNSCRYPT - /** Is this a dnscrypt channel */ - int dnscrypt; - /** encrypted buffer pointer. Either to perthread, or own buffer or NULL */ - struct sldns_buffer* dnscrypt_buffer; -#endif - /** number of queries outstanding on this socket, used by - * outside network for udp ports */ - int inuse; - /** the timestamp when the packet was received by the kernel */ - struct timeval recv_tv; - /** callback when done. - tcp_accept does not get called back, is NULL then. - If a timeout happens, callback with timeout=1 is called. - If an error happens, callback is called with error set - nonzero. If not NETEVENT_NOERROR, it is an errno value. - If the connection is closed (by remote end) then the - callback is called with error set to NETEVENT_CLOSED=-1. - If a timeout happens on the connection, the error is set to - NETEVENT_TIMEOUT=-2. - The reply_info can be copied if the reply needs to happen at a - later time. It consists of a struct with commpoint and address. - It can be passed to a msg send routine some time later. - Note the reply information is temporary and must be copied. - NULL is passed for_reply info, in cases where error happened. - - declare as: - int my_callback(struct comm_point* c, void* my_arg, int error, - struct comm_reply *reply_info); - - if the routine returns 0, nothing is done. - Notzero, the buffer will be sent back to client. - For UDP this is done without changing the commpoint. - In TCP it sets write state. - */ - comm_point_callback_type* callback; - /** argument to pass to callback. */ - void *cb_arg; -}; - -/** - * Structure only for making timeout events. - */ -struct comm_timer { - /** the internal event stuff (derived) */ - struct internal_timer* ev_timer; - - /** callback function, takes user arg only */ - void (*callback)(void*); - - /** callback user argument */ - void* cb_arg; -}; - -/** - * Structure only for signal events. - */ -struct comm_signal { - /** the communication base */ - struct comm_base* base; - - /** the internal event stuff */ - struct internal_signal* ev_signal; - - /** callback function, takes signal number and user arg */ - void (*callback)(int, void*); - - /** callback user argument */ - void* cb_arg; -}; - -/** - * Create a new comm base. - * @param sigs: if true it attempts to create a default loop for - * signal handling. - * @return: the new comm base. NULL on error. - */ -struct comm_base* comm_base_create(int sigs); - -/** - * Create comm base that uses the given ub_event_base (underlying pluggable - * event mechanism pointer). - * @param base: underlying pluggable event base. - * @return: the new comm base. NULL on error. - */ -struct comm_base* comm_base_create_event(struct ub_event_base* base); - -/** - * Delete comm base structure but not the underlying lib event base. - * All comm points must have been deleted. - * @param b: the base to delete. - */ -void comm_base_delete_no_base(struct comm_base* b); - -/** - * Destroy a comm base. - * All comm points must have been deleted. - * @param b: the base to delete. - */ -void comm_base_delete(struct comm_base* b); - -/** - * Obtain two pointers. The pointers never change (until base_delete()). - * The pointers point to time values that are updated regularly. - * @param b: the communication base that will update the time values. - * @param tt: pointer to time in seconds is returned. - * @param tv: pointer to time in microseconds is returned. - */ -void comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv); - -/** - * Dispatch the comm base events. - * @param b: the communication to perform. - */ -void comm_base_dispatch(struct comm_base* b); - -/** - * Exit from dispatch loop. - * @param b: the communication base that is in dispatch(). - */ -void comm_base_exit(struct comm_base* b); - -/** - * Set the slow_accept mode handlers. You can not provide these if you do - * not perform accept() calls. - * @param b: comm base - * @param stop_accept: function that stops listening to accept fds. - * @param start_accept: function that resumes listening to accept fds. - * @param arg: callback arg to pass to the functions. - */ -void comm_base_set_slow_accept_handlers(struct comm_base* b, - void (*stop_accept)(void*), void (*start_accept)(void*), void* arg); - -/** - * Access internal data structure (for util/tube.c on windows) - * @param b: comm base - * @return ub_event_base. - */ -struct ub_event_base* comm_base_internal(struct comm_base* b); - -/** - * Create an UDP comm point. Calls malloc. - * setups the structure with the parameters you provide. - * @param base: in which base to alloc the commpoint. - * @param fd: file descriptor of open UDP socket. - * @param buffer: shared buffer by UDP sockets from this thread. - * @param pp2_enabled: if the comm point will support PROXYv2. - * @param callback: callback function pointer. - * @param callback_arg: will be passed to your callback function. - * @param socket: and opened socket properties will be passed to your callback function. - * @return: returns the allocated communication point. NULL on error. - * Sets timeout to NULL. Turns off TCP options. - */ -struct comm_point* comm_point_create_udp(struct comm_base* base, - int fd, struct sldns_buffer* buffer, int pp2_enabled, - comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); - -/** - * Create an UDP with ancillary data comm point. Calls malloc. - * Uses recvmsg instead of recv to get udp message. - * setups the structure with the parameters you provide. - * @param base: in which base to alloc the commpoint. - * @param fd: file descriptor of open UDP socket. - * @param buffer: shared buffer by UDP sockets from this thread. - * @param pp2_enabled: if the comm point will support PROXYv2. - * @param callback: callback function pointer. - * @param callback_arg: will be passed to your callback function. - * @param socket: and opened socket properties will be passed to your callback function. - * @return: returns the allocated communication point. NULL on error. - * Sets timeout to NULL. Turns off TCP options. - */ -struct comm_point* comm_point_create_udp_ancil(struct comm_base* base, - int fd, struct sldns_buffer* buffer, int pp2_enabled, - comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); - -/** - * Create a TCP listener comm point. Calls malloc. - * Setups the structure with the parameters you provide. - * Also Creates TCP Handlers, pre allocated for you. - * Uses the parameters you provide. - * @param base: in which base to alloc the commpoint. - * @param fd: file descriptor of open TCP socket set to listen nonblocking. - * @param num: becomes max_tcp_count, the routine allocates that - * many tcp handler commpoints. - * @param idle_timeout: TCP idle timeout in ms. - * @param harden_large_queries: whether query size should be limited. - * @param http_max_streams: maximum number of HTTP/2 streams per connection. - * @param http_endpoint: HTTP endpoint to service queries on - * @param tcp_conn_limit: TCP connection limit info. - * @param bufsize: size of buffer to create for handlers. - * @param spoolbuf: shared spool buffer for tcp_req_info structures. - * or NULL to not create those structures in the tcp handlers. - * @param port_type: the type of port we are creating a TCP listener for. Used - * to select handler type to use. - * @param pp2_enabled: if the comm point will support PROXYv2. - * @param callback: callback function pointer for TCP handlers. - * @param callback_arg: will be passed to your callback function. - * @param socket: and opened socket properties will be passed to your callback function. - * @return: returns the TCP listener commpoint. You can find the - * TCP handlers in the array inside the listener commpoint. - * returns NULL on error. - * Inits timeout to NULL. All handlers are on the free list. - */ -struct comm_point* comm_point_create_tcp(struct comm_base* base, - int fd, int num, int idle_timeout, int harden_large_queries, - uint32_t http_max_streams, char* http_endpoint, - struct tcl_list* tcp_conn_limit, - size_t bufsize, struct sldns_buffer* spoolbuf, - enum listen_type port_type, int pp2_enabled, - comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket); - -/** - * Create an outgoing TCP commpoint. No file descriptor is opened, left at -1. - * @param base: in which base to alloc the commpoint. - * @param bufsize: size of buffer to create for handlers. - * @param callback: callback function pointer for the handler. - * @param callback_arg: will be passed to your callback function. - * @return: the commpoint or NULL on error. - */ -struct comm_point* comm_point_create_tcp_out(struct comm_base* base, - size_t bufsize, comm_point_callback_type* callback, void* callback_arg); - -/** - * Create an outgoing HTTP commpoint. No file descriptor is opened, left at -1. - * @param base: in which base to alloc the commpoint. - * @param bufsize: size of buffer to create for handlers. - * @param callback: callback function pointer for the handler. - * @param callback_arg: will be passed to your callback function. - * @param temp: sldns buffer, shared between other http_out commpoints, for - * temporary data when performing callbacks. - * @return: the commpoint or NULL on error. - */ -struct comm_point* comm_point_create_http_out(struct comm_base* base, - size_t bufsize, comm_point_callback_type* callback, - void* callback_arg, struct sldns_buffer* temp); - -/** - * Create commpoint to listen to a local domain file descriptor. - * @param base: in which base to alloc the commpoint. - * @param fd: file descriptor of open AF_UNIX socket set to listen nonblocking. - * @param bufsize: size of buffer to create for handlers. - * @param callback: callback function pointer for the handler. - * @param callback_arg: will be passed to your callback function. - * @return: the commpoint or NULL on error. - */ -struct comm_point* comm_point_create_local(struct comm_base* base, - int fd, size_t bufsize, - comm_point_callback_type* callback, void* callback_arg); - -/** - * Create commpoint to listen to a local domain pipe descriptor. - * @param base: in which base to alloc the commpoint. - * @param fd: file descriptor. - * @param writing: true if you want to listen to writes, false for reads. - * @param callback: callback function pointer for the handler. - * @param callback_arg: will be passed to your callback function. - * @return: the commpoint or NULL on error. - */ -struct comm_point* comm_point_create_raw(struct comm_base* base, - int fd, int writing, - comm_point_callback_type* callback, void* callback_arg); - -/** - * Close a comm point fd. - * @param c: comm point to close. - */ -void comm_point_close(struct comm_point* c); - -/** - * Close and deallocate (free) the comm point. If the comm point is - * a tcp-accept point, also its tcp-handler points are deleted. - * @param c: comm point to delete. - */ -void comm_point_delete(struct comm_point* c); - -/** - * Send reply. Put message into commpoint buffer. - * @param repinfo: The reply info copied from a commpoint callback call. - */ -void comm_point_send_reply(struct comm_reply* repinfo); - -/** - * Drop reply. Cleans up. - * @param repinfo: The reply info copied from a commpoint callback call. - */ -void comm_point_drop_reply(struct comm_reply* repinfo); - -/** - * Send an udp message over a commpoint. - * @param c: commpoint to send it from. - * @param packet: what to send. - * @param addr: where to send it to. If NULL, send is performed, - * for connected sockets, to the connected address. - * @param addrlen: length of addr. - * @param is_connected: if the UDP socket is connect()ed. - * @return: false on a failure. - */ -int comm_point_send_udp_msg(struct comm_point* c, struct sldns_buffer* packet, - struct sockaddr* addr, socklen_t addrlen,int is_connected); - -/** - * Stop listening for input on the commpoint. No callbacks will happen. - * @param c: commpoint to disable. The fd is not closed. - */ -void comm_point_stop_listening(struct comm_point* c); - -/** - * Start listening again for input on the comm point. - * @param c: commpoint to enable again. - * @param newfd: new fd, or -1 to leave fd be. - * @param msec: timeout in milliseconds, or -1 for no (change to the) timeout. - * So seconds*1000. - */ -void comm_point_start_listening(struct comm_point* c, int newfd, int msec); - -/** - * Stop listening and start listening again for reading or writing. - * @param c: commpoint - * @param rd: if true, listens for reading. - * @param wr: if true, listens for writing. - */ -void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr); - -/** - * For TCP handlers that use c->tcp_timeout_msec, this routine adjusts - * it with the minimum. Otherwise, a 0 value advertised without the - * minimum applied moves to a 0 in comm_point_start_listening and that - * routine treats it as no timeout, listen forever, which is not wanted. - * @param c: comm point to use the tcp_timeout_msec of. - * @return adjusted tcp_timeout_msec value with the minimum if smaller. - */ -int adjusted_tcp_timeout(struct comm_point* c); - -/** - * Get size of memory used by comm point. - * For TCP handlers this includes subhandlers. - * For UDP handlers, this does not include the (shared) UDP buffer. - * @param c: commpoint. - * @return size in bytes. - */ -size_t comm_point_get_mem(struct comm_point* c); - -/** - * create timer. Not active upon creation. - * @param base: event handling base. - * @param cb: callback function: void myfunc(void* myarg); - * @param cb_arg: user callback argument. - * @return: the new timer or NULL on error. - */ -struct comm_timer* comm_timer_create(struct comm_base* base, - void (*cb)(void*), void* cb_arg); - -/** - * disable timer. Stops callbacks from happening. - * @param timer: to disable. - */ -void comm_timer_disable(struct comm_timer* timer); - -/** - * reset timevalue for timer. - * @param timer: timer to (re)set. - * @param tv: when the timer should activate. if NULL timer is disabled. - */ -void comm_timer_set(struct comm_timer* timer, struct timeval* tv); - -/** - * delete timer. - * @param timer: to delete. - */ -void comm_timer_delete(struct comm_timer* timer); - -/** - * see if timeout has been set to a value. - * @param timer: the timer to examine. - * @return: false if disabled or not set. - */ -int comm_timer_is_set(struct comm_timer* timer); - -/** - * Get size of memory used by comm timer. - * @param timer: the timer to examine. - * @return size in bytes. - */ -size_t comm_timer_get_mem(struct comm_timer* timer); - -/** - * Create a signal handler. Call signal_bind() later to bind to a signal. - * @param base: communication base to use. - * @param callback: called when signal is caught. - * @param cb_arg: user argument to callback - * @return: the signal struct or NULL on error. - */ -struct comm_signal* comm_signal_create(struct comm_base* base, - void (*callback)(int, void*), void* cb_arg); - -/** - * Bind signal struct to catch a signal. A single comm_signal can be bound - * to multiple signals, calling comm_signal_bind multiple times. - * @param comsig: the communication point, with callback information. - * @param sig: signal number. - * @return: true on success. false on error. - */ -int comm_signal_bind(struct comm_signal* comsig, int sig); - -/** - * Delete the signal communication point. - * @param comsig: to delete. - */ -void comm_signal_delete(struct comm_signal* comsig); - -/** - * perform accept(2) with error checking. - * @param c: commpoint with accept fd. - * @param addr: remote end returned here. - * @param addrlen: length of remote end returned here. - * @return new fd, or -1 on error. - * if -1, error message has been printed if necessary, simply drop - * out of the reading handler. - */ -int comm_point_perform_accept(struct comm_point* c, - struct sockaddr_storage* addr, socklen_t* addrlen); - -/**** internal routines ****/ - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for udp comm point. - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_udp_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for udp ancillary data comm point. - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_udp_ancil_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for tcp accept comm point - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_tcp_accept_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for tcp data comm point - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_tcp_handle_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for tcp data comm point - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_http_handle_callback(int fd, short event, void* arg); - -/** - * HTTP2 session. HTTP2 related info per comm point. - */ -struct http2_session { - /** first item in list of streams */ - struct http2_stream* first_stream; -#ifdef HAVE_NGHTTP2 - /** nghttp2 session */ - nghttp2_session *session; - /** store nghttp2 callbacks for easy reuse */ - nghttp2_session_callbacks* callbacks; -#endif - /** comm point containing buffer used to build answer in worker or - * module */ - struct comm_point* c; - /** session is instructed to get dropped (comm port will be closed) */ - int is_drop; - /** postpone dropping the session, can be used to prevent dropping - * while being in a callback */ - int postpone_drop; -}; - -/** enum of HTTP status */ -enum http_status { - HTTP_STATUS_OK = 200, - HTTP_STATUS_BAD_REQUEST = 400, - HTTP_STATUS_NOT_FOUND = 404, - HTTP_STATUS_PAYLOAD_TOO_LARGE = 413, - HTTP_STATUS_URI_TOO_LONG = 414, - HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, - HTTP_STATUS_NOT_IMPLEMENTED = 501 -}; - -/** - * HTTP stream. Part of list of HTTP2 streams per session. - */ -struct http2_stream { - /** next stream in list per session */ - struct http2_stream* next; - /** previous stream in list per session */ - struct http2_stream* prev; - /** HTTP2 stream ID is an unsigned 31-bit integer */ - int32_t stream_id; - /** HTTP method used for this stream */ - enum { - HTTP_METHOD_POST = 1, - HTTP_METHOD_GET, - HTTP_METHOD_UNSUPPORTED - } http_method; - /** message contains invalid content type */ - int invalid_content_type; - /** message body content type */ - size_t content_length; - /** HTTP response status */ - enum http_status status; - /** request for non existing endpoint */ - int invalid_endpoint; - /** query in request is too large */ - int query_too_large; - /** buffer to store query into. Can't use session shared buffer as query - * can arrive in parts, intertwined with frames for other queries. */ - struct sldns_buffer* qbuffer; - /** buffer to store response into. Can't use shared buffer as a next - * query read callback can overwrite it before it is send out. */ - struct sldns_buffer* rbuffer; - /** mesh area containing mesh state */ - struct mesh_area* mesh; - /** mesh state for query. Used to remove mesh reply before closing - * stream. */ - struct mesh_state* mesh_state; -}; - -#ifdef HAVE_NGHTTP2 -/** nghttp2 receive cb. Read from SSL connection into nghttp2 buffer */ -ssize_t http2_recv_cb(nghttp2_session* session, uint8_t* buf, - size_t len, int flags, void* cb_arg); -/** nghttp2 send callback. Send from nghttp2 buffer to ssl socket */ -ssize_t http2_send_cb(nghttp2_session* session, const uint8_t* buf, - size_t len, int flags, void* cb_arg); -/** nghttp2 callback on closing stream */ -int http2_stream_close_cb(nghttp2_session* session, int32_t stream_id, - uint32_t error_code, void* cb_arg); -#endif - -/** - * Create new http2 stream - * @param stream_id: ID for stream to create. - * @return malloc'ed stream, NULL on error - */ -struct http2_stream* http2_stream_create(int32_t stream_id); - -/** - * Add new stream to session linked list - * @param h2_session: http2 session to add stream to - * @param h2_stream: stream to add to session list - */ -void http2_session_add_stream(struct http2_session* h2_session, - struct http2_stream* h2_stream); - -/** Add mesh state to stream. To be able to remove mesh reply on stream closure - */ -void http2_stream_add_meshstate(struct http2_stream* h2_stream, - struct mesh_area* mesh, struct mesh_state* m); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for timer comm. - * @param fd: file descriptor (always -1). - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_timer structure. - */ -void comm_timer_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * handle libevent callback for signal comm. - * @param fd: file descriptor (used for the signal number). - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the internal commsignal structure. - */ -void comm_signal_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * libevent callback for AF_UNIX fds - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_local_handle_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * libevent callback for raw fd access. - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_point_raw_handle_callback(int fd, short event, void* arg); - -/** - * This routine is published for checks and tests, and is only used internally. - * libevent callback for timeout on slow accept. - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -void comm_base_handle_slow_accept(int fd, short event, void* arg); - -#ifdef USE_WINSOCK -/** - * Callback for openssl BIO to on windows detect WSAEWOULDBLOCK and notify - * the winsock_event of this for proper TCP nonblocking implementation. - * @param c: comm_point, fd must be set its struct event is registered. - * @param ssl: openssl SSL, fd must be set so it has a bio. - */ -void comm_point_tcp_win_bio_cb(struct comm_point* c, void* ssl); -#endif - -/** - * See if errno for tcp connect has to be logged or not. This uses errno - * @param addr: apart from checking errno, the addr is checked for ip4mapped - * and broadcast type, hence passed. - * @param addrlen: length of the addr parameter. - * @return true if it needs to be logged. - */ -int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen); - -#ifdef HAVE_SSL -/** - * True if the ssl handshake error has to be squelched from the logs - * @param err: the error returned by the openssl routine, ERR_get_error. - * This is a packed structure with elements that are examined. - * @return true if the error is squelched (not logged). - */ -int squelch_err_ssl_handshake(unsigned long err); -#endif - -#endif /* NET_EVENT_H */ diff --git a/crates/libunbound-sys/unbound/util/proxy_protocol.c b/crates/libunbound-sys/unbound/util/proxy_protocol.c deleted file mode 100644 index 757c5141..00000000 --- a/crates/libunbound-sys/unbound/util/proxy_protocol.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * util/proxy_protocol.c - event notification - * - * Copyright (c) 2022, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains PROXY protocol functions. - */ -#include "config.h" -#include "util/log.h" -#include "util/proxy_protocol.h" - -int -pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src, - int stream) -{ - int af; - if(!src) return 0; - af = (int)((struct sockaddr_in*)src)->sin_family; - if(sldns_buffer_remaining(buf) < - PP2_HEADER_SIZE + (af==AF_INET?12:36)) { - return 0; - } - /* sig */ - sldns_buffer_write(buf, PP2_SIG, PP2_SIG_LEN); - /* version and command */ - sldns_buffer_write_u8(buf, (PP2_VERSION << 4) | PP2_CMD_PROXY); - if(af==AF_INET) { - /* family and protocol */ - sldns_buffer_write_u8(buf, - (PP2_AF_INET<<4) | - (stream?PP2_PROT_STREAM:PP2_PROT_DGRAM)); - /* length */ - sldns_buffer_write_u16(buf, 12); - /* src addr */ - sldns_buffer_write(buf, - &((struct sockaddr_in*)src)->sin_addr.s_addr, 4); - /* dst addr */ - sldns_buffer_write_u32(buf, 0); - /* src port */ - sldns_buffer_write(buf, - &((struct sockaddr_in*)src)->sin_port, 2); - /* dst port */ - sldns_buffer_write_u16(buf, 0); - } else { - /* family and protocol */ - sldns_buffer_write_u8(buf, - (PP2_AF_INET6<<4) | - (stream?PP2_PROT_STREAM:PP2_PROT_DGRAM)); - /* length */ - sldns_buffer_write_u16(buf, 36); - /* src addr */ - sldns_buffer_write(buf, - &((struct sockaddr_in6*)src)->sin6_addr, 16); - /* dst addr */ - sldns_buffer_set_at(buf, - sldns_buffer_position(buf), 0, 16); - sldns_buffer_skip(buf, 16); - /* src port */ - sldns_buffer_write(buf, - &((struct sockaddr_in6*)src)->sin6_port, 2); - /* dst port */ - sldns_buffer_write_u16(buf, 0); - } - return 1; -} - -struct pp2_header* -pp2_read_header(struct sldns_buffer* buf) -{ - size_t size; - struct pp2_header* header = (struct pp2_header*)sldns_buffer_begin(buf); - /* Try to fail all the unsupported cases first. */ - if(sldns_buffer_remaining(buf) < PP2_HEADER_SIZE) { - log_err("proxy_protocol: not enough space for header"); - return NULL; - } - /* Check for PROXYv2 header */ - if(memcmp(header, PP2_SIG, PP2_SIG_LEN) != 0 || - ((header->ver_cmd & 0xF0)>>4) != PP2_VERSION) { - log_err("proxy_protocol: could not match PROXYv2 header"); - return NULL; - } - /* Check the length */ - size = PP2_HEADER_SIZE + ntohs(header->len); - if(sldns_buffer_remaining(buf) < size) { - log_err("proxy_protocol: not enough space for header"); - return NULL; - } - /* Check for supported commands */ - if((header->ver_cmd & 0xF) != PP2_CMD_LOCAL && - (header->ver_cmd & 0xF) != PP2_CMD_PROXY) { - log_err("proxy_protocol: unsupported command"); - return NULL; - } - /* Check for supported family and protocol */ - if(header->fam_prot != 0x00 /* AF_UNSPEC|UNSPEC */ && - header->fam_prot != 0x11 /* AF_INET|STREAM */ && - header->fam_prot != 0x12 /* AF_INET|DGRAM */ && - header->fam_prot != 0x21 /* AF_INET6|STREAM */ && - header->fam_prot != 0x22 /* AF_INET6|DGRAM */) { - log_err("proxy_protocol: unsupported family and protocol"); - return NULL; - } - /* We have a correct header */ - return header; -} diff --git a/crates/libunbound-sys/unbound/util/proxy_protocol.h b/crates/libunbound-sys/unbound/util/proxy_protocol.h deleted file mode 100644 index 13cab9d7..00000000 --- a/crates/libunbound-sys/unbound/util/proxy_protocol.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * util/proxy_protocol.h - PROXY protocol - * - * Copyright (c) 2022, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains PROXY protocol structs and functions. - * Only v2 is supported. TLVs are not currently supported. - */ -#ifndef PROXY_PROTOCOL_H -#define PROXY_PROTOCOL_H - -#include "sldns/sbuffer.h" - -/** PROXYv2 minimum header size */ -#define PP2_HEADER_SIZE 16 - -/** PROXYv2 header signature */ -#define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A" -#define PP2_SIG_LEN 12 - -/** PROXYv2 version */ -#define PP2_VERSION 0x2 - -/** - * PROXYv2 command. - */ -enum pp2_command { - PP2_CMD_LOCAL = 0x0, - PP2_CMD_PROXY = 0x1 -}; - -/** - * PROXYv2 address family. - */ -enum pp2_af { - PP2_AF_UNSPEC = 0x0, - PP2_AF_INET = 0x1, - PP2_AF_INET6 = 0x2, - PP2_AF_UNIX = 0x3 -}; - -/** - * PROXYv2 protocol. - */ -enum pp2_protocol { - PP2_PROT_UNSPEC = 0x0, - PP2_PROT_STREAM = 0x1, - PP2_PROT_DGRAM = 0x2 -}; - -/** - * PROXYv2 header. - */ -struct pp2_header { - uint8_t sig[PP2_SIG_LEN]; - uint8_t ver_cmd; - uint8_t fam_prot; - uint16_t len; - union { - struct { /* for TCP/UDP over IPv4, len = 12 */ - uint32_t src_addr; - uint32_t dst_addr; - uint16_t src_port; - uint16_t dst_port; - } addr4; - struct { /* for TCP/UDP over IPv6, len = 36 */ - uint8_t src_addr[16]; - uint8_t dst_addr[16]; - uint16_t src_port; - uint16_t dst_port; - } addr6; - struct { /* for AF_UNIX sockets, len = 216 */ - uint8_t src_addr[108]; - uint8_t dst_addr[108]; - } addru; - } addr; -}; - -/** - * Write a PROXYv2 header at the current position of the buffer. - * @param buf: the buffer to write to. - * @param src: the source address. - * @param stream: if the protocol is stream or datagram. - * @return 1 on success, 0 on failure. - */ -int pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src, - int stream); - -/** - * Read a PROXYv2 header from the current position of the buffer. - * It does initial validation and returns a pointer to the buffer position on - * success. - * @param buf: the buffer to read from. - * @return the pointer to the buffer position on success, NULL on error. - */ -struct pp2_header* pp2_read_header(struct sldns_buffer* buf); - -#endif /* PROXY_PROTOCOL_H */ diff --git a/crates/libunbound-sys/unbound/util/random.c b/crates/libunbound-sys/unbound/util/random.c deleted file mode 100644 index 6eb102c6..00000000 --- a/crates/libunbound-sys/unbound/util/random.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * util/random.c - thread safe random generator, which is reasonably secure. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * Thread safe random functions. Similar to arc4random() with an explicit - * initialisation routine. - * - * The code in this file is based on arc4random from - * openssh-4.0p1/openbsd-compat/bsd-arc4random.c - * That code is also BSD licensed. Here is their statement: - * - * Copyright (c) 1996, David Mazieres - * Copyright (c) 2008, Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "config.h" -#include "util/random.h" -#include "util/log.h" -#include - -#ifdef HAVE_NSS -/* nspr4 */ -#include "prerror.h" -/* nss3 */ -#include "secport.h" -#include "pk11pub.h" -#elif defined(HAVE_NETTLE) -#include "yarrow.h" -#endif - -/** - * Max random value. Similar to RAND_MAX, but more portable - * (mingw uses only 15 bits random). - */ -#define MAX_VALUE 0x7fffffff - -#if defined(HAVE_SSL) || defined(HAVE_LIBBSD) -struct ub_randstate* -ub_initstate(struct ub_randstate* ATTR_UNUSED(from)) -{ - struct ub_randstate* s = (struct ub_randstate*)malloc(1); - if(!s) { - log_err("malloc failure in random init"); - return NULL; - } - return s; -} - -long int -ub_random(struct ub_randstate* ATTR_UNUSED(s)) -{ - /* This relies on MAX_VALUE being 0x7fffffff. */ - return (long)arc4random() & MAX_VALUE; -} - -long int -ub_random_max(struct ub_randstate* state, long int x) -{ - (void)state; - /* on OpenBSD, this does not need _seed(), or _stir() calls */ - return (long)arc4random_uniform((uint32_t)x); -} - -#elif defined(HAVE_NSS) - -/* not much to remember for NSS since we use its pk11_random, placeholder */ -struct ub_randstate { - int ready; -}; - -struct ub_randstate* ub_initstate(struct ub_randstate* ATTR_UNUSED(from)) -{ - struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s)); - if(!s) { - log_err("malloc failure in random init"); - return NULL; - } - return s; -} - -long int ub_random(struct ub_randstate* ATTR_UNUSED(state)) -{ - long int x; - /* random 31 bit value. */ - SECStatus s = PK11_GenerateRandom((unsigned char*)&x, (int)sizeof(x)); - if(s != SECSuccess) { - /* unbound needs secure randomness for randomized - * ID bits and port numbers in packets to upstream servers */ - fatal_exit("PK11_GenerateRandom error: %s", - PORT_ErrorToString(PORT_GetError())); - } - return x & MAX_VALUE; -} - -#elif defined(HAVE_NETTLE) - -/** - * libnettle implements a Yarrow-256 generator (SHA256 + AES), - * and we have to ensure it is seeded before use. - */ -struct ub_randstate { - struct yarrow256_ctx ctx; - int seeded; -}; - -struct ub_randstate* ub_initstate(struct ub_randstate* ATTR_UNUSED(from)) -{ - struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s)); - uint8_t buf[YARROW256_SEED_FILE_SIZE]; - if(!s) { - log_err("malloc failure in random init"); - return NULL; - } - /* Setup Yarrow context */ - yarrow256_init(&s->ctx, 0, NULL); - - if(getentropy(buf, sizeof(buf)) != -1) { - /* got entropy */ - yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf); - s->seeded = yarrow256_is_seeded(&s->ctx); - } else { - log_err("nettle random(yarrow) cannot initialize, " - "getentropy failed: %s", strerror(errno)); - free(s); - return NULL; - } - - return s; -} - -long int ub_random(struct ub_randstate* s) -{ - /* random 31 bit value. */ - long int x = 0; - if (!s || !s->seeded) { - log_err("Couldn't generate randomness, Yarrow-256 generator not yet seeded"); - } else { - yarrow256_random(&s->ctx, sizeof(x), (uint8_t *)&x); - } - return x & MAX_VALUE; -} -#endif /* HAVE_SSL or HAVE_LIBBSD or HAVE_NSS or HAVE_NETTLE */ - - -#if defined(HAVE_NSS) || defined(HAVE_NETTLE) && !defined(HAVE_LIBBSD) -long int -ub_random_max(struct ub_randstate* state, long int x) -{ - /* make sure we fetch in a range that is divisible by x. ignore - * values from d .. MAX_VALUE, instead draw a new number */ - long int d = MAX_VALUE - (MAX_VALUE % x); /* d is divisible by x */ - long int v = ub_random(state); - while(d <= v) - v = ub_random(state); - return (v % x); -} -#endif /* HAVE_NSS or HAVE_NETTLE and !HAVE_LIBBSD */ - -void -ub_randfree(struct ub_randstate* s) -{ - free(s); - /* user app must do RAND_cleanup(); */ -} diff --git a/crates/libunbound-sys/unbound/util/random.h b/crates/libunbound-sys/unbound/util/random.h deleted file mode 100644 index b257793a..00000000 --- a/crates/libunbound-sys/unbound/util/random.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * util/random.h - thread safe random generator, which is reasonably secure. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UTIL_RANDOM_H -#define UTIL_RANDOM_H - -/** - * \file - * Thread safe random functions. Similar to arc4random() with an explicit - * initialisation routine. - */ - -/** - * random state structure. - */ -struct ub_randstate; - -/** - * Initialize a random generator state for use - * @param from: if not NULL, the seed is taken from this random structure. - * can be used to seed random states via a parent-random-state that - * is itself seeded with entropy. - * @return new state or NULL alloc failure. - */ -struct ub_randstate* ub_initstate(struct ub_randstate* from); - -/** - * Generate next random number from the state passed along. - * Thread safe, so random numbers are repeatable. - * @param state: must have been initialised with ub_initstate. - * @return: random 31 bit value. - */ -long int ub_random(struct ub_randstate* state); - -/** - * Generate random number between 0 and x-1. No modulo bias. - * @param state: must have been initialised with ub_initstate. - * @param x: an upper limit. not (negative or zero). must be smaller than 2**31. - * @return: random value between 0..x-1. Possibly more than one - * random number is picked from the random stream to satisfy this. - */ -long int ub_random_max(struct ub_randstate* state, long int x); - -/** - * Delete the random state. - * @param state: to delete. - */ -void ub_randfree(struct ub_randstate* state); - -#endif /* UTIL_RANDOM_H */ diff --git a/crates/libunbound-sys/unbound/util/rbtree.c b/crates/libunbound-sys/unbound/util/rbtree.c deleted file mode 100644 index f031c9a1..00000000 --- a/crates/libunbound-sys/unbound/util/rbtree.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * rbtree.c -- generic red black tree - * - * Copyright (c) 2001-2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * Implementation of a redblack tree. - */ - -#include "config.h" -#include "log.h" -#include "fptr_wlist.h" -#include "util/rbtree.h" - -/** Node colour black */ -#define BLACK 0 -/** Node colour red */ -#define RED 1 - -/** the NULL node, global alloc */ -rbnode_type rbtree_null_node = { - RBTREE_NULL, /* Parent. */ - RBTREE_NULL, /* Left. */ - RBTREE_NULL, /* Right. */ - NULL, /* Key. */ - BLACK /* Color. */ -}; - -/** rotate subtree left (to preserve redblack property) */ -static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node); -/** rotate subtree right (to preserve redblack property) */ -static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node); -/** Fixup node colours when insert happened */ -static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node); -/** Fixup node colours when delete happened */ -static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, - rbnode_type* child_parent); - -/* - * Creates a new red black tree, initializes and returns a pointer to it. - * - * Return NULL on failure. - * - */ -rbtree_type * -rbtree_create (int (*cmpf)(const void *, const void *)) -{ - rbtree_type *rbtree; - - /* Allocate memory for it */ - rbtree = (rbtree_type *) malloc(sizeof(rbtree_type)); - if (!rbtree) { - return NULL; - } - - /* Initialize it */ - rbtree_init(rbtree, cmpf); - - return rbtree; -} - -void -rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *)) -{ - /* Initialize it */ - rbtree->root = RBTREE_NULL; - rbtree->count = 0; - rbtree->cmp = cmpf; -} - -/* - * Rotates the node to the left. - * - */ -static void -rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node) -{ - rbnode_type *right = node->right; - node->right = right->left; - if (right->left != RBTREE_NULL) - right->left->parent = node; - - right->parent = node->parent; - - if (node->parent != RBTREE_NULL) { - if (node == node->parent->left) { - node->parent->left = right; - } else { - node->parent->right = right; - } - } else { - rbtree->root = right; - } - right->left = node; - node->parent = right; -} - -/* - * Rotates the node to the right. - * - */ -static void -rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node) -{ - rbnode_type *left = node->left; - node->left = left->right; - if (left->right != RBTREE_NULL) - left->right->parent = node; - - left->parent = node->parent; - - if (node->parent != RBTREE_NULL) { - if (node == node->parent->right) { - node->parent->right = left; - } else { - node->parent->left = left; - } - } else { - rbtree->root = left; - } - left->right = node; - node->parent = left; -} - -static void -rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node) -{ - rbnode_type *uncle; - - /* While not at the root and need fixing... */ - while (node != rbtree->root && node->parent->color == RED) { - /* If our parent is left child of our grandparent... */ - if (node->parent == node->parent->parent->left) { - uncle = node->parent->parent->right; - - /* If our uncle is red... */ - if (uncle->color == RED) { - /* Paint the parent and the uncle black... */ - node->parent->color = BLACK; - uncle->color = BLACK; - - /* And the grandparent red... */ - node->parent->parent->color = RED; - - /* And continue fixing the grandparent */ - node = node->parent->parent; - } else { /* Our uncle is black... */ - /* Are we the right child? */ - if (node == node->parent->right) { - node = node->parent; - rbtree_rotate_left(rbtree, node); - } - /* Now we're the left child, repaint and rotate... */ - node->parent->color = BLACK; - node->parent->parent->color = RED; - rbtree_rotate_right(rbtree, node->parent->parent); - } - } else { - uncle = node->parent->parent->left; - - /* If our uncle is red... */ - if (uncle->color == RED) { - /* Paint the parent and the uncle black... */ - node->parent->color = BLACK; - uncle->color = BLACK; - - /* And the grandparent red... */ - node->parent->parent->color = RED; - - /* And continue fixing the grandparent */ - node = node->parent->parent; - } else { /* Our uncle is black... */ - /* Are we the right child? */ - if (node == node->parent->left) { - node = node->parent; - rbtree_rotate_right(rbtree, node); - } - /* Now we're the right child, repaint and rotate... */ - node->parent->color = BLACK; - node->parent->parent->color = RED; - rbtree_rotate_left(rbtree, node->parent->parent); - } - } - } - rbtree->root->color = BLACK; -} - - -/* - * Inserts a node into a red black tree. - * - * Returns NULL on failure or the pointer to the newly added node - * otherwise. - */ -rbnode_type * -rbtree_insert (rbtree_type *rbtree, rbnode_type *data) -{ - /* XXX Not necessary, but keeps compiler quiet... */ - int r = 0; - - /* We start at the root of the tree */ - rbnode_type *node = rbtree->root; - rbnode_type *parent = RBTREE_NULL; - - fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp)); - /* Lets find the new parent... */ - while (node != RBTREE_NULL) { - /* Compare two keys, do we have a duplicate? */ - if ((r = rbtree->cmp(data->key, node->key)) == 0) { - return NULL; - } - parent = node; - - if (r < 0) { - node = node->left; - } else { - node = node->right; - } - } - - /* Initialize the new node */ - data->parent = parent; - data->left = data->right = RBTREE_NULL; - data->color = RED; - rbtree->count++; - - /* Insert it into the tree... */ - if (parent != RBTREE_NULL) { - if (r < 0) { - parent->left = data; - } else { - parent->right = data; - } - } else { - rbtree->root = data; - } - - /* Fix up the red-black properties... */ - rbtree_insert_fixup(rbtree, data); - - return data; -} - -/* - * Searches the red black tree, returns the data if key is found or NULL otherwise. - * - */ -rbnode_type * -rbtree_search (rbtree_type *rbtree, const void *key) -{ - rbnode_type *node; - - if (rbtree_find_less_equal(rbtree, key, &node)) { - return node; - } else { - return NULL; - } -} - -/** helpers for delete: swap node colours */ -static void swap_int8(uint8_t* x, uint8_t* y) -{ - uint8_t t = *x; *x = *y; *y = t; -} - -/** helpers for delete: swap node pointers */ -static void swap_np(rbnode_type** x, rbnode_type** y) -{ - rbnode_type* t = *x; *x = *y; *y = t; -} - -/** Update parent pointers of child trees of 'parent' */ -static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent, - rbnode_type* old, rbnode_type* new) -{ - if(parent == RBTREE_NULL) - { - log_assert(rbtree->root == old); - if(rbtree->root == old) rbtree->root = new; - return; - } - log_assert(parent->left == old || parent->right == old - || parent->left == new || parent->right == new); - if(parent->left == old) parent->left = new; - if(parent->right == old) parent->right = new; -} -/** Update parent pointer of a node 'child' */ -static void change_child_ptr(rbnode_type* child, rbnode_type* old, - rbnode_type* new) -{ - if(child == RBTREE_NULL) return; - log_assert(child->parent == old || child->parent == new); - if(child->parent == old) child->parent = new; -} - -rbnode_type* -rbtree_delete(rbtree_type *rbtree, const void *key) -{ - rbnode_type *to_delete; - rbnode_type *child; - if((to_delete = rbtree_search(rbtree, key)) == 0) return 0; - rbtree->count--; - - /* make sure we have at most one non-leaf child */ - if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL) - { - /* swap with smallest from right subtree (or largest from left) */ - rbnode_type *smright = to_delete->right; - while(smright->left != RBTREE_NULL) - smright = smright->left; - /* swap the smright and to_delete elements in the tree, - * but the rbnode_type is first part of user data struct - * so cannot just swap the keys and data pointers. Instead - * readjust the pointers left,right,parent */ - - /* swap colors - colors are tied to the position in the tree */ - swap_int8(&to_delete->color, &smright->color); - - /* swap child pointers in parents of smright/to_delete */ - change_parent_ptr(rbtree, to_delete->parent, to_delete, smright); - if(to_delete->right != smright) - change_parent_ptr(rbtree, smright->parent, smright, to_delete); - - /* swap parent pointers in children of smright/to_delete */ - change_child_ptr(smright->left, smright, to_delete); - change_child_ptr(smright->left, smright, to_delete); - change_child_ptr(smright->right, smright, to_delete); - change_child_ptr(smright->right, smright, to_delete); - change_child_ptr(to_delete->left, to_delete, smright); - if(to_delete->right != smright) - change_child_ptr(to_delete->right, to_delete, smright); - if(to_delete->right == smright) - { - /* set up so after swap they work */ - to_delete->right = to_delete; - smright->parent = smright; - } - - /* swap pointers in to_delete/smright nodes */ - swap_np(&to_delete->parent, &smright->parent); - swap_np(&to_delete->left, &smright->left); - swap_np(&to_delete->right, &smright->right); - - /* now delete to_delete (which is at the location where the smright previously was) */ - } - log_assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL); - - if(to_delete->left != RBTREE_NULL) child = to_delete->left; - else child = to_delete->right; - - /* unlink to_delete from the tree, replace to_delete with child */ - change_parent_ptr(rbtree, to_delete->parent, to_delete, child); - change_child_ptr(child, to_delete, to_delete->parent); - - if(to_delete->color == RED) - { - /* if node is red then the child (black) can be swapped in */ - } - else if(child->color == RED) - { - /* change child to BLACK, removing a RED node is no problem */ - if(child!=RBTREE_NULL) child->color = BLACK; - } - else rbtree_delete_fixup(rbtree, child, to_delete->parent); - - /* unlink completely */ - to_delete->parent = RBTREE_NULL; - to_delete->left = RBTREE_NULL; - to_delete->right = RBTREE_NULL; - to_delete->color = BLACK; - return to_delete; -} - -static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child, - rbnode_type* child_parent) -{ - rbnode_type* sibling; - int go_up = 1; - - /* determine sibling to the node that is one-black short */ - if(child_parent->right == child) sibling = child_parent->left; - else sibling = child_parent->right; - - while(go_up) - { - if(child_parent == RBTREE_NULL) - { - /* removed parent==black from root, every path, so ok */ - return; - } - - if(sibling->color == RED) - { /* rotate to get a black sibling */ - child_parent->color = RED; - sibling->color = BLACK; - if(child_parent->right == child) - rbtree_rotate_right(rbtree, child_parent); - else rbtree_rotate_left(rbtree, child_parent); - /* new sibling after rotation */ - if(child_parent->right == child) sibling = child_parent->left; - else sibling = child_parent->right; - } - - if(child_parent->color == BLACK - && sibling->color == BLACK - && sibling->left->color == BLACK - && sibling->right->color == BLACK) - { /* fixup local with recolor of sibling */ - if(sibling != RBTREE_NULL) - sibling->color = RED; - - child = child_parent; - child_parent = child_parent->parent; - /* prepare to go up, new sibling */ - if(child_parent->right == child) sibling = child_parent->left; - else sibling = child_parent->right; - } - else go_up = 0; - } - - if(child_parent->color == RED - && sibling->color == BLACK - && sibling->left->color == BLACK - && sibling->right->color == BLACK) - { - /* move red to sibling to rebalance */ - if(sibling != RBTREE_NULL) - sibling->color = RED; - child_parent->color = BLACK; - return; - } - log_assert(sibling != RBTREE_NULL); - - /* get a new sibling, by rotating at sibling. See which child - of sibling is red */ - if(child_parent->right == child - && sibling->color == BLACK - && sibling->right->color == RED - && sibling->left->color == BLACK) - { - sibling->color = RED; - sibling->right->color = BLACK; - rbtree_rotate_left(rbtree, sibling); - /* new sibling after rotation */ - if(child_parent->right == child) sibling = child_parent->left; - else sibling = child_parent->right; - } - else if(child_parent->left == child - && sibling->color == BLACK - && sibling->left->color == RED - && sibling->right->color == BLACK) - { - sibling->color = RED; - sibling->left->color = BLACK; - rbtree_rotate_right(rbtree, sibling); - /* new sibling after rotation */ - if(child_parent->right == child) sibling = child_parent->left; - else sibling = child_parent->right; - } - - /* now we have a black sibling with a red child. rotate and exchange colors. */ - sibling->color = child_parent->color; - child_parent->color = BLACK; - if(child_parent->right == child) - { - log_assert(sibling->left->color == RED); - sibling->left->color = BLACK; - rbtree_rotate_right(rbtree, child_parent); - } - else - { - log_assert(sibling->right->color == RED); - sibling->right->color = BLACK; - rbtree_rotate_left(rbtree, child_parent); - } -} - -int -rbtree_find_less_equal(rbtree_type *rbtree, const void *key, - rbnode_type **result) -{ - int r; - rbnode_type *node; - - log_assert(result); - - /* We start at root... */ - node = rbtree->root; - - *result = NULL; - fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp)); - - /* While there are children... */ - while (node != RBTREE_NULL) { - r = rbtree->cmp(key, node->key); - if (r == 0) { - /* Exact match */ - *result = node; - return 1; - } - if (r < 0) { - node = node->left; - } else { - /* Temporary match */ - *result = node; - node = node->right; - } - } - return 0; -} - -/* - * Finds the first element in the red black tree - * - */ -rbnode_type * -rbtree_first (rbtree_type *rbtree) -{ - rbnode_type *node; - - for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left); - return node; -} - -rbnode_type * -rbtree_last (rbtree_type *rbtree) -{ - rbnode_type *node; - - for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right); - return node; -} - -/* - * Returns the next node... - * - */ -rbnode_type * -rbtree_next (rbnode_type *node) -{ - rbnode_type *parent; - - if (node->right != RBTREE_NULL) { - /* One right, then keep on going left... */ - for (node = node->right; node->left != RBTREE_NULL; node = node->left); - } else { - parent = node->parent; - while (parent != RBTREE_NULL && node == parent->right) { - node = parent; - parent = parent->parent; - } - node = parent; - } - return node; -} - -rbnode_type * -rbtree_previous(rbnode_type *node) -{ - rbnode_type *parent; - - if (node->left != RBTREE_NULL) { - /* One left, then keep on going right... */ - for (node = node->left; node->right != RBTREE_NULL; node = node->right); - } else { - parent = node->parent; - while (parent != RBTREE_NULL && node == parent->left) { - node = parent; - parent = parent->parent; - } - node = parent; - } - return node; -} - -/** recursive descent traverse */ -static void -traverse_post(void (*func)(rbnode_type*, void*), void* arg, rbnode_type* node) -{ - if(!node || node == RBTREE_NULL) - return; - /* recurse */ - traverse_post(func, arg, node->left); - traverse_post(func, arg, node->right); - /* call user func */ - (*func)(node, arg); -} - -void -traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*), - void* arg) -{ - traverse_post(func, arg, tree->root); -} diff --git a/crates/libunbound-sys/unbound/util/rbtree.h b/crates/libunbound-sys/unbound/util/rbtree.h deleted file mode 100644 index dfcf09ac..00000000 --- a/crates/libunbound-sys/unbound/util/rbtree.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * rbtree.h -- generic red-black tree - * - * Copyright (c) 2001-2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/** - * \file - * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use - * in unbound (memory allocation, logging and so on). - */ - -#ifndef UTIL_RBTREE_H_ -#define UTIL_RBTREE_H_ - -/** - * This structure must be the first member of the data structure in - * the rbtree. This allows easy casting between an rbnode_type and the - * user data (poor man's inheritance). - */ -typedef struct rbnode_type rbnode_type; -/** - * The rbnode_type struct definition. - */ -struct rbnode_type { - /** parent in rbtree, RBTREE_NULL for root */ - rbnode_type *parent; - /** left node (smaller items) */ - rbnode_type *left; - /** right node (larger items) */ - rbnode_type *right; - /** pointer to sorting key */ - const void *key; - /** colour of this node */ - uint8_t color; -}; - -/** The nullpointer, points to empty node */ -#define RBTREE_NULL &rbtree_null_node -/** the global empty node */ -extern rbnode_type rbtree_null_node; - -/** An entire red black tree */ -typedef struct rbtree_type rbtree_type; -/** definition for tree struct */ -struct rbtree_type { - /** The root of the red-black tree */ - rbnode_type *root; - - /** The number of the nodes in the tree */ - size_t count; - - /** - * Key compare function. <0,0,>0 like strcmp. - * Return 0 on two NULL ptrs. - */ - int (*cmp) (const void *, const void *); -}; - -/** - * Create new tree (malloced) with given key compare function. - * @param cmpf: compare function (like strcmp) takes pointers to two keys. - * @return: new tree, empty. - */ -rbtree_type *rbtree_create(int (*cmpf)(const void *, const void *)); - -/** - * Init a new tree (malloced by caller) with given key compare function. - * @param rbtree: uninitialised memory for new tree, returned empty. - * @param cmpf: compare function (like strcmp) takes pointers to two keys. - */ -void rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *)); - -/** - * Insert data into the tree. - * @param rbtree: tree to insert to. - * @param data: element to insert. - * @return: data ptr or NULL if key already present. - */ -rbnode_type *rbtree_insert(rbtree_type *rbtree, rbnode_type *data); - -/** - * Delete element from tree. - * @param rbtree: tree to delete from. - * @param key: key of item to delete. - * @return: node that is now unlinked from the tree. User to delete it. - * returns 0 if node not present - */ -rbnode_type *rbtree_delete(rbtree_type *rbtree, const void *key); - -/** - * Find key in tree. Returns NULL if not found. - * @param rbtree: tree to find in. - * @param key: key that must match. - * @return: node that fits or NULL. - */ -rbnode_type *rbtree_search(rbtree_type *rbtree, const void *key); - -/** - * Find, but match does not have to be exact. - * @param rbtree: tree to find in. - * @param key: key to find position of. - * @param result: set to the exact node if present, otherwise to element that - * precedes the position of key in the tree. NULL if no smaller element. - * @return: true if exact match in result. Else result points to <= element, - * or NULL if key is smaller than the smallest key. - */ -int rbtree_find_less_equal(rbtree_type *rbtree, const void *key, - rbnode_type **result); - -/** - * Returns first (smallest) node in the tree - * @param rbtree: tree - * @return: smallest element or NULL if tree empty. - */ -rbnode_type *rbtree_first(rbtree_type *rbtree); - -/** - * Returns last (largest) node in the tree - * @param rbtree: tree - * @return: largest element or NULL if tree empty. - */ -rbnode_type *rbtree_last(rbtree_type *rbtree); - -/** - * Returns next larger node in the tree - * @param rbtree: tree - * @return: next larger element or NULL if no larger in tree. - */ -rbnode_type *rbtree_next(rbnode_type *rbtree); - -/** - * Returns previous smaller node in the tree - * @param rbtree: tree - * @return: previous smaller element or NULL if no previous in tree. - */ -rbnode_type *rbtree_previous(rbnode_type *rbtree); - -/** - * Call with node=variable of struct* with rbnode_type as first element. - * with type is the type of a pointer to that struct. - */ -#define RBTREE_FOR(node, type, rbtree) \ - for(node=(type)rbtree_first(rbtree); \ - (rbnode_type*)node != RBTREE_NULL; \ - node = (type)rbtree_next((rbnode_type*)node)) - -/** - * Call function for all elements in the redblack tree, such that - * leaf elements are called before parent elements. So that all - * elements can be safely free()d. - * Note that your function must not remove the nodes from the tree. - * Since that may trigger rebalances of the rbtree. - * @param tree: the tree - * @param func: function called with element and user arg. - * The function must not alter the rbtree. - * @param arg: user argument. - */ -void traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*), - void* arg); - -#endif /* UTIL_RBTREE_H_ */ diff --git a/crates/libunbound-sys/unbound/util/regional.c b/crates/libunbound-sys/unbound/util/regional.c deleted file mode 100644 index 44aee68b..00000000 --- a/crates/libunbound-sys/unbound/util/regional.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * regional.c -- region based memory allocator. - * - * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * Regional allocator. Allocates small portions of of larger chunks. - */ - -#include "config.h" -#include "util/log.h" -#include "util/regional.h" - -#ifdef ALIGNMENT -# undef ALIGNMENT -#endif -/** increase size until it fits alignment of s bytes */ -#define ALIGN_UP(x, s) (((x) + s - 1) & (~(s - 1))) -/** what size to align on; make sure a char* fits in it. */ -#define ALIGNMENT (sizeof(uint64_t)) - -/** Default reasonable size for chunks */ -#define REGIONAL_CHUNK_SIZE 8192 -#ifdef UNBOUND_ALLOC_NONREGIONAL -/** All objects allocated outside of chunks, for debug */ -#define REGIONAL_LARGE_OBJECT_SIZE 0 -#else -/** Default size for large objects - allocated outside of chunks. */ -#define REGIONAL_LARGE_OBJECT_SIZE 2048 -#endif - -struct regional* -regional_create(void) -{ - return regional_create_custom(REGIONAL_CHUNK_SIZE); -} - -/** init regional struct with first block */ -static void -regional_init(struct regional* r) -{ - size_t a = ALIGN_UP(sizeof(struct regional), ALIGNMENT); - r->data = (char*)r + a; - r->available = r->first_size - a; - r->next = NULL; - r->large_list = NULL; - r->total_large = 0; -} - -/** - * Create a new region, with custom first block and large-object sizes. - * @param size: length of first block. - * @param large_object_size: outside of chunk allocation threshold. - * @return: newly allocated regional. - */ -static struct regional* -regional_create_custom_large_object(size_t size, size_t large_object_size) -{ - struct regional* r; - size = ALIGN_UP(size, ALIGNMENT); - r = (struct regional*)malloc(size); - log_assert(sizeof(struct regional) <= size); - if(!r) return NULL; - r->first_size = size; - r->large_object_size = large_object_size; - regional_init(r); - return r; -} - -struct regional* -regional_create_custom(size_t size) -{ - if(size < sizeof(struct regional)) - size = sizeof(struct regional); - return regional_create_custom_large_object(size, - REGIONAL_LARGE_OBJECT_SIZE); -} - -struct regional* -regional_create_nochunk(size_t size) -{ - return regional_create_custom_large_object(size, 0); -} - -void -regional_free_all(struct regional *r) -{ - char* p = r->next, *np; - while(p) { - np = *(char**)p; - free(p); - p = np; - } - p = r->large_list; - while(p) { - np = *(char**)p; - free(p); - p = np; - } - regional_init(r); -} - -void -regional_destroy(struct regional *r) -{ - if(!r) return; - regional_free_all(r); - free(r); -} - -void * -regional_alloc(struct regional *r, size_t size) -{ - size_t a; - void *s; - if( -#if SIZEOF_SIZE_T == 8 - (unsigned long long)size >= 0xffffffffffffff00ULL -#else - (unsigned)size >= (unsigned)0xffffff00UL -#endif - ) - return NULL; /* protect against integer overflow in - malloc and ALIGN_UP */ - a = ALIGN_UP(size, ALIGNMENT); - /* large objects */ - if(a > r->large_object_size) { - s = malloc(ALIGNMENT + size); - if(!s) return NULL; - r->total_large += ALIGNMENT+size; - *(char**)s = r->large_list; - r->large_list = (char*)s; - return (char*)s+ALIGNMENT; - } - /* create a new chunk */ - if(a > r->available) { - s = malloc(REGIONAL_CHUNK_SIZE); - if(!s) return NULL; - *(char**)s = r->next; - r->next = (char*)s; - r->data = (char*)s + ALIGNMENT; - r->available = REGIONAL_CHUNK_SIZE - ALIGNMENT; - } - /* put in this chunk */ - r->available -= a; - s = r->data; - r->data += a; - return s; -} - -void * -regional_alloc_init(struct regional* r, const void *init, size_t size) -{ - void *s = regional_alloc(r, size); - if(!s) return NULL; - memmove(s, init, size); - return s; -} - -void * -regional_alloc_zero(struct regional *r, size_t size) -{ - void *s = regional_alloc(r, size); - if(!s) return NULL; - memset(s, 0, size); - return s; -} - -char * -regional_strdup(struct regional *r, const char *string) -{ - return (char*)regional_alloc_init(r, string, strlen(string)+1); -} - -/** - * reasonably slow, but stats and get_mem are not supposed to be fast - * count the number of chunks in use - */ -static size_t -count_chunks(struct regional* r) -{ - size_t c = 1; - char* p = r->next; - while(p) { - c++; - p = *(char**)p; - } - return c; -} - -/** - * also reasonably slow, counts the number of large objects - */ -static size_t -count_large(struct regional* r) -{ - size_t c = 0; - char* p = r->large_list; - while(p) { - c++; - p = *(char**)p; - } - return c; -} - -void -regional_log_stats(struct regional *r) -{ - /* some basic assertions put here (non time critical code) */ - log_assert(ALIGNMENT >= sizeof(char*)); - log_assert(REGIONAL_CHUNK_SIZE > ALIGNMENT); - log_assert(REGIONAL_CHUNK_SIZE-ALIGNMENT > r->large_object_size); - log_assert(REGIONAL_CHUNK_SIZE >= sizeof(struct regional)); - /* debug print */ - log_info("regional %u chunks, %u large", - (unsigned)count_chunks(r), (unsigned)count_large(r)); -} - -size_t -regional_get_mem(struct regional* r) -{ - return r->first_size + (count_chunks(r)-1)*REGIONAL_CHUNK_SIZE - + r->total_large; -} diff --git a/crates/libunbound-sys/unbound/util/regional.h b/crates/libunbound-sys/unbound/util/regional.h deleted file mode 100644 index b439897d..00000000 --- a/crates/libunbound-sys/unbound/util/regional.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * regional.h -- region based memory allocator. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * Regional allocator. Allocates small portions of of larger chunks. - * Based on region-allocator from NSD, but rewritten to be light. - * - * Different from (nsd) region-allocator.h - * o does not have recycle bin - * o does not collect stats; just enough to answer get_mem() in use. - * o does not keep cleanup list - * o does not have function pointers to setup - * o allocs the regional struct inside the first block. - * o can take a block to create regional from. - * o blocks and large allocations are kept on singly linked lists. - */ - -#ifndef UTIL_REGIONAL_H_ -#define UTIL_REGIONAL_H_ - -/** - * the regional* is the first block*. - * every block has a ptr to the next in first bytes. - * and so does the regional struct, which is the first block. - */ -struct regional -{ - /** - * next chunk. NULL if first chunk is the only chunk. - * first inside that chunk is the char* next pointer. - * When regional_free_all() has been called this value is NULL. - */ - char* next; - /** first large object, cast to char** to obtain next ptr */ - char* large_list; - /** total large size */ - size_t total_large; - /** initial chunk size */ - size_t first_size; - /** number of bytes available in the current chunk. */ - size_t available; - /** current chunk data position. */ - char* data; - /** threshold for outside of chunk allocations */ - size_t large_object_size; - /** padding for sizeof8 alignment of sizeof(struct regional) - * for 32bit systems */ - size_t padding; -}; - -/** - * Create a new regional. - * @return: newly allocated regional. - */ -struct regional* regional_create(void); - -/** - * Create a new region, with custom settings. - * @param size: length of first block. - * @return: newly allocated regional. - */ -struct regional* regional_create_custom(size_t size); - -/** - * Create a new region, with custom settings, that will allocate everything - * outside the region chunk. - * @param size: length of first block. - * @return: newly allocated regional. - */ -struct regional* regional_create_nochunk(size_t size); - -/** - * Free all memory associated with regional. Only keeps the first block with - * the regional inside it. - * @param r: the region. - */ -void regional_free_all(struct regional *r); - -/** - * Destroy regional. All memory associated with regional is freed as if - * regional_free_all was called, as well as destroying the regional struct. - * @param r: to delete. - */ -void regional_destroy(struct regional *r); - -/** - * Allocate size bytes of memory inside regional. The memory is - * deallocated when region_free_all is called for this region. - * @param r: the region. - * @param size: number of bytes. - * @return: pointer to memory allocated. - */ -void *regional_alloc(struct regional *r, size_t size); - -/** - * Allocate size bytes of memory inside regional and copy INIT into it. - * The memory is deallocated when region_free_all is called for this - * region. - * @param r: the region. - * @param init: to copy. - * @param size: number of bytes. - * @return: pointer to memory allocated. - */ -void *regional_alloc_init(struct regional* r, const void *init, size_t size); - -/** - * Allocate size bytes of memory inside regional that are initialized to - * 0. The memory is deallocated when region_free_all is called for - * this region. - * @param r: the region. - * @param size: number of bytes. - * @return: pointer to memory allocated. - */ -void *regional_alloc_zero(struct regional *r, size_t size); - -/** - * Duplicate string and allocate the result in regional. - * @param r: the region. - * @param string: null terminated string. - * @return: pointer to memory allocated. - */ -char *regional_strdup(struct regional *r, const char *string); - -/** Debug print regional statistics to log */ -void regional_log_stats(struct regional *r); - -/** get total memory size in use by region */ -size_t regional_get_mem(struct regional* r); - -#endif /* UTIL_REGIONAL_H_ */ diff --git a/crates/libunbound-sys/unbound/util/rfc_1982.c b/crates/libunbound-sys/unbound/util/rfc_1982.c deleted file mode 100644 index c28deded..00000000 --- a/crates/libunbound-sys/unbound/util/rfc_1982.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * util/rfc_1982.c - RFC 1982 Serial Number Arithmetic - * - * Copyright (c) 2023, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for RFC 1982 serial number arithmetic. - */ -#include "config.h" - -int -compare_1982(uint32_t a, uint32_t b) -{ - /* for 32 bit values */ - const uint32_t cutoff = ((uint32_t) 1 << (32 - 1)); - - if (a == b) { - return 0; - } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) { - return -1; - } else { - return 1; - } -} - -uint32_t -subtract_1982(uint32_t a, uint32_t b) -{ - /* for 32 bit values */ - const uint32_t cutoff = ((uint32_t) 1 << (32 - 1)); - - if(a == b) - return 0; - if(a < b && b - a < cutoff) { - return b-a; - } - if(a > b && a - b > cutoff) { - return ((uint32_t)0xffffffff) - (a-b-1); - } - /* wrong case, b smaller than a */ - return 0; -} diff --git a/crates/libunbound-sys/unbound/util/rfc_1982.h b/crates/libunbound-sys/unbound/util/rfc_1982.h deleted file mode 100644 index bae383d0..00000000 --- a/crates/libunbound-sys/unbound/util/rfc_1982.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * util/rfc_1982.h - RFC 1982 Serial Number Arithmetic - * - * Copyright (c) 2023, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for RFC 1982 serial number arithmetic. - */ -#ifndef RFC_1982_H -#define RFC_1982_H - -/** - * RFC 1982 comparison, uses unsigned integers, and tries to avoid - * compiler optimization (eg. by avoiding a-b<0 comparisons). - * @param a: value to compare. - * @param b: value to compare. - * @return 0 if equal, 1 if a > b, else -1. - */ -int compare_1982(uint32_t a, uint32_t b); - -/** - * RFC 1982 subtraction, uses unsigned integers, and tries to avoid - * compiler optimization (eg. by avoiding a-b<0 comparisons). - * @param a: value to subtract from. - * @param b: value to subtract. - * @return the difference between them if we know that b is larger than a, - * that is the distance between them in serial number arithmetic. - */ -uint32_t subtract_1982(uint32_t a, uint32_t b); - -#endif /* RFC_1982_H */ diff --git a/crates/libunbound-sys/unbound/util/rtt.c b/crates/libunbound-sys/unbound/util/rtt.c deleted file mode 100644 index b64206ec..00000000 --- a/crates/libunbound-sys/unbound/util/rtt.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * util/rtt.c - UDP round trip time estimator for resend timeouts. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a data type and functions to help estimate good - * round trip times for UDP resend timeout values. - */ -#include "config.h" -#include "util/rtt.h" -#include "iterator/iterator.h" - -/* overwritten by config: infra_cache_min_rtt: */ -int RTT_MIN_TIMEOUT = 50; -/* overwritten by config: infra_cache_max_rtt: */ -int RTT_MAX_TIMEOUT = 120000; - -/** calculate RTO from rtt information */ -static int -calc_rto(const struct rtt_info* rtt) -{ - /* From Stevens, Unix Network Programming, Vol1, 3rd ed., p.598 */ - int rto = rtt->srtt + 4*rtt->rttvar; - if(rto < RTT_MIN_TIMEOUT) - rto = RTT_MIN_TIMEOUT; - if(rto > RTT_MAX_TIMEOUT) - rto = RTT_MAX_TIMEOUT; - return rto; -} - -void -rtt_init(struct rtt_info* rtt) -{ - rtt->srtt = 0; - rtt->rttvar = UNKNOWN_SERVER_NICENESS/4; - rtt->rto = calc_rto(rtt); - /* default value from the book is 0 + 4*0.75 = 3 seconds */ - /* first RTO is 0 + 4*0.094 = 0.376 seconds */ -} - -int -rtt_timeout(const struct rtt_info* rtt) -{ - return rtt->rto; -} - -int -rtt_unclamped(const struct rtt_info* rtt) -{ - if(calc_rto(rtt) != rtt->rto) { - /* timeout fallback has happened */ - return rtt->rto; - } - /* return unclamped value */ - return rtt->srtt + 4*rtt->rttvar; -} - -void -rtt_update(struct rtt_info* rtt, int ms) -{ - int delta = ms - rtt->srtt; - rtt->srtt += delta / 8; /* g = 1/8 */ - if(delta < 0) - delta = -delta; /* |delta| */ - rtt->rttvar += (delta - rtt->rttvar) / 4; /* h = 1/4 */ - rtt->rto = calc_rto(rtt); -} - -void -rtt_lost(struct rtt_info* rtt, int orig) -{ - /* exponential backoff */ - - /* if a query succeeded and put down the rto meanwhile, ignore this */ - if(rtt->rto < orig) - return; - - /* the original rto is doubled, not the current one to make sure - * that the values in the cache are not increased by lots of - * queries simultaneously as they time out at the same time */ - orig *= 2; - if(rtt->rto <= orig) { - rtt->rto = orig; - if(rtt->rto > RTT_MAX_TIMEOUT) - rtt->rto = RTT_MAX_TIMEOUT; - } -} - -int rtt_notimeout(const struct rtt_info* rtt) -{ - return calc_rto(rtt); -} diff --git a/crates/libunbound-sys/unbound/util/rtt.h b/crates/libunbound-sys/unbound/util/rtt.h deleted file mode 100644 index 63ed8ead..00000000 --- a/crates/libunbound-sys/unbound/util/rtt.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * util/rtt.h - UDP round trip time estimator for resend timeouts. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a data type and functions to help estimate good - * round trip times for UDP resend timeout values. - */ - -#ifndef UTIL_RTT_H -#define UTIL_RTT_H - -/** - * RTT information. Keeps packet Round Trip Time. - */ -struct rtt_info { - /** smoothed rtt estimator, in milliseconds */ - int srtt; - /** smoothed mean deviation, in milliseconds */ - int rttvar; - /** current RTO in use, in milliseconds */ - int rto; -}; - -/** min retransmit timeout value, in milliseconds */ -extern int RTT_MIN_TIMEOUT; -/** max retransmit timeout value, in milliseconds */ -extern int RTT_MAX_TIMEOUT; - -/** - * Initialize RTT estimators. - * @param rtt: The structure. Caller is responsible for allocation of it. - */ -void rtt_init(struct rtt_info* rtt); - -/** - * Get timeout to use for sending a UDP packet. - * @param rtt: round trip statistics structure. - * @return: timeout to use in milliseconds. Relative time value. - */ -int rtt_timeout(const struct rtt_info* rtt); - -/** - * Get unclamped timeout to use for server selection. - * Recent timeouts are reflected in the returned value. - * @param rtt: round trip statistics structure. - * @return: value to use in milliseconds. - */ -int rtt_unclamped(const struct rtt_info* rtt); - -/** - * RTT for valid responses. Without timeouts. - * @param rtt: round trip statistics structure. - * @return: value in msec. - */ -int rtt_notimeout(const struct rtt_info* rtt); - -/** - * Update the statistics with a new roundtrip estimate observation. - * @param rtt: round trip statistics structure. - * @param ms: estimate of roundtrip time in milliseconds. - */ -void rtt_update(struct rtt_info* rtt, int ms); - -/** - * Update the statistics with a new timeout expired observation. - * @param rtt: round trip statistics structure. - * @param orig: original rtt time given for the query that timed out. - * Used to calculate the maximum responsible backed off time that - * can reasonably be applied. - */ -void rtt_lost(struct rtt_info* rtt, int orig); - -#endif /* UTIL_RTT_H */ diff --git a/crates/libunbound-sys/unbound/util/shm_side/shm_main.c b/crates/libunbound-sys/unbound/util/shm_side/shm_main.c deleted file mode 100644 index 6fd1f5ea..00000000 --- a/crates/libunbound-sys/unbound/util/shm_side/shm_main.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * util/shm_side/shm_main.c - SHM for statistics transport - * - * Copyright (c) 2017, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for the SHM implementation. - */ - -#include "config.h" -#include -#include -#ifdef HAVE_SYS_IPC_H -#include -#endif -#ifdef HAVE_SYS_SHM_H -#include -#endif -#include -#include -#include "shm_main.h" -#include "daemon/daemon.h" -#include "daemon/worker.h" -#include "daemon/stats.h" -#include "services/mesh.h" -#include "services/cache/rrset.h" -#include "services/cache/infra.h" -#include "validator/validator.h" -#include "util/config_file.h" -#include "util/fptr_wlist.h" -#include "util/log.h" - -#ifdef HAVE_SHMGET -/** subtract timers and the values do not overflow or become negative */ -static void -stat_timeval_subtract(long long *d_sec, long long *d_usec, const struct timeval* end, - const struct timeval* start) -{ -#ifndef S_SPLINT_S - time_t end_usec = end->tv_usec; - *d_sec = end->tv_sec - start->tv_sec; - if(end_usec < start->tv_usec) { - end_usec += 1000000; - (*d_sec)--; - } - *d_usec = end_usec - start->tv_usec; -#endif -} -#endif /* HAVE_SHMGET */ - -int shm_main_init(struct daemon* daemon) -{ -#ifdef HAVE_SHMGET - struct ub_shm_stat_info *shm_stat; - size_t shm_size; - - /* sanitize */ - if(!daemon) - return 0; - if(!daemon->cfg->shm_enable) - return 1; - if(daemon->cfg->stat_interval == 0) - log_warn("shm-enable is yes but statistics-interval is 0"); - - /* Statistics to maintain the number of thread + total */ - shm_size = (sizeof(struct ub_stats_info) * (daemon->num + 1)); - - /* Allocation of needed memory */ - daemon->shm_info = (struct shm_main_info*)calloc(1, shm_size); - - /* Sanitize */ - if(!daemon->shm_info) { - log_err("shm fail: malloc failure"); - return 0; - } - - daemon->shm_info->key = daemon->cfg->shm_key; - - /* Check for previous create SHM */ - daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(int), SHM_R); - daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, sizeof(int), SHM_R); - - /* Destroy previous SHM */ - if (daemon->shm_info->id_ctl >= 0) - shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL); - - /* Destroy previous SHM */ - if (daemon->shm_info->id_arr >= 0) - shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL); - - /* SHM: Create the segment */ - daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(struct ub_shm_stat_info), IPC_CREAT | 0644); - - if (daemon->shm_info->id_ctl < 0) - { - log_err("SHM failed(id_ctl) cannot shmget(key %d) %s", - daemon->shm_info->key, strerror(errno)); - - /* Just release memory unused */ - free(daemon->shm_info); - daemon->shm_info = NULL; - - return 0; - } - - daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, shm_size, IPC_CREAT | 0644); - - if (daemon->shm_info->id_arr < 0) - { - log_err("SHM failed(id_arr) cannot shmget(key %d + 1) %s", - daemon->shm_info->key, strerror(errno)); - - /* Just release memory unused */ - free(daemon->shm_info); - daemon->shm_info = NULL; - - return 0; - } - - /* SHM: attach the segment */ - daemon->shm_info->ptr_ctl = (struct ub_shm_stat_info*) - shmat(daemon->shm_info->id_ctl, NULL, 0); - if(daemon->shm_info->ptr_ctl == (void *) -1) { - log_err("SHM failed(ctl) cannot shmat(%d) %s", - daemon->shm_info->id_ctl, strerror(errno)); - - /* Just release memory unused */ - free(daemon->shm_info); - daemon->shm_info = NULL; - - return 0; - } - - daemon->shm_info->ptr_arr = (struct ub_stats_info*) - shmat(daemon->shm_info->id_arr, NULL, 0); - - if (daemon->shm_info->ptr_arr == (void *) -1) - { - log_err("SHM failed(arr) cannot shmat(%d) %s", - daemon->shm_info->id_arr, strerror(errno)); - - /* Just release memory unused */ - free(daemon->shm_info); - daemon->shm_info = NULL; - - return 0; - } - - /* Zero fill SHM to stand clean while is not filled by other events */ - memset(daemon->shm_info->ptr_ctl, 0, sizeof(struct ub_shm_stat_info)); - memset(daemon->shm_info->ptr_arr, 0, shm_size); - - shm_stat = daemon->shm_info->ptr_ctl; - shm_stat->num_threads = daemon->num; - -#else - (void)daemon; -#endif /* HAVE_SHMGET */ - return 1; -} - -void shm_main_shutdown(struct daemon* daemon) -{ -#ifdef HAVE_SHMGET - /* web are OK, just disabled */ - if(!daemon->cfg->shm_enable) - return; - - verbose(VERB_DETAIL, "SHM shutdown - KEY [%d] - ID CTL [%d] ARR [%d] - PTR CTL [%p] ARR [%p]", - daemon->shm_info->key, daemon->shm_info->id_ctl, daemon->shm_info->id_arr, daemon->shm_info->ptr_ctl, daemon->shm_info->ptr_arr); - - /* Destroy previous SHM */ - if (daemon->shm_info->id_ctl >= 0) - shmctl(daemon->shm_info->id_ctl, IPC_RMID, NULL); - - if (daemon->shm_info->id_arr >= 0) - shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL); - - if (daemon->shm_info->ptr_ctl) - shmdt(daemon->shm_info->ptr_ctl); - - if (daemon->shm_info->ptr_arr) - shmdt(daemon->shm_info->ptr_arr); - - free(daemon->shm_info); - daemon->shm_info = NULL; -#else - (void)daemon; -#endif /* HAVE_SHMGET */ -} - -void shm_main_run(struct worker *worker) -{ -#ifdef HAVE_SHMGET - struct ub_shm_stat_info *shm_stat; - struct ub_stats_info *stat_total; - struct ub_stats_info *stat_info; - int offset; - -#ifndef S_SPLINT_S - verbose(VERB_DETAIL, "SHM run - worker [%d] - daemon [%p] - timenow(%u) - timeboot(%u)", - worker->thread_num, worker->daemon, (unsigned)worker->env.now_tv->tv_sec, (unsigned)worker->daemon->time_boot.tv_sec); -#endif - - offset = worker->thread_num + 1; - stat_total = worker->daemon->shm_info->ptr_arr; - stat_info = worker->daemon->shm_info->ptr_arr + offset; - - /* Copy data to the current position */ - server_stats_compile(worker, stat_info, 0); - - /* First thread, zero fill total, and copy general info */ - if (worker->thread_num == 0) { - - /* Copy data to the current position */ - memset(stat_total, 0, sizeof(struct ub_stats_info)); - - /* Point to data into SHM */ -#ifndef S_SPLINT_S - shm_stat = worker->daemon->shm_info->ptr_ctl; - shm_stat->time.now_sec = (long long)worker->env.now_tv->tv_sec; - shm_stat->time.now_usec = (long long)worker->env.now_tv->tv_usec; -#endif - - stat_timeval_subtract(&shm_stat->time.up_sec, &shm_stat->time.up_usec, worker->env.now_tv, &worker->daemon->time_boot); - stat_timeval_subtract(&shm_stat->time.elapsed_sec, &shm_stat->time.elapsed_usec, worker->env.now_tv, &worker->daemon->time_last_stat); - - shm_stat->mem.msg = (long long)slabhash_get_mem(worker->env.msg_cache); - shm_stat->mem.rrset = (long long)slabhash_get_mem(&worker->env.rrset_cache->table); - shm_stat->mem.dnscrypt_shared_secret = 0; -#ifdef USE_DNSCRYPT - if(worker->daemon->dnscenv) { - shm_stat->mem.dnscrypt_shared_secret = (long long)slabhash_get_mem( - worker->daemon->dnscenv->shared_secrets_cache); - shm_stat->mem.dnscrypt_nonce = (long long)slabhash_get_mem( - worker->daemon->dnscenv->nonces_cache); - } -#endif - shm_stat->mem.val = (long long)mod_get_mem(&worker->env, - "validator"); - shm_stat->mem.iter = (long long)mod_get_mem(&worker->env, - "iterator"); - shm_stat->mem.respip = (long long)mod_get_mem(&worker->env, - "respip"); - - /* subnet mem value is available in shm, also when not enabled, - * to make the struct easier to memmap by other applications, - * independent of the configuration of unbound */ - shm_stat->mem.subnet = 0; -#ifdef CLIENT_SUBNET - shm_stat->mem.subnet = (long long)mod_get_mem(&worker->env, - "subnetcache"); -#endif - /* ipsecmod mem value is available in shm, also when not enabled, - * to make the struct easier to memmap by other applications, - * independent of the configuration of unbound */ - shm_stat->mem.ipsecmod = 0; -#ifdef USE_IPSECMOD - shm_stat->mem.ipsecmod = (long long)mod_get_mem(&worker->env, - "ipsecmod"); -#endif -#ifdef WITH_DYNLIBMODULE - shm_stat->mem.dynlib = (long long)mod_get_mem(&worker->env, - "dynlib"); -#endif - } - - server_stats_add(stat_total, stat_info); - - /* print the thread statistics */ - stat_total->mesh_time_median /= (double)worker->daemon->num; - -#else - (void)worker; -#endif /* HAVE_SHMGET */ -} diff --git a/crates/libunbound-sys/unbound/util/shm_side/shm_main.h b/crates/libunbound-sys/unbound/util/shm_side/shm_main.h deleted file mode 100644 index 76c60e48..00000000 --- a/crates/libunbound-sys/unbound/util/shm_side/shm_main.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * util/shm_side/shm_main.h - control the shared memory for unbound. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for the SHM side. - */ - -#ifndef UTIL_SHM_SIDE_MAIN_H -#define UTIL_SHM_SIDE_MAIN_H -struct daemon; -struct worker; - -/* get struct ub_shm_stat_info */ -#include "libunbound/unbound.h" - -/** - * The SHM info. - */ -struct shm_main_info { - /** stats_info array, shared memory segment. - * [0] is totals, [1..thread_num] are per-thread stats */ - struct ub_stats_info* ptr_arr; - /** the global stats block, shared memory segment */ - struct ub_shm_stat_info* ptr_ctl; - int key; - int id_ctl; - int id_arr; -}; - -int shm_main_init(struct daemon* daemon); -void shm_main_shutdown(struct daemon* daemon); -void shm_main_run(struct worker *worker); - -#endif /* UTIL_SHM_SIDE_MAIN_H */ diff --git a/crates/libunbound-sys/unbound/util/siphash.c b/crates/libunbound-sys/unbound/util/siphash.c deleted file mode 100644 index 0e1b597d..00000000 --- a/crates/libunbound-sys/unbound/util/siphash.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - SipHash reference C implementation - - Copyright (c) 2012-2016 Jean-Philippe Aumasson - - Copyright (c) 2012-2014 Daniel J. Bernstein - - To the extent possible under law, the author(s) have dedicated all copyright - and related and neighboring rights to this software to the public domain - worldwide. This software is distributed without any warranty. - - You should have received a copy of the CC0 Public Domain Dedication along - with - this software. If not, see - . - */ -/** - * Edited slightly for integration in Unbound. Edits are noted with 'EDIT'. - */ -/** EDIT - * \#include - * \#include - * \#include - * \#include - * Replaced the above includes with Unbound's config.h - */ -#include "config.h" - -/* default: SipHash-2-4 */ -#define cROUNDS 2 -#define dROUNDS 4 - -#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) - -#define U32TO8_LE(p, v) \ - (p)[0] = (uint8_t)((v)); \ - (p)[1] = (uint8_t)((v) >> 8); \ - (p)[2] = (uint8_t)((v) >> 16); \ - (p)[3] = (uint8_t)((v) >> 24); - -#define U64TO8_LE(p, v) \ - U32TO8_LE((p), (uint32_t)((v))); \ - U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); - -#define U8TO64_LE(p) \ - (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ - ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ - ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \ - ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) - -#define SIPROUND \ - do { \ - v0 += v1; \ - v1 = ROTL(v1, 13); \ - v1 ^= v0; \ - v0 = ROTL(v0, 32); \ - v2 += v3; \ - v3 = ROTL(v3, 16); \ - v3 ^= v2; \ - v0 += v3; \ - v3 = ROTL(v3, 21); \ - v3 ^= v0; \ - v2 += v1; \ - v1 = ROTL(v1, 17); \ - v1 ^= v2; \ - v2 = ROTL(v2, 32); \ - } while (0) - -#ifdef DEBUG -#define TRACE \ - do { \ - printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \ - (uint32_t)v0); \ - printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \ - (uint32_t)v1); \ - printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \ - (uint32_t)v2); \ - printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \ - (uint32_t)v3); \ - } while (0) -#else -#define TRACE -#endif - -int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k, - uint8_t *out, const size_t outlen) { - - uint64_t v0 = 0x736f6d6570736575ULL; - uint64_t v1 = 0x646f72616e646f6dULL; - uint64_t v2 = 0x6c7967656e657261ULL; - uint64_t v3 = 0x7465646279746573ULL; - uint64_t k0 = U8TO64_LE(k); - uint64_t k1 = U8TO64_LE(k + 8); - uint64_t m; - int i; - const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t)); - const int left = inlen & 7; - uint64_t b = ((uint64_t)inlen) << 56; - /** EDIT - * The following assert moved here from the top for C90 compliance. - */ - assert((outlen == 8) || (outlen == 16)); - v3 ^= k1; - v2 ^= k0; - v1 ^= k1; - v0 ^= k0; - - if (outlen == 16) - v1 ^= 0xee; - - for (; in != end; in += 8) { - m = U8TO64_LE(in); - v3 ^= m; - - TRACE; - for (i = 0; i < cROUNDS; ++i) - SIPROUND; - - v0 ^= m; - } - - switch (left) { - case 7: - b |= ((uint64_t)in[6]) << 48; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 6: - b |= ((uint64_t)in[5]) << 40; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 5: - b |= ((uint64_t)in[4]) << 32; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 4: - b |= ((uint64_t)in[3]) << 24; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 3: - b |= ((uint64_t)in[2]) << 16; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 2: - b |= ((uint64_t)in[1]) << 8; - /** EDIT annotate case statement fallthrough for gcc */ - /* fallthrough */ - case 1: - b |= ((uint64_t)in[0]); - break; - case 0: - break; - } - - v3 ^= b; - - TRACE; - for (i = 0; i < cROUNDS; ++i) - SIPROUND; - - v0 ^= b; - - if (outlen == 16) - v2 ^= 0xee; - else - v2 ^= 0xff; - - TRACE; - for (i = 0; i < dROUNDS; ++i) - SIPROUND; - - b = v0 ^ v1 ^ v2 ^ v3; - U64TO8_LE(out, b); - - if (outlen == 8) - return 0; - - v1 ^= 0xdd; - - TRACE; - for (i = 0; i < dROUNDS; ++i) - SIPROUND; - - b = v0 ^ v1 ^ v2 ^ v3; - U64TO8_LE(out + 8, b); - - return 0; -} diff --git a/crates/libunbound-sys/unbound/util/siphash.h b/crates/libunbound-sys/unbound/util/siphash.h deleted file mode 100644 index 63da2175..00000000 --- a/crates/libunbound-sys/unbound/util/siphash.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * util/siphash.h - header for SipHash reference C implementation. - * - * Copyright (c) 2023, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Contains the SipHash reference C implementation. - */ -#ifndef UTIL_SIPHASH_H -#define UTIL_SIPHASH_H -int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k, - uint8_t *out, const size_t outlen); -#endif /* UTIL_SIPHASH_H */ diff --git a/crates/libunbound-sys/unbound/util/storage/dnstree.c b/crates/libunbound-sys/unbound/util/storage/dnstree.c deleted file mode 100644 index eef393f9..00000000 --- a/crates/libunbound-sys/unbound/util/storage/dnstree.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * util/storage/dnstree.c - support for rbtree types suitable for DNS code. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains structures combining types and functions to - * manipulate those structures that help building DNS lookup trees. - */ -#include "config.h" -#include "util/storage/dnstree.h" -#include "util/data/dname.h" -#include "util/net_help.h" - -int name_tree_compare(const void* k1, const void* k2) -{ - struct name_tree_node* x = (struct name_tree_node*)k1; - struct name_tree_node* y = (struct name_tree_node*)k2; - int m; - if(x->dclass != y->dclass) { - if(x->dclass < y->dclass) - return -1; - return 1; - } - return dname_lab_cmp(x->name, x->labs, y->name, y->labs, &m); -} - -int addr_tree_compare(const void* k1, const void* k2) -{ - struct addr_tree_node* n1 = (struct addr_tree_node*)k1; - struct addr_tree_node* n2 = (struct addr_tree_node*)k2; - int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr, - n2->addrlen); - if(r != 0) return r; - if(n1->net < n2->net) - return -1; - if(n1->net > n2->net) - return 1; - return 0; -} - -int addr_tree_addrport_compare(const void* k1, const void* k2) -{ - struct addr_tree_node* n1 = (struct addr_tree_node*)k1; - struct addr_tree_node* n2 = (struct addr_tree_node*)k2; - return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, - n2->addrlen); -} - -void name_tree_init(rbtree_type* tree) -{ - rbtree_init(tree, &name_tree_compare); -} - -void addr_tree_init(rbtree_type* tree) -{ - rbtree_init(tree, &addr_tree_compare); -} - -void addr_tree_addrport_init(rbtree_type* tree) -{ - rbtree_init(tree, &addr_tree_addrport_compare); -} - -int name_tree_insert(rbtree_type* tree, struct name_tree_node* node, - uint8_t* name, size_t len, int labs, uint16_t dclass) -{ - node->node.key = node; - node->name = name; - node->len = len; - node->labs = labs; - node->dclass = dclass; - node->parent = NULL; - return rbtree_insert(tree, &node->node) != NULL; -} - -int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node, - struct sockaddr_storage* addr, socklen_t addrlen, int net) -{ - node->node.key = node; - memcpy(&node->addr, addr, addrlen); - node->addrlen = addrlen; - node->net = net; - node->parent = NULL; - return rbtree_insert(tree, &node->node) != NULL; -} - -void addr_tree_init_parents_node(struct addr_tree_node* node) -{ - struct addr_tree_node* prev = NULL, *p; - int m; - for(; (rbnode_type*)node != RBTREE_NULL; - node = (struct addr_tree_node*)rbtree_next((rbnode_type*)node)) { - node->parent = NULL; - if(!prev || prev->addrlen != node->addrlen) { - prev = node; - continue; - } - m = addr_in_common(&prev->addr, prev->net, &node->addr, - node->net, node->addrlen); - /* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - if(p->net <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - -void addr_tree_init_parents(rbtree_type* tree) -{ - addr_tree_init_parents_node( - (struct addr_tree_node*)rbtree_first(tree)); -} - -void name_tree_init_parents(rbtree_type* tree) -{ - struct name_tree_node* node, *prev = NULL, *p; - int m; - RBTREE_FOR(node, struct name_tree_node*, tree) { - node->parent = NULL; - if(!prev || prev->dclass != node->dclass) { - prev = node; - continue; - } - (void)dname_lab_cmp(prev->name, prev->labs, node->name, - node->labs, &m); /* we know prev is smaller */ - /* sort order like: . com. bla.com. zwb.com. net. */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - if(p->labs <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - prev = node; - } -} - -struct name_tree_node* name_tree_find(rbtree_type* tree, uint8_t* name, - size_t len, int labs, uint16_t dclass) -{ - struct name_tree_node key; - key.node.key = &key; - key.name = name; - key.len = len; - key.labs = labs; - key.dclass = dclass; - return (struct name_tree_node*)rbtree_search(tree, &key); -} - -struct name_tree_node* name_tree_lookup(rbtree_type* tree, uint8_t* name, - size_t len, int labs, uint16_t dclass) -{ - rbnode_type* res = NULL; - struct name_tree_node *result; - struct name_tree_node key; - key.node.key = &key; - key.name = name; - key.len = len; - key.labs = labs; - key.dclass = dclass; - if(rbtree_find_less_equal(tree, &key, &res)) { - /* exact */ - result = (struct name_tree_node*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct name_tree_node*)res; - if(!result || result->dclass != dclass) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->labs, key.name, - key.labs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->labs <= m) - break; - result = result->parent; - } - } - return result; -} - -struct addr_tree_node* addr_tree_lookup(rbtree_type* tree, - struct sockaddr_storage* addr, socklen_t addrlen) -{ - rbnode_type* res = NULL; - struct addr_tree_node* result; - struct addr_tree_node key; - key.node.key = &key; - memcpy(&key.addr, addr, addrlen); - key.addrlen = addrlen; - key.net = (addr_is_ip6(addr, addrlen)?128:32); - if(rbtree_find_less_equal(tree, &key, &res)) { - /* exact */ - return (struct addr_tree_node*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct addr_tree_node*)res; - if(!result || result->addrlen != addrlen) - return 0; - /* count number of bits matched */ - m = addr_in_common(&result->addr, result->net, addr, - key.net, addrlen); - while(result) { /* go up until addr is inside netblock */ - if(result->net <= m) - break; - result = result->parent; - } - } - return result; -} - -struct addr_tree_node* addr_tree_find(rbtree_type* tree, - struct sockaddr_storage* addr, socklen_t addrlen, int net) -{ - rbnode_type* res = NULL; - struct addr_tree_node key; - key.node.key = &key; - memcpy(&key.addr, addr, addrlen); - key.addrlen = addrlen; - key.net = net; - res = rbtree_search(tree, &key); - return (struct addr_tree_node*)res; -} - -int -name_tree_next_root(rbtree_type* tree, uint16_t* dclass) -{ - struct name_tree_node key; - rbnode_type* n; - struct name_tree_node* p; - if(*dclass == 0) { - /* first root item is first item in tree */ - n = rbtree_first(tree); - if(n == RBTREE_NULL) - return 0; - p = (struct name_tree_node*)n; - if(dname_is_root(p->name)) { - *dclass = p->dclass; - return 1; - } - /* root not first item? search for higher items */ - *dclass = p->dclass + 1; - return name_tree_next_root(tree, dclass); - } - /* find class n in tree, we may get a direct hit, or if we don't - * this is the last item of the previous class so rbtree_next() takes - * us to the next root (if any) */ - key.node.key = &key; - key.name = (uint8_t*)"\000"; - key.len = 1; - key.labs = 0; - key.dclass = *dclass; - n = NULL; - if(rbtree_find_less_equal(tree, &key, &n)) { - /* exact */ - return 1; - } else { - /* smaller element */ - if(!n || n == RBTREE_NULL) - return 0; /* nothing found */ - n = rbtree_next(n); - if(n == RBTREE_NULL) - return 0; /* no higher */ - p = (struct name_tree_node*)n; - if(dname_is_root(p->name)) { - *dclass = p->dclass; - return 1; - } - /* not a root node, return next higher item */ - *dclass = p->dclass+1; - return name_tree_next_root(tree, dclass); - } -} diff --git a/crates/libunbound-sys/unbound/util/storage/dnstree.h b/crates/libunbound-sys/unbound/util/storage/dnstree.h deleted file mode 100644 index 8aaa9409..00000000 --- a/crates/libunbound-sys/unbound/util/storage/dnstree.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * util/storage/dnstree.h - support for rbtree types suitable for DNS code. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains structures combining types and functions to - * manipulate those structures that help building DNS lookup trees. - */ - -#ifndef UTIL_STORAGE_DNSTREE_H -#define UTIL_STORAGE_DNSTREE_H -#include "util/rbtree.h" - -/** - * Tree of domain names. Sorted first by class then by name. - * This is not sorted canonically, but fast. - * This can be looked up to obtain a closest encloser parent name. - * - * The tree itself is a rbtree_type. - * This is the element node put as first entry in the client structure. - */ -struct name_tree_node { - /** rbtree node, key is this struct : dclass and name */ - rbnode_type node; - /** parent in tree */ - struct name_tree_node* parent; - /** name in uncompressed wireformat */ - uint8_t* name; - /** length of name */ - size_t len; - /** labels in name */ - int labs; - /** the class of the name (host order) */ - uint16_t dclass; -}; - -/** - * Tree of IP addresses. Sorted first by protocol, then by bits. - * This can be looked up to obtain the enclosing subnet. - * - * The tree itself is a rbtree_type. - * This is the element node put as first entry in the client structure. - */ -struct addr_tree_node { - /** rbtree node, key is this struct : proto and subnet */ - rbnode_type node; - /** parent in tree */ - struct addr_tree_node* parent; - /** address */ - struct sockaddr_storage addr; - /** length of addr */ - socklen_t addrlen; - /** netblock size */ - int net; -}; - -/** - * Init a name tree to be empty - * @param tree: to init. - */ -void name_tree_init(rbtree_type* tree); - -/** - * insert element into name tree. - * @param tree: name tree - * @param node: node element (at start of a structure that caller - * has allocated). - * @param name: name to insert (wireformat) - * this node has been allocated by the caller and it itself inserted. - * @param len: length of name - * @param labs: labels in name - * @param dclass: class of name - * @return false on error (duplicate element). - */ -int name_tree_insert(rbtree_type* tree, struct name_tree_node* node, - uint8_t* name, size_t len, int labs, uint16_t dclass); - -/** - * Initialize parent pointers in name tree. - * Should be performed after insertions are done, before lookups - * @param tree: name tree - */ -void name_tree_init_parents(rbtree_type* tree); - -/** - * Lookup exact match in name tree - * @param tree: name tree - * @param name: wireformat name - * @param len: length of name - * @param labs: labels in name - * @param dclass: class of name - * @return node or NULL if not found. - */ -struct name_tree_node* name_tree_find(rbtree_type* tree, uint8_t* name, - size_t len, int labs, uint16_t dclass); - -/** - * Lookup closest encloser in name tree. - * @param tree: name tree - * @param name: wireformat name - * @param len: length of name - * @param labs: labels in name - * @param dclass: class of name - * @return closest enclosing node (could be equal) or NULL if not found. - */ -struct name_tree_node* name_tree_lookup(rbtree_type* tree, uint8_t* name, - size_t len, int labs, uint16_t dclass); - -/** - * Find next root item in name tree. - * @param tree: the nametree. - * @param dclass: the class to look for next (or higher). - * @return false if no classes found, true means class put into c. - */ -int name_tree_next_root(rbtree_type* tree, uint16_t* dclass); - -/** - * Init addr tree to be empty. - * @param tree: to init. - */ -void addr_tree_init(rbtree_type* tree); - -/** - * Init addr tree to be empty. - * The comparison function to be used is addr_tree_addrport_compare. - * @param tree: to init. - */ -void addr_tree_addrport_init(rbtree_type* tree); - -/** - * insert element into addr tree. - * @param tree: addr tree - * @param node: node element (at start of a structure that caller - * has allocated). - * @param addr: to insert (copied). - * @param addrlen: length of addr - * @param net: size of subnet. - * @return false on error (duplicate element). - */ -int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node, - struct sockaddr_storage* addr, socklen_t addrlen, int net); - -/** - * Initialize parent pointers in addr tree. - * Should be performed after insertions are done, before lookups - * @param tree: addr tree - */ -void addr_tree_init_parents(rbtree_type* tree); - -/** - * Initialize parent pointers in partial addr tree. - * Reinitialize pointer for part of tree, used after node deletion - * @param node: node to start parent pointer initialization for. - */ -void addr_tree_init_parents_node(struct addr_tree_node* node); - -/** - * Lookup closest encloser in addr tree. - * @param tree: addr tree - * @param addr: to lookup. - * @param addrlen: length of addr - * @return closest enclosing node (could be equal) or NULL if not found. - */ -struct addr_tree_node* addr_tree_lookup(rbtree_type* tree, - struct sockaddr_storage* addr, socklen_t addrlen); - -/** - * Find element in addr tree. (search a netblock, not a match for an address) - * @param tree: addr tree - * @param addr: netblock to lookup. - * @param addrlen: length of addr - * @param net: size of subnet - * @return addr tree element, or NULL if not found. - */ -struct addr_tree_node* addr_tree_find(rbtree_type* tree, - struct sockaddr_storage* addr, socklen_t addrlen, int net); - -/** compare name tree nodes */ -int name_tree_compare(const void* k1, const void* k2); - -/** compare addr tree nodes */ -int addr_tree_compare(const void* k1, const void* k2); - -/** compare addr tree nodes (address and port only) */ -int addr_tree_addrport_compare(const void* k1, const void* k2); - -#endif /* UTIL_STORAGE_DNSTREE_H */ diff --git a/crates/libunbound-sys/unbound/util/storage/lookup3.c b/crates/libunbound-sys/unbound/util/storage/lookup3.c deleted file mode 100644 index c4026626..00000000 --- a/crates/libunbound-sys/unbound/util/storage/lookup3.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* - May 2019(Wouter) patch to enable the valgrind clean implementation all the - time. This enables better security audit and checks, which is better - than the speedup. Git issue #30. Renamed the define ARRAY_CLEAN_ACCESS. - February 2013(Wouter) patch defines for BSD endianness, from Brad Smith. - January 2012(Wouter) added randomised initial value, fallout from 28c3. - March 2007(Wouter) adapted from lookup3.c original, add config.h include. - added #ifdef VALGRIND to remove 298,384,660 'unused variable k8' warnings. - added include of lookup3.h to check definitions match declarations. - removed include of stdint - config.h takes care of platform independence. - added fallthrough comments for new gcc warning suppression. - url http://burtleburtle.net/bob/hash/index.html. -*/ -/* -------------------------------------------------------------------------------- -lookup3.c, by Bob Jenkins, May 2006, Public Domain. - -These are functions for producing 32-bit hashes for hash table lookup. -hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() -are externally useful functions. Routines to test the hash are included -if SELF_TEST is defined. You can use this free for any purpose. It's in -the public domain. It has no warranty. - -You probably want to use hashlittle(). hashlittle() and hashbig() -hash byte arrays. hashlittle() is is faster than hashbig() on -little-endian machines. Intel and AMD are little-endian machines. -On second thought, you probably want hashlittle2(), which is identical to -hashlittle() except it returns two 32-bit hashes for the price of one. -You could implement hashbig2() if you wanted but I haven't bothered here. - -If you want to find a hash of, say, exactly 7 integers, do - a = i1; b = i2; c = i3; - mix(a,b,c); - a += i4; b += i5; c += i6; - mix(a,b,c); - a += i7; - final(a,b,c); -then use c as the hash value. If you have a variable length array of -4-byte integers to hash, use hashword(). If you have a byte array (like -a character string), use hashlittle(). If you have several byte arrays, or -a mix of things, see the comments above hashlittle(). - -Why is this so big? I read 12 bytes at a time into 3 4-byte integers, -then mix those integers. This is fast (you can do a lot more thorough -mixing with 12*3 instructions on 3 integers than you can with 3 instructions -on 1 byte), but shoehorning those bytes into integers efficiently is messy. -------------------------------------------------------------------------------- -*/ -/*#define SELF_TEST 1*/ -#define ARRAY_CLEAN_ACCESS 1 - -#include "config.h" -#include "util/storage/lookup3.h" -#include /* defines printf for tests */ -#include /* defines time_t for timings in the test */ - -/* - * If our build system provides endianness info, signalled by - * HAVE_TARGET_ENDIANNESS and the presence or absence of TARGET_IS_BIG_ENDIAN, - * use that. Otherwise try to work out the endianness. - */ -#if defined(HAVE_TARGET_ENDIANNESS) -# if defined(TARGET_IS_BIG_ENDIAN) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -# else -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -# endif -#else -# include /* attempt to define endianness */ -# ifdef HAVE_SYS_TYPES_H -# include /* attempt to define endianness (solaris) */ -# endif -# if defined(linux) || defined(__OpenBSD__) -# ifdef HAVE_ENDIAN_H -# include /* attempt to define endianness */ -# else -# include /* on older OpenBSD */ -# endif -# endif -# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# include /* attempt to define endianness */ -# endif - /* - * My best guess at if you are big-endian or little-endian. This may - * need adjustment. - */ -# if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL) || defined(__x86)) -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -# elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(sparc) || defined(__sparc) || defined(__sparc__) || defined(POWERPC) || defined(mc68000) || defined(sel)) -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -# elif defined(_MACHINE_ENDIAN_H_) - /* test for machine_endian_h protects failure if some are empty strings */ -# if defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && _BYTE_ORDER == _BIG_ENDIAN -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 1 -# endif -# if defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && _BYTE_ORDER == _LITTLE_ENDIAN -# define HASH_LITTLE_ENDIAN 1 -# define HASH_BIG_ENDIAN 0 -# endif /* _MACHINE_ENDIAN_H_ */ -# else -# define HASH_LITTLE_ENDIAN 0 -# define HASH_BIG_ENDIAN 0 -# endif -#endif /* defined(HAVE_TARGET_ENDIANNESS) */ - -#define hashsize(n) ((uint32_t)1<<(n)) -#define hashmask(n) (hashsize(n)-1) -#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) - -/* random initial value */ -static uint32_t raninit = (uint32_t)0xdeadbeef; - -void -hash_set_raninit(uint32_t v) -{ - raninit = v; -} - -/* -------------------------------------------------------------------------------- -mix -- mix 3 32-bit values reversibly. - -This is reversible, so any information in (a,b,c) before mix() is -still in (a,b,c) after mix(). - -If four pairs of (a,b,c) inputs are run through mix(), or through -mix() in reverse, there are at least 32 bits of the output that -are sometimes the same for one pair and different for another pair. -This was tested for: -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that -satisfy this are - 4 6 8 16 19 4 - 9 15 3 18 27 15 - 14 9 3 7 17 3 -Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing -for "differ" defined as + with a one-bit base and a two-bit delta. I -used http://burtleburtle.net/bob/hash/avalanche.html to choose -the operations, constants, and arrangements of the variables. - -This does not achieve avalanche. There are input bits of (a,b,c) -that fail to affect some output bits of (a,b,c), especially of a. The -most thoroughly mixed value is c, but it doesn't really even achieve -avalanche in c. - -This allows some parallelism. Read-after-writes are good at doubling -the number of bits affected, so the goal of mixing pulls in the opposite -direction as the goal of parallelism. I did what I could. Rotates -seem to cost as much as shifts on every machine I could lay my hands -on, and rotates are much kinder to the top and bottom bits, so I used -rotates. -------------------------------------------------------------------------------- -*/ -#define mix(a,b,c) \ -{ \ - a -= c; a ^= rot(c, 4); c += b; \ - b -= a; b ^= rot(a, 6); a += c; \ - c -= b; c ^= rot(b, 8); b += a; \ - a -= c; a ^= rot(c,16); c += b; \ - b -= a; b ^= rot(a,19); a += c; \ - c -= b; c ^= rot(b, 4); b += a; \ -} - -/* -------------------------------------------------------------------------------- -final -- final mixing of 3 32-bit values (a,b,c) into c - -Pairs of (a,b,c) values differing in only a few bits will usually -produce values of c that look totally different. This was tested for -* pairs that differed by one bit, by two bits, in any combination - of top bits of (a,b,c), or in any combination of bottom bits of - (a,b,c). -* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed - the output delta to a Gray code (a^(a>>1)) so a string of 1's (as - is commonly produced by subtraction) look like a single 1-bit - difference. -* the base values were pseudorandom, all zero but one bit set, or - all zero plus a counter that starts at zero. - -These constants passed: - 14 11 25 16 4 14 24 - 12 14 25 16 4 14 24 -and these came close: - 4 8 15 26 3 22 24 - 10 8 15 26 3 22 24 - 11 8 15 26 3 22 24 -------------------------------------------------------------------------------- -*/ -#define final(a,b,c) \ -{ \ - c ^= b; c -= rot(b,14); \ - a ^= c; a -= rot(c,11); \ - b ^= a; b -= rot(a,25); \ - c ^= b; c -= rot(b,16); \ - a ^= c; a -= rot(c,4); \ - b ^= a; b -= rot(a,14); \ - c ^= b; c -= rot(b,24); \ -} - -/* --------------------------------------------------------------------- - This works on all machines. To be useful, it requires - -- that the key be an array of uint32_t's, and - -- that the length be the number of uint32_t's in the key - - The function hashword() is identical to hashlittle() on little-endian - machines, and identical to hashbig() on big-endian machines, - except that the length has to be measured in uint32_ts rather than in - bytes. hashlittle() is more complicated than hashword() only because - hashlittle() has to dance around fitting the key bytes into registers. --------------------------------------------------------------------- -*/ -uint32_t hashword( -const uint32_t *k, /* the key, an array of uint32_t values */ -size_t length, /* the length of the key, in uint32_ts */ -uint32_t initval) /* the previous hash, or an arbitrary value */ -{ - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = raninit + (((uint32_t)length)<<2) + initval; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - /* fallthrough */ - case 2 : b+=k[1]; - /* fallthrough */ - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - return c; -} - - -#ifdef SELF_TEST - -/* --------------------------------------------------------------------- -hashword2() -- same as hashword(), but take two seeds and return two -32-bit values. pc and pb must both be nonnull, and *pc and *pb must -both be initialized with seeds. If you pass in (*pb)==0, the output -(*pc) will be the same as the return value from hashword(). --------------------------------------------------------------------- -*/ -void hashword2 ( -const uint32_t *k, /* the key, an array of uint32_t values */ -size_t length, /* the length of the key, in uint32_ts */ -uint32_t *pc, /* IN: seed OUT: primary hash value */ -uint32_t *pb) /* IN: more seed OUT: secondary hash value */ -{ - uint32_t a,b,c; - - /* Set up the internal state */ - a = b = c = raninit + ((uint32_t)(length<<2)) + *pc; - c += *pb; - - /*------------------------------------------------- handle most of the key */ - while (length > 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 3; - k += 3; - } - - /*------------------------------------------- handle the last 3 uint32_t's */ - switch(length) /* all the case statements fall through */ - { - case 3 : c+=k[2]; - case 2 : b+=k[1]; - case 1 : a+=k[0]; - final(a,b,c); - case 0: /* case 0: nothing left to add */ - break; - } - /*------------------------------------------------------ report the result */ - *pc=c; *pb=b; -} - -#endif /* SELF_TEST */ - -/* -------------------------------------------------------------------------------- -hashlittle() -- hash a variable-length key into a 32-bit value - k : the key (the unaligned variable-length array of bytes) - length : the length of the key, counting by bytes - initval : can be any 4-byte value -Returns a 32-bit value. Every bit of the key affects every bit of -the return value. Two keys differing by one or two bits will have -totally different hash values. - -The best hash table sizes are powers of 2. There is no need to do -mod a prime (mod is sooo slow!). If you need less than 32 bits, -use a bitmask. For example, if you need only 10 bits, do - h = (h & hashmask(10)); -In which case, the hash table should have hashsize(10) elements. - -If you are hashing n strings (uint8_t **)k, do it like this: - for (i=0, h=0; i 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, but - * then masks off the part it's not allowed to read. Because the - * string is aligned, the masked-off tail is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticeably faster for short strings (like English words). - */ -#ifndef ARRAY_CLEAN_ACCESS - - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : return c; /* zero length strings require no mixing */ - } - -#else /* make valgrind happy */ - - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : return c; - } - -#endif /* !valgrind */ - - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; - - /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); - length -= 12; - k += 6; - } - - /*----------------------------- handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : return c; /* zero length requires no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; - b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; - c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=((uint32_t)k[11])<<24; - /* fallthrough */ - case 11: c+=((uint32_t)k[10])<<16; - /* fallthrough */ - case 10: c+=((uint32_t)k[9])<<8; - /* fallthrough */ - case 9 : c+=k[8]; - /* fallthrough */ - case 8 : b+=((uint32_t)k[7])<<24; - /* fallthrough */ - case 7 : b+=((uint32_t)k[6])<<16; - /* fallthrough */ - case 6 : b+=((uint32_t)k[5])<<8; - /* fallthrough */ - case 5 : b+=k[4]; - /* fallthrough */ - case 4 : a+=((uint32_t)k[3])<<24; - /* fallthrough */ - case 3 : a+=((uint32_t)k[2])<<16; - /* fallthrough */ - case 2 : a+=((uint32_t)k[1])<<8; - /* fallthrough */ - case 1 : a+=k[0]; - break; - case 0 : return c; - } - } - - final(a,b,c); - return c; -} - -#ifdef SELF_TEST - -/* - * hashlittle2: return 2 32-bit hash values - * - * This is identical to hashlittle(), except it returns two 32-bit hash - * values instead of just one. This is good enough for hash table - * lookup with 2^^64 buckets, or if you want a second hash if you're not - * happy with the first, or if you want a probably-unique 64-bit ID for - * the key. *pc is better mixed than *pb, so use *pc first. If you want - * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". - */ -void hashlittle2( - const void *key, /* the key to hash */ - size_t length, /* length of the key */ - uint32_t *pc, /* IN: primary initval, OUT: primary hash */ - uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ -{ - uint32_t a,b,c; /* internal state */ - union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ - - /* Set up the internal state */ - a = b = c = raninit + ((uint32_t)length) + *pc; - c += *pb; - - u.ptr = key; - if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ -#ifdef VALGRIND - const uint8_t *k8; -#endif - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]&0xffffff" actually reads beyond the end of the string, but - * then masks off the part it's not allowed to read. Because the - * string is aligned, the masked-off tail is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticeably faster for short strings (like English words). - */ -#ifndef VALGRIND - - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff; a+=k[0]; break; - case 6 : b+=k[1]&0xffff; a+=k[0]; break; - case 5 : b+=k[1]&0xff; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff; break; - case 2 : a+=k[0]&0xffff; break; - case 1 : a+=k[0]&0xff; break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - -#else /* make valgrind happy */ - - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ - case 1 : a+=k8[0]; break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - -#endif /* !valgrind */ - - } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { - const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ - const uint8_t *k8; - - /*--------------- all but last block: aligned reads and different mixing */ - while (length > 12) - { - a += k[0] + (((uint32_t)k[1])<<16); - b += k[2] + (((uint32_t)k[3])<<16); - c += k[4] + (((uint32_t)k[5])<<16); - mix(a,b,c); - length -= 12; - k += 6; - } - - /*----------------------------- handle the last (probably partial) block */ - k8 = (const uint8_t *)k; - switch(length) - { - case 12: c+=k[4]+(((uint32_t)k[5])<<16); - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ - case 10: c+=k[4]; - b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 9 : c+=k8[8]; /* fall through */ - case 8 : b+=k[2]+(((uint32_t)k[3])<<16); - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ - case 6 : b+=k[2]; - a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 5 : b+=k8[4]; /* fall through */ - case 4 : a+=k[0]+(((uint32_t)k[1])<<16); - break; - case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ - case 2 : a+=k[0]; - break; - case 1 : a+=k8[0]; - break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - a += ((uint32_t)k[1])<<8; - a += ((uint32_t)k[2])<<16; - a += ((uint32_t)k[3])<<24; - b += k[4]; - b += ((uint32_t)k[5])<<8; - b += ((uint32_t)k[6])<<16; - b += ((uint32_t)k[7])<<24; - c += k[8]; - c += ((uint32_t)k[9])<<8; - c += ((uint32_t)k[10])<<16; - c += ((uint32_t)k[11])<<24; - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=((uint32_t)k[11])<<24; - case 11: c+=((uint32_t)k[10])<<16; - case 10: c+=((uint32_t)k[9])<<8; - case 9 : c+=k[8]; - case 8 : b+=((uint32_t)k[7])<<24; - case 7 : b+=((uint32_t)k[6])<<16; - case 6 : b+=((uint32_t)k[5])<<8; - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3])<<24; - case 3 : a+=((uint32_t)k[2])<<16; - case 2 : a+=((uint32_t)k[1])<<8; - case 1 : a+=k[0]; - break; - case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ - } - } - - final(a,b,c); - *pc=c; *pb=b; -} - -#endif /* SELF_TEST */ - -#if 0 /* currently not used */ - -/* - * hashbig(): - * This is the same as hashword() on big-endian machines. It is different - * from hashlittle() on all machines. hashbig() takes advantage of - * big-endian byte ordering. - */ -uint32_t hashbig( const void *key, size_t length, uint32_t initval) -{ - uint32_t a,b,c; - union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ - - /* Set up the internal state */ - a = b = c = raninit + ((uint32_t)length) + initval; - - u.ptr = key; - if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { - const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ -#ifdef VALGRIND - const uint8_t *k8; -#endif - - /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ - while (length > 12) - { - a += k[0]; - b += k[1]; - c += k[2]; - mix(a,b,c); - length -= 12; - k += 3; - } - - /*----------------------------- handle the last (probably partial) block */ - /* - * "k[2]<<8" actually reads beyond the end of the string, but - * then shifts out the part it's not allowed to read. Because the - * string is aligned, the illegal read is in the same word as the - * rest of the string. Every machine with memory protection I've seen - * does it on word boundaries, so is OK with this. But VALGRIND will - * still catch it and complain. The masking trick does make the hash - * noticeably faster for short strings (like English words). - */ -#ifndef VALGRIND - - switch(length) - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; - case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; - case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; - case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; - case 5 : b+=k[1]&0xff000000; a+=k[0]; break; - case 4 : a+=k[0]; break; - case 3 : a+=k[0]&0xffffff00; break; - case 2 : a+=k[0]&0xffff0000; break; - case 1 : a+=k[0]&0xff000000; break; - case 0 : return c; /* zero length strings require no mixing */ - } - -#else /* make valgrind happy */ - - k8 = (const uint8_t *)k; - switch(length) /* all the case statements fall through */ - { - case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; - case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ - case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ - case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ - case 8 : b+=k[1]; a+=k[0]; break; - case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ - case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ - case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ - case 4 : a+=k[0]; break; - case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ - case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ - case 1 : a+=((uint32_t)k8[0])<<24; break; - case 0 : return c; - } - -#endif /* !VALGRIND */ - - } else { /* need to read the key one byte at a time */ - const uint8_t *k = (const uint8_t *)key; - - /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ - while (length > 12) - { - a += ((uint32_t)k[0])<<24; - a += ((uint32_t)k[1])<<16; - a += ((uint32_t)k[2])<<8; - a += ((uint32_t)k[3]); - b += ((uint32_t)k[4])<<24; - b += ((uint32_t)k[5])<<16; - b += ((uint32_t)k[6])<<8; - b += ((uint32_t)k[7]); - c += ((uint32_t)k[8])<<24; - c += ((uint32_t)k[9])<<16; - c += ((uint32_t)k[10])<<8; - c += ((uint32_t)k[11]); - mix(a,b,c); - length -= 12; - k += 12; - } - - /*-------------------------------- last block: affect all 32 bits of (c) */ - switch(length) /* all the case statements fall through */ - { - case 12: c+=k[11]; - case 11: c+=((uint32_t)k[10])<<8; - case 10: c+=((uint32_t)k[9])<<16; - case 9 : c+=((uint32_t)k[8])<<24; - case 8 : b+=k[7]; - case 7 : b+=((uint32_t)k[6])<<8; - case 6 : b+=((uint32_t)k[5])<<16; - case 5 : b+=((uint32_t)k[4])<<24; - case 4 : a+=k[3]; - case 3 : a+=((uint32_t)k[2])<<8; - case 2 : a+=((uint32_t)k[1])<<16; - case 1 : a+=((uint32_t)k[0])<<24; - break; - case 0 : return c; - } - } - - final(a,b,c); - return c; -} - -#endif /* 0 == currently not used */ - -#ifdef SELF_TEST - -/* used for timings */ -void driver1(void) -{ - uint8_t buf[256]; - uint32_t i; - uint32_t h=0; - time_t a,z; - - time(&a); - for (i=0; i<256; ++i) buf[i] = 'x'; - for (i=0; i<1; ++i) - { - h = hashlittle(&buf[0],1,h); - } - time(&z); - if (z-a > 0) printf("time %d %.8x\n", z-a, h); -} - -/* check that every input bit changes every output bit half the time */ -#define HASHSTATE 1 -#define HASHLEN 1 -#define MAXPAIR 60 -#define MAXLEN 70 -void driver2(void) -{ - uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; - uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; - uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; - uint32_t x[HASHSTATE],y[HASHSTATE]; - uint32_t hlen; - - printf("No more than %d trials should ever be needed \n",MAXPAIR/2); - for (hlen=0; hlen < MAXLEN; ++hlen) - { - z=0; - for (i=0; i>(8-j)); - c[0] = hashlittle(a, hlen, m); - b[i] ^= ((k+1)<>(8-j)); - d[0] = hashlittle(b, hlen, m); - /* check every bit is 1, 0, set, and not set at least once */ - for (l=0; lz) z=k; - if (k==MAXPAIR) - { - printf("Some bit didn't change: "); - printf("%.8x %.8x %.8x %.8x %.8x %.8x ", - e[0],f[0],g[0],h[0],x[0],y[0]); - printf("i %d j %d m %d len %d\n", i, j, m, hlen); - } - if (z==MAXPAIR) goto done; - } - } - } - done: - if (z < MAXPAIR) - { - printf("Mix success %2d bytes %2d initvals ",i,m); - printf("required %d trials\n", z/2); - } - } - printf("\n"); -} - -/* Check for reading beyond the end of the buffer and alignment problems */ -void driver3(void) -{ - uint8_t buf[MAXLEN+20], *b; - uint32_t len; - uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; - uint32_t h; - uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; - uint32_t i; - uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; - uint32_t j; - uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; - uint32_t ref,x,y; - uint8_t *p; - - printf("Endianness. These lines should all be the same (for values filled in):\n"); - printf("%.8x %.8x %.8x\n", - hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), - hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), - hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); - p = q; - printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", - hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), - hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), - hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), - hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), - hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), - hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); - p = &qq[1]; - printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", - hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), - hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), - hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), - hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), - hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), - hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); - p = &qqq[2]; - printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", - hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), - hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), - hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), - hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), - hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), - hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); - p = &qqqq[3]; - printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", - hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), - hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), - hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), - hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), - hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), - hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); - printf("\n"); - - /* check that hashlittle2 and hashlittle produce the same results */ - i=47; j=0; - hashlittle2(q, sizeof(q), &i, &j); - if (hashlittle(q, sizeof(q), 47) != i) - printf("hashlittle2 and hashlittle mismatch\n"); - - /* check that hashword2 and hashword produce the same results */ - len = raninit; - i=47, j=0; - hashword2(&len, 1, &i, &j); - if (hashword(&len, 1, 47) != i) - printf("hashword2 and hashword mismatch %x %x\n", - i, hashword(&len, 1, 47)); - - /* check hashlittle doesn't read before or after the ends of the string */ - for (h=0, b=buf+1; h<8; ++h, ++b) - { - for (i=0; ilock); - table->sizefunc = sizefunc; - table->compfunc = compfunc; - table->delkeyfunc = delkeyfunc; - table->deldatafunc = deldatafunc; - table->cb_arg = arg; - table->size = start_size; - table->size_mask = (int)(start_size-1); - table->lru_start = NULL; - table->lru_end = NULL; - table->num = 0; - table->space_used = 0; - table->space_max = maxmem; - table->max_collisions = 0; - table->array = calloc(table->size, sizeof(struct lruhash_bin)); - if(!table->array) { - lock_quick_destroy(&table->lock); - free(table); - return NULL; - } - bin_init(table->array, table->size); - lock_protect(&table->lock, table, sizeof(*table)); - lock_protect(&table->lock, table->array, - table->size*sizeof(struct lruhash_bin)); - return table; -} - -void -bin_delete(struct lruhash* table, struct lruhash_bin* bin) -{ - struct lruhash_entry* p, *np; - void *d; - if(!bin) - return; - lock_quick_destroy(&bin->lock); - p = bin->overflow_list; - bin->overflow_list = NULL; - while(p) { - np = p->overflow_next; - d = p->data; - (*table->delkeyfunc)(p->key, table->cb_arg); - (*table->deldatafunc)(d, table->cb_arg); - p = np; - } -} - -void -bin_split(struct lruhash* table, struct lruhash_bin* newa, - int newmask) -{ - size_t i; - struct lruhash_entry *p, *np; - struct lruhash_bin* newbin; - /* move entries to new table. Notice that since hash x is mapped to - * bin x & mask, and new mask uses one more bit, so all entries in - * one bin will go into the old bin or bin | newbit */ -#ifndef THREADS_DISABLED - int newbit = newmask - table->size_mask; -#endif - /* so, really, this task could also be threaded, per bin. */ - /* LRU list is not changed */ - for(i=0; isize; i++) - { - lock_quick_lock(&table->array[i].lock); - p = table->array[i].overflow_list; - /* lock both destination bins */ - lock_quick_lock(&newa[i].lock); - lock_quick_lock(&newa[newbit|i].lock); - while(p) { - np = p->overflow_next; - /* link into correct new bin */ - newbin = &newa[p->hash & newmask]; - p->overflow_next = newbin->overflow_list; - newbin->overflow_list = p; - p=np; - } - lock_quick_unlock(&newa[i].lock); - lock_quick_unlock(&newa[newbit|i].lock); - lock_quick_unlock(&table->array[i].lock); - } -} - -void -lruhash_delete(struct lruhash* table) -{ - size_t i; - if(!table) - return; - /* delete lock on hashtable to force check its OK */ - lock_quick_destroy(&table->lock); - for(i=0; isize; i++) - bin_delete(table, &table->array[i]); - free(table->array); - free(table); -} - -void -bin_overflow_remove(struct lruhash_bin* bin, struct lruhash_entry* entry) -{ - struct lruhash_entry* p = bin->overflow_list; - struct lruhash_entry** prevp = &bin->overflow_list; - while(p) { - if(p == entry) { - *prevp = p->overflow_next; - return; - } - prevp = &p->overflow_next; - p = p->overflow_next; - } -} - -void -reclaim_space(struct lruhash* table, struct lruhash_entry** list) -{ - struct lruhash_entry* d; - struct lruhash_bin* bin; - log_assert(table); - /* does not delete MRU entry, so table will not be empty. */ - while(table->num > 1 && table->space_used > table->space_max) { - /* notice that since we hold the hashtable lock, nobody - can change the lru chain. So it cannot be deleted underneath - us. We still need the hashbin and entry write lock to make - sure we flush all users away from the entry. - which is unlikely, since it is LRU, if someone got a rdlock - it would be moved to front, but to be sure. */ - d = table->lru_end; - /* specialised, delete from end of double linked list, - and we know num>1, so there is a previous lru entry. */ - log_assert(d && d->lru_prev); - table->lru_end = d->lru_prev; - d->lru_prev->lru_next = NULL; - /* schedule entry for deletion */ - bin = &table->array[d->hash & table->size_mask]; - table->num --; - lock_quick_lock(&bin->lock); - bin_overflow_remove(bin, d); - d->overflow_next = *list; - *list = d; - lock_rw_wrlock(&d->lock); - table->space_used -= table->sizefunc(d->key, d->data); - if(table->markdelfunc) - (*table->markdelfunc)(d->key); - lock_rw_unlock(&d->lock); - lock_quick_unlock(&bin->lock); - } -} - -struct lruhash_entry* -bin_find_entry(struct lruhash* table, - struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions) -{ - size_t c = 0; - struct lruhash_entry* p = bin->overflow_list; - while(p) { - if(p->hash == hash && table->compfunc(p->key, key) == 0) - break; - c++; - p = p->overflow_next; - } - if (collisions != NULL) - *collisions = c; - return p; -} - -void -table_grow(struct lruhash* table) -{ - struct lruhash_bin* newa; - int newmask; - size_t i; - if(table->size_mask == (int)(((size_t)-1)>>1)) { - log_err("hash array malloc: size_t too small"); - return; - } - /* try to allocate new array, if not fail */ - newa = calloc(table->size*2, sizeof(struct lruhash_bin)); - if(!newa) { - log_err("hash grow: malloc failed"); - /* continue with smaller array. Though its slower. */ - return; - } - bin_init(newa, table->size*2); - newmask = (table->size_mask << 1) | 1; - bin_split(table, newa, newmask); - /* delete the old bins */ - lock_unprotect(&table->lock, table->array); - for(i=0; isize; i++) { - lock_quick_destroy(&table->array[i].lock); - } - free(table->array); - - table->size *= 2; - table->size_mask = newmask; - table->array = newa; - lock_protect(&table->lock, table->array, - table->size*sizeof(struct lruhash_bin)); - return; -} - -void -lru_front(struct lruhash* table, struct lruhash_entry* entry) -{ - entry->lru_prev = NULL; - entry->lru_next = table->lru_start; - if(!table->lru_start) - table->lru_end = entry; - else table->lru_start->lru_prev = entry; - table->lru_start = entry; -} - -void -lru_remove(struct lruhash* table, struct lruhash_entry* entry) -{ - if(entry->lru_prev) - entry->lru_prev->lru_next = entry->lru_next; - else table->lru_start = entry->lru_next; - if(entry->lru_next) - entry->lru_next->lru_prev = entry->lru_prev; - else table->lru_end = entry->lru_prev; -} - -void -lru_touch(struct lruhash* table, struct lruhash_entry* entry) -{ - log_assert(table && entry); - if(entry == table->lru_start) - return; /* nothing to do */ - /* remove from current lru position */ - lru_remove(table, entry); - /* add at front */ - lru_front(table, entry); -} - -void -lruhash_insert(struct lruhash* table, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* cb_arg) -{ - struct lruhash_bin* bin; - struct lruhash_entry* found, *reclaimlist=NULL; - size_t need_size; - size_t collisions; - fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); - fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); - fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); - fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); - fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); - need_size = table->sizefunc(entry->key, data); - if(cb_arg == NULL) cb_arg = table->cb_arg; - - /* find bin */ - lock_quick_lock(&table->lock); - bin = &table->array[hash & table->size_mask]; - lock_quick_lock(&bin->lock); - - /* see if entry exists already */ - if(!(found=bin_find_entry(table, bin, hash, entry->key, &collisions))) { - /* if not: add to bin */ - entry->overflow_next = bin->overflow_list; - bin->overflow_list = entry; - lru_front(table, entry); - table->num++; - if (table->max_collisions < collisions) - table->max_collisions = collisions; - table->space_used += need_size; - } else { - /* if so: update data - needs a writelock */ - table->space_used += need_size - - (*table->sizefunc)(found->key, found->data); - (*table->delkeyfunc)(entry->key, cb_arg); - lru_touch(table, found); - lock_rw_wrlock(&found->lock); - (*table->deldatafunc)(found->data, cb_arg); - found->data = data; - lock_rw_unlock(&found->lock); - } - lock_quick_unlock(&bin->lock); - if(table->space_used > table->space_max) - reclaim_space(table, &reclaimlist); - if(table->num >= table->size) - table_grow(table); - lock_quick_unlock(&table->lock); - - /* finish reclaim if any (outside of critical region) */ - while(reclaimlist) { - struct lruhash_entry* n = reclaimlist->overflow_next; - void* d = reclaimlist->data; - (*table->delkeyfunc)(reclaimlist->key, cb_arg); - (*table->deldatafunc)(d, cb_arg); - reclaimlist = n; - } -} - -struct lruhash_entry* -lruhash_lookup(struct lruhash* table, hashvalue_type hash, void* key, int wr) -{ - struct lruhash_entry* entry; - struct lruhash_bin* bin; - fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); - - lock_quick_lock(&table->lock); - bin = &table->array[hash & table->size_mask]; - lock_quick_lock(&bin->lock); - if((entry=bin_find_entry(table, bin, hash, key, NULL))) - lru_touch(table, entry); - lock_quick_unlock(&table->lock); - - if(entry) { - if(wr) { lock_rw_wrlock(&entry->lock); } - else { lock_rw_rdlock(&entry->lock); } - } - lock_quick_unlock(&bin->lock); - return entry; -} - -void -lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key) -{ - struct lruhash_entry* entry; - struct lruhash_bin* bin; - void *d; - fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); - fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); - fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); - fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); - fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); - - lock_quick_lock(&table->lock); - bin = &table->array[hash & table->size_mask]; - lock_quick_lock(&bin->lock); - if((entry=bin_find_entry(table, bin, hash, key, NULL))) { - bin_overflow_remove(bin, entry); - lru_remove(table, entry); - } else { - lock_quick_unlock(&table->lock); - lock_quick_unlock(&bin->lock); - return; - } - table->num--; - table->space_used -= (*table->sizefunc)(entry->key, entry->data); - lock_rw_wrlock(&entry->lock); - if(table->markdelfunc) - (*table->markdelfunc)(entry->key); - lock_rw_unlock(&entry->lock); - lock_quick_unlock(&bin->lock); - lock_quick_unlock(&table->lock); - /* finish removal */ - d = entry->data; - (*table->delkeyfunc)(entry->key, table->cb_arg); - (*table->deldatafunc)(d, table->cb_arg); -} - -/** clear bin, respecting locks, does not do space, LRU */ -static void -bin_clear(struct lruhash* table, struct lruhash_bin* bin) -{ - struct lruhash_entry* p, *np; - void *d; - lock_quick_lock(&bin->lock); - p = bin->overflow_list; - while(p) { - lock_rw_wrlock(&p->lock); - np = p->overflow_next; - d = p->data; - if(table->markdelfunc) - (*table->markdelfunc)(p->key); - lock_rw_unlock(&p->lock); - (*table->delkeyfunc)(p->key, table->cb_arg); - (*table->deldatafunc)(d, table->cb_arg); - p = np; - } - bin->overflow_list = NULL; - lock_quick_unlock(&bin->lock); -} - -void -lruhash_clear(struct lruhash* table) -{ - size_t i; - if(!table) - return; - fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); - fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); - fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); - - lock_quick_lock(&table->lock); - for(i=0; isize; i++) { - bin_clear(table, &table->array[i]); - } - table->lru_start = NULL; - table->lru_end = NULL; - table->num = 0; - table->space_used = 0; - lock_quick_unlock(&table->lock); -} - -void -lruhash_status(struct lruhash* table, const char* id, int extended) -{ - lock_quick_lock(&table->lock); - log_info("%s: %u entries, memory %u / %u", - id, (unsigned)table->num, (unsigned)table->space_used, - (unsigned)table->space_max); - log_info(" itemsize %u, array %u, mask %d", - (unsigned)(table->num? table->space_used/table->num : 0), - (unsigned)table->size, table->size_mask); - if(extended) { - size_t i; - int min=(int)table->size*2, max=-2; - for(i=0; isize; i++) { - int here = 0; - struct lruhash_entry *en; - lock_quick_lock(&table->array[i].lock); - en = table->array[i].overflow_list; - while(en) { - here ++; - en = en->overflow_next; - } - lock_quick_unlock(&table->array[i].lock); - if(extended >= 2) - log_info("bin[%d] %d", (int)i, here); - if(here > max) max = here; - if(here < min) min = here; - } - log_info(" bin min %d, avg %.2lf, max %d", min, - (double)table->num/(double)table->size, max); - } - lock_quick_unlock(&table->lock); -} - -size_t -lruhash_get_mem(struct lruhash* table) -{ - size_t s; - lock_quick_lock(&table->lock); - s = sizeof(struct lruhash) + table->space_used; -#ifdef USE_THREAD_DEBUG - if(table->size != 0) { - size_t i; - for(i=0; isize; i++) - s += sizeof(struct lruhash_bin) + - lock_get_mem(&table->array[i].lock); - } -#else /* no THREAD_DEBUG */ - if(table->size != 0) - s += (table->size)*(sizeof(struct lruhash_bin) + - lock_get_mem(&table->array[0].lock)); -#endif - lock_quick_unlock(&table->lock); - s += lock_get_mem(&table->lock); - return s; -} - -void -lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md) -{ - lock_quick_lock(&table->lock); - table->markdelfunc = md; - lock_quick_unlock(&table->lock); -} - -void -lruhash_traverse(struct lruhash* h, int wr, - void (*func)(struct lruhash_entry*, void*), void* arg) -{ - size_t i; - struct lruhash_entry* e; - - lock_quick_lock(&h->lock); - for(i=0; isize; i++) { - lock_quick_lock(&h->array[i].lock); - for(e = h->array[i].overflow_list; e; e = e->overflow_next) { - if(wr) { - lock_rw_wrlock(&e->lock); - } else { - lock_rw_rdlock(&e->lock); - } - (*func)(e, arg); - lock_rw_unlock(&e->lock); - } - lock_quick_unlock(&h->array[i].lock); - } - lock_quick_unlock(&h->lock); -} - -/* - * Demote: the opposite of touch, move an entry to the bottom - * of the LRU pile. - */ - -void -lru_demote(struct lruhash* table, struct lruhash_entry* entry) -{ - log_assert(table && entry); - if (entry == table->lru_end) - return; /* nothing to do */ - /* remove from current lru position */ - lru_remove(table, entry); - /* add at end */ - entry->lru_next = NULL; - entry->lru_prev = table->lru_end; - - if (table->lru_end == NULL) - { - table->lru_start = entry; - } - else - { - table->lru_end->lru_next = entry; - } - table->lru_end = entry; -} - -struct lruhash_entry* -lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* cb_arg) -{ - struct lruhash_bin* bin; - struct lruhash_entry* found, *reclaimlist = NULL; - size_t need_size; - size_t collisions; - fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); - fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); - fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); - fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); - fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); - need_size = table->sizefunc(entry->key, data); - if (cb_arg == NULL) cb_arg = table->cb_arg; - - /* find bin */ - lock_quick_lock(&table->lock); - bin = &table->array[hash & table->size_mask]; - lock_quick_lock(&bin->lock); - - /* see if entry exists already */ - if ((found = bin_find_entry(table, bin, hash, entry->key, &collisions)) != NULL) { - /* if so: keep the existing data - acquire a writelock */ - lock_rw_wrlock(&found->lock); - } - else - { - /* if not: add to bin */ - entry->overflow_next = bin->overflow_list; - bin->overflow_list = entry; - lru_front(table, entry); - table->num++; - if (table->max_collisions < collisions) - table->max_collisions = collisions; - table->space_used += need_size; - /* return the entry that was presented, and lock it */ - found = entry; - lock_rw_wrlock(&found->lock); - } - lock_quick_unlock(&bin->lock); - if (table->space_used > table->space_max) - reclaim_space(table, &reclaimlist); - if (table->num >= table->size) - table_grow(table); - lock_quick_unlock(&table->lock); - - /* finish reclaim if any (outside of critical region) */ - while (reclaimlist) { - struct lruhash_entry* n = reclaimlist->overflow_next; - void* d = reclaimlist->data; - (*table->delkeyfunc)(reclaimlist->key, cb_arg); - (*table->deldatafunc)(d, cb_arg); - reclaimlist = n; - } - - /* return the entry that was selected */ - return found; -} - diff --git a/crates/libunbound-sys/unbound/util/storage/lruhash.h b/crates/libunbound-sys/unbound/util/storage/lruhash.h deleted file mode 100644 index 2086e4de..00000000 --- a/crates/libunbound-sys/unbound/util/storage/lruhash.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * util/storage/lruhash.h - hashtable, hash function, LRU keeping. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a hashtable with LRU keeping of entries. - * - * The hash table keeps a maximum memory size. Old entries are removed - * to make space for new entries. - * - * The locking strategy is as follows: - * o since (almost) every read also implies a LRU update, the - * hashtable lock is a spinlock, not rwlock. - * o the idea is to move every thread through the hash lock quickly, - * so that the next thread can access the lookup table. - * o User performs hash function. - * - * For read: - * o lock hashtable. - * o lookup hash bin. - * o lock hash bin. - * o find entry (if failed, unlock hash, unl bin, exit). - * o swizzle pointers for LRU update. - * o unlock hashtable. - * o lock entry (rwlock). - * o unlock hash bin. - * o work on entry. - * o unlock entry. - * - * To update an entry, gain writelock and change the entry. - * (the entry must keep the same hashvalue, so a data update.) - * (you cannot upgrade a readlock to a writelock, because the item may - * be deleted, it would cause race conditions. So instead, unlock and - * relookup it in the hashtable.) - * - * To delete an entry: - * o unlock the entry if you hold the lock already. - * o lock hashtable. - * o lookup hash bin. - * o lock hash bin. - * o find entry (if failed, unlock hash, unl bin, exit). - * o remove entry from hashtable bin overflow chain. - * o unlock hashtable. - * o lock entry (writelock). - * o unlock hash bin. - * o unlock entry (nobody else should be waiting for this lock, - * since you removed it from hashtable, and you got writelock while - * holding the hashbinlock so you are the only one.) - * Note you are only allowed to obtain a lock while holding hashbinlock. - * o delete entry. - * - * The above sequence is: - * o race free, works with read, write and delete. - * o but has a queue, imagine someone needing a writelock on an item. - * but there are still readlocks. The writelocker waits, but holds - * the hashbinlock. The next thread that comes in and needs the same - * hashbin will wait for the lock while holding the hashtable lock. - * thus halting the entire system on hashtable. - * This is because of the delete protection. - * Readlocks will be easier on the rwlock on entries. - * While the writer is holding writelock, similar problems happen with - * a reader or writer needing the same item. - * the scenario requires more than three threads. - * o so the queue length is 3 threads in a bad situation. The fourth is - * unable to use the hashtable. - * - * If you need to acquire locks on multiple items from the hashtable. - * o you MUST release all locks on items from the hashtable before - * doing the next lookup/insert/delete/whatever. - * o To acquire multiple items you should use a special routine that - * obtains the locks on those multiple items in one go. - */ - -#ifndef UTIL_STORAGE_LRUHASH_H -#define UTIL_STORAGE_LRUHASH_H -#include "util/locks.h" -struct lruhash_bin; -struct lruhash_entry; - -/** default start size for hash arrays */ -#define HASH_DEFAULT_STARTARRAY 1024 /* entries in array */ -/** default max memory for hash arrays */ -#define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */ - -/** the type of a hash value */ -typedef uint32_t hashvalue_type; - -/** - * Type of function that calculates the size of an entry. - * Result must include the size of struct lruhash_entry. - * Keys that are identical must also calculate to the same size. - * size = func(key, data). - */ -typedef size_t (*lruhash_sizefunc_type)(void*, void*); - -/** type of function that compares two keys. return 0 if equal. */ -typedef int (*lruhash_compfunc_type)(void*, void*); - -/** old keys are deleted. - * The RRset type has to revoke its ID number, markdel() is used first. - * This function is called: func(key, userarg) */ -typedef void (*lruhash_delkeyfunc_type)(void*, void*); - -/** old data is deleted. This function is called: func(data, userarg). */ -typedef void (*lruhash_deldatafunc_type)(void*, void*); - -/** mark a key as pending to be deleted (and not to be used by anyone). - * called: func(key) */ -typedef void (*lruhash_markdelfunc_type)(void*); - -/** - * Hash table that keeps LRU list of entries. - */ -struct lruhash { - /** lock for exclusive access, to the lookup array */ - lock_quick_type lock; - /** the size function for entries in this table */ - lruhash_sizefunc_type sizefunc; - /** the compare function for entries in this table. */ - lruhash_compfunc_type compfunc; - /** how to delete keys. */ - lruhash_delkeyfunc_type delkeyfunc; - /** how to delete data. */ - lruhash_deldatafunc_type deldatafunc; - /** how to mark a key pending deletion */ - lruhash_markdelfunc_type markdelfunc; - /** user argument for user functions */ - void* cb_arg; - - /** the size of the lookup array */ - size_t size; - /** size bitmask - since size is a power of 2 */ - int size_mask; - /** lookup array of bins */ - struct lruhash_bin* array; - - /** the lru list, start and end, noncyclical double linked list. */ - struct lruhash_entry* lru_start; - /** lru list end item (least recently used) */ - struct lruhash_entry* lru_end; - - /** the number of entries in the hash table. */ - size_t num; - /** the amount of space used, roughly the number of bytes in use. */ - size_t space_used; - /** the amount of space the hash table is maximally allowed to use. */ - size_t space_max; - /** the maximum collisions were detected during the lruhash_insert operations. */ - size_t max_collisions; -}; - -/** - * A single bin with a linked list of entries in it. - */ -struct lruhash_bin { - /** - * Lock for exclusive access to the linked list - * This lock makes deletion of items safe in this overflow list. - */ - lock_quick_type lock; - /** linked list of overflow entries */ - struct lruhash_entry* overflow_list; -}; - -/** - * An entry into the hash table. - * To change overflow_next you need to hold the bin lock. - * To change the lru items you need to hold the hashtable lock. - * This structure is designed as part of key struct. And key pointer helps - * to get the surrounding structure. Data should be allocated on its own. - */ -struct lruhash_entry { - /** - * rwlock for access to the contents of the entry - * Note that it does _not_ cover the lru_ and overflow_ ptrs. - * Even with a writelock, you cannot change hash and key. - * You need to delete it to change hash or key. - */ - lock_rw_type lock; - /** next entry in overflow chain. Covered by hashlock and binlock. */ - struct lruhash_entry* overflow_next; - /** next entry in lru chain. covered by hashlock. */ - struct lruhash_entry* lru_next; - /** prev entry in lru chain. covered by hashlock. */ - struct lruhash_entry* lru_prev; - /** hash value of the key. It may not change, until entry deleted. */ - hashvalue_type hash; - /** key */ - void* key; - /** data */ - void* data; -}; - -/** - * Create new hash table. - * @param start_size: size of hashtable array at start, must be power of 2. - * @param maxmem: maximum amount of memory this table is allowed to use. - * @param sizefunc: calculates memory usage of entries. - * @param compfunc: compares entries, 0 on equality. - * @param delkeyfunc: deletes key. - * Calling both delkey and deldata will also free the struct lruhash_entry. - * Make it part of the key structure and delete it in delkeyfunc. - * @param deldatafunc: deletes data. - * @param arg: user argument that is passed to user function calls. - * @return: new hash table or NULL on malloc failure. - */ -struct lruhash* lruhash_create(size_t start_size, size_t maxmem, - lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc, - lruhash_delkeyfunc_type delkeyfunc, - lruhash_deldatafunc_type deldatafunc, void* arg); - -/** - * Delete hash table. Entries are all deleted. - * @param table: to delete. - */ -void lruhash_delete(struct lruhash* table); - -/** - * Clear hash table. Entries are all deleted, while locking them before - * doing so. At end the table is empty. - * @param table: to make empty. - */ -void lruhash_clear(struct lruhash* table); - -/** - * Insert a new element into the hashtable. - * If key is already present data pointer in that entry is updated. - * The space calculation function is called with the key, data. - * If necessary the least recently used entries are deleted to make space. - * If necessary the hash array is grown up. - * - * @param table: hash table. - * @param hash: hash value. User calculates the hash. - * @param entry: identifies the entry. - * If key already present, this entry->key is deleted immediately. - * But entry->data is set to NULL before deletion, and put into - * the existing entry. The data is then freed. - * @param data: the data. - * @param cb_override: if not null overrides the cb_arg for the deletefunc. - */ -void lruhash_insert(struct lruhash* table, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* cb_override); - -/** - * Lookup an entry in the hashtable. - * At the end of the function you hold a (read/write)lock on the entry. - * The LRU is updated for the entry (if found). - * @param table: hash table. - * @param hash: hash of key. - * @param key: what to look for, compared against entries in overflow chain. - * the hash value must be set, and must work with compare function. - * @param wr: set to true if you desire a writelock on the entry. - * with a writelock you can update the data part. - * @return: pointer to the entry or NULL. The entry is locked. - * The user must unlock the entry when done. - */ -struct lruhash_entry* lruhash_lookup(struct lruhash* table, - hashvalue_type hash, void* key, int wr); - -/** - * Touch entry, so it becomes the most recently used in the LRU list. - * Caller must hold hash table lock. The entry must be inserted already. - * @param table: hash table. - * @param entry: entry to make first in LRU. - */ -void lru_touch(struct lruhash* table, struct lruhash_entry* entry); - -/** - * Set the markdelfunction (or NULL) - */ -void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md); - -/************************* getdns functions ************************/ -/*** these are used by getdns only and not by unbound. ***/ - -/** - * Demote entry, so it becomes the least recently used in the LRU list. - * Caller must hold hash table lock. The entry must be inserted already. - * @param table: hash table. - * @param entry: entry to make last in LRU. - */ -void lru_demote(struct lruhash* table, struct lruhash_entry* entry); - -/** - * Insert a new element into the hashtable, or retrieve the corresponding - * element of it exits. - * - * If key is already present data pointer in that entry is kept. - * If it is not present, a new entry is created. In that case, - * the space calculation function is called with the key, data. - * If necessary the least recently used entries are deleted to make space. - * If necessary the hash array is grown up. - * - * @param table: hash table. - * @param hash: hash value. User calculates the hash. - * @param entry: identifies the entry. - * @param data: the data. - * @param cb_arg: if not null overrides the cb_arg for the deletefunc. - * @return: pointer to the existing entry if the key was already present, - * or to the entry argument if it was not. - */ -struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* cb_arg); - -/************************* Internal functions ************************/ -/*** these are only exposed for unit tests. ***/ - -/** - * Remove entry from hashtable. Does nothing if not found in hashtable. - * Delfunc is called for the entry. - * @param table: hash table. - * @param hash: hash of key. - * @param key: what to look for. - */ -void lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key); - -/** init the hash bins for the table */ -void bin_init(struct lruhash_bin* array, size_t size); - -/** delete the hash bin and entries inside it */ -void bin_delete(struct lruhash* table, struct lruhash_bin* bin); - -/** - * Find entry in hash bin. You must have locked the bin. - * @param table: hash table with function pointers. - * @param bin: hash bin to look into. - * @param hash: hash value to look for. - * @param key: key to look for. - * @param collisions: how many collisions were found during the search. - * @return: the entry or NULL if not found. - */ -struct lruhash_entry* bin_find_entry(struct lruhash* table, - struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions); - -/** - * Remove entry from bin overflow chain. - * You must have locked the bin. - * @param bin: hash bin to look into. - * @param entry: entry ptr that needs removal. - */ -void bin_overflow_remove(struct lruhash_bin* bin, - struct lruhash_entry* entry); - -/** - * Split hash bin into two new ones. Based on increased size_mask. - * Caller must hold hash table lock. - * At the end the routine acquires all hashbin locks (in the old array). - * This makes it wait for other threads to finish with the bins. - * So the bins are ready to be deleted after this function. - * @param table: hash table with function pointers. - * @param newa: new increased array. - * @param newmask: new lookup mask. - */ -void bin_split(struct lruhash* table, struct lruhash_bin* newa, - int newmask); - -/** - * Try to make space available by deleting old entries. - * Assumes that the lock on the hashtable is being held by caller. - * Caller must not hold bin locks. - * @param table: hash table. - * @param list: list of entries that are to be deleted later. - * Entries have been removed from the hash table and writelock is held. - */ -void reclaim_space(struct lruhash* table, struct lruhash_entry** list); - -/** - * Grow the table lookup array. Becomes twice as large. - * Caller must hold the hash table lock. Must not hold any bin locks. - * Tries to grow, on malloc failure, nothing happened. - * @param table: hash table. - */ -void table_grow(struct lruhash* table); - -/** - * Put entry at front of lru. entry must be unlinked from lru. - * Caller must hold hash table lock. - * @param table: hash table with lru head and tail. - * @param entry: entry to make most recently used. - */ -void lru_front(struct lruhash* table, struct lruhash_entry* entry); - -/** - * Remove entry from lru list. - * Caller must hold hash table lock. - * @param table: hash table with lru head and tail. - * @param entry: entry to remove from lru. - */ -void lru_remove(struct lruhash* table, struct lruhash_entry* entry); - -/** - * Output debug info to the log as to state of the hash table. - * @param table: hash table. - * @param id: string printed with table to identify the hash table. - * @param extended: set to true to print statistics on overflow bin lengths. - */ -void lruhash_status(struct lruhash* table, const char* id, int extended); - -/** - * Get memory in use now by the lruhash table. - * @param table: hash table. Will be locked before use. And unlocked after. - * @return size in bytes. - */ -size_t lruhash_get_mem(struct lruhash* table); - -/** - * Traverse a lruhash. Call back for every element in the table. - * @param h: hash table. Locked before use. - * @param wr: if true writelock is obtained on element, otherwise readlock. - * @param func: function for every element. Do not lock or unlock elements. - * @param arg: user argument to func. - */ -void lruhash_traverse(struct lruhash* h, int wr, - void (*func)(struct lruhash_entry*, void*), void* arg); - -#endif /* UTIL_STORAGE_LRUHASH_H */ diff --git a/crates/libunbound-sys/unbound/util/storage/slabhash.c b/crates/libunbound-sys/unbound/util/storage/slabhash.c deleted file mode 100644 index 7d376c4d..00000000 --- a/crates/libunbound-sys/unbound/util/storage/slabhash.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * util/storage/slabhash.c - hashtable consisting of several smaller tables. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * Implementation of hash table that consists of smaller hash tables. - * This results in a partitioned lruhash table. - * It cannot grow, but that gives it the ability to have multiple - * locks. Also this means there are multiple LRU lists. - */ - -#include "config.h" -#include "util/storage/slabhash.h" - -struct slabhash* slabhash_create(size_t numtables, size_t start_size, - size_t maxmem, lruhash_sizefunc_type sizefunc, - lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc, - lruhash_deldatafunc_type deldatafunc, void* arg) -{ - size_t i; - struct slabhash* sl = (struct slabhash*)calloc(1, - sizeof(struct slabhash)); - if(!sl) return NULL; - sl->size = numtables; - log_assert(sl->size > 0); - sl->array = (struct lruhash**)calloc(sl->size, sizeof(struct lruhash*)); - if(!sl->array) { - free(sl); - return NULL; - } - sl->mask = (uint32_t)(sl->size - 1); - if(sl->mask == 0) { - sl->shift = 0; - } else { - log_assert( (sl->size & sl->mask) == 0 - /* size must be power of 2 */ ); - sl->shift = 0; - while(!(sl->mask & 0x80000000)) { - sl->mask <<= 1; - sl->shift ++; - } - } - for(i=0; isize; i++) { - sl->array[i] = lruhash_create(start_size, maxmem / sl->size, - sizefunc, compfunc, delkeyfunc, deldatafunc, arg); - if(!sl->array[i]) { - slabhash_delete(sl); - return NULL; - } - } - return sl; -} - -void slabhash_delete(struct slabhash* sl) -{ - if(!sl) - return; - if(sl->array) { - size_t i; - for(i=0; isize; i++) - lruhash_delete(sl->array[i]); - free(sl->array); - } - free(sl); -} - -void slabhash_clear(struct slabhash* sl) -{ - size_t i; - if(!sl) - return; - for(i=0; isize; i++) - lruhash_clear(sl->array[i]); -} - -/** helper routine to calculate the slabhash index */ -static unsigned int -slab_idx(struct slabhash* sl, hashvalue_type hash) -{ - return ((hash & sl->mask) >> sl->shift); -} - -void slabhash_insert(struct slabhash* sl, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* arg) -{ - lruhash_insert(sl->array[slab_idx(sl, hash)], hash, entry, data, arg); -} - -struct lruhash_entry* slabhash_lookup(struct slabhash* sl, - hashvalue_type hash, void* key, int wr) -{ - return lruhash_lookup(sl->array[slab_idx(sl, hash)], hash, key, wr); -} - -void slabhash_remove(struct slabhash* sl, hashvalue_type hash, void* key) -{ - lruhash_remove(sl->array[slab_idx(sl, hash)], hash, key); -} - -void slabhash_status(struct slabhash* sl, const char* id, int extended) -{ - size_t i; - char num[17]; - log_info("Slabhash %s: %u tables mask=%x shift=%d", - id, (unsigned)sl->size, (unsigned)sl->mask, sl->shift); - for(i=0; isize; i++) { - snprintf(num, sizeof(num), "table %u", (unsigned)i); - lruhash_status(sl->array[i], num, extended); - } -} - -size_t slabhash_get_size(struct slabhash* sl) -{ - size_t i, total = 0; - for(i=0; isize; i++) { - lock_quick_lock(&sl->array[i]->lock); - total += sl->array[i]->space_max; - lock_quick_unlock(&sl->array[i]->lock); - } - return total; -} - -int slabhash_is_size(struct slabhash* sl, size_t size, size_t slabs) -{ - /* divide by slabs and then multiply by the number of slabs, - * because if the size is not an even multiple of slabs, the - * uneven amount needs to be removed for comparison */ - if(!sl) return 0; - if(sl->size != slabs) return 0; - if(slabs == 0) return 0; - if( (size/slabs)*slabs == slabhash_get_size(sl)) - return 1; - return 0; -} - -size_t slabhash_get_mem(struct slabhash* sl) -{ - size_t i, total = sizeof(*sl); - total += sizeof(struct lruhash*)*sl->size; - for(i=0; isize; i++) { - total += lruhash_get_mem(sl->array[i]); - } - return total; -} - -struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_type hash) -{ - return sl->array[slab_idx(sl, hash)]; -} - -/* test code, here to avoid linking problems with fptr_wlist */ -/** delete key */ -static void delkey(struct slabhash_testkey* k) { - lock_rw_destroy(&k->entry.lock); free(k);} -/** delete data */ -static void deldata(struct slabhash_testdata* d) {free(d);} - -size_t test_slabhash_sizefunc(void* ATTR_UNUSED(key), void* ATTR_UNUSED(data)) -{ - return sizeof(struct slabhash_testkey) + - sizeof(struct slabhash_testdata); -} - -int test_slabhash_compfunc(void* key1, void* key2) -{ - struct slabhash_testkey* k1 = (struct slabhash_testkey*)key1; - struct slabhash_testkey* k2 = (struct slabhash_testkey*)key2; - if(k1->id == k2->id) - return 0; - if(k1->id > k2->id) - return 1; - return -1; -} - -void test_slabhash_delkey(void* key, void* ATTR_UNUSED(arg)) -{ - delkey((struct slabhash_testkey*)key); -} - -void test_slabhash_deldata(void* data, void* ATTR_UNUSED(arg)) -{ - deldata((struct slabhash_testdata*)data); -} - -void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_type md) -{ - size_t i; - for(i=0; isize; i++) { - lruhash_setmarkdel(sl->array[i], md); - } -} - -void slabhash_traverse(struct slabhash* sh, int wr, - void (*func)(struct lruhash_entry*, void*), void* arg) -{ - size_t i; - for(i=0; isize; i++) - lruhash_traverse(sh->array[i], wr, func, arg); -} - -size_t count_slabhash_entries(struct slabhash* sh) -{ - size_t slab, cnt = 0; - - for(slab=0; slabsize; slab++) { - lock_quick_lock(&sh->array[slab]->lock); - cnt += sh->array[slab]->num; - lock_quick_unlock(&sh->array[slab]->lock); - } - return cnt; -} - -void get_slabhash_stats(struct slabhash* sh, long long* num, long long* collisions) -{ - size_t slab, cnt = 0, max_collisions = 0; - - for(slab=0; slabsize; slab++) { - lock_quick_lock(&sh->array[slab]->lock); - cnt += sh->array[slab]->num; - if (max_collisions < sh->array[slab]->max_collisions) { - max_collisions = sh->array[slab]->max_collisions; - } - lock_quick_unlock(&sh->array[slab]->lock); - } - if (num != NULL) - *num = cnt; - if (collisions != NULL) - *collisions = max_collisions; -} diff --git a/crates/libunbound-sys/unbound/util/storage/slabhash.h b/crates/libunbound-sys/unbound/util/storage/slabhash.h deleted file mode 100644 index dc5fc360..00000000 --- a/crates/libunbound-sys/unbound/util/storage/slabhash.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * util/storage/slabhash.h - hashtable consisting of several smaller tables. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * Hash table that consists of smaller hash tables. - * It cannot grow, but that gives it the ability to have multiple - * locks. Also this means there are multiple LRU lists. - */ - -#ifndef UTIL_STORAGE_SLABHASH_H -#define UTIL_STORAGE_SLABHASH_H -#include "util/storage/lruhash.h" - -/** default number of slabs */ -#define HASH_DEFAULT_SLABS 4 - -/** - * Hash table formed from several smaller ones. - * This results in a partitioned lruhash table, a 'slashtable'. - * None of the data inside the slabhash may be altered. - * Therefore, no locks are needed to access the structure. - */ -struct slabhash { - /** the size of the array - must be power of 2 */ - size_t size; - /** size bitmask - uses high bits. */ - uint32_t mask; - /** shift right this many bits to get index into array. */ - unsigned int shift; - /** lookup array of hash tables */ - struct lruhash** array; -}; - -/** - * Create new slabbed hash table. - * @param numtables: number of hash tables to use, other parameters used to - * initialize these smaller hashtables. - * @param start_size: size of hashtable array at start, must be power of 2. - * @param maxmem: maximum amount of memory this table is allowed to use. - * so every table gets maxmem/numtables to use for itself. - * @param sizefunc: calculates memory usage of entries. - * @param compfunc: compares entries, 0 on equality. - * @param delkeyfunc: deletes key. - * @param deldatafunc: deletes data. - * @param arg: user argument that is passed to user function calls. - * @return: new hash table or NULL on malloc failure. - */ -struct slabhash* slabhash_create(size_t numtables, size_t start_size, - size_t maxmem, lruhash_sizefunc_type sizefunc, - lruhash_compfunc_type compfunc, lruhash_delkeyfunc_type delkeyfunc, - lruhash_deldatafunc_type deldatafunc, void* arg); - -/** - * Delete hash table. Entries are all deleted. - * @param table: to delete. - */ -void slabhash_delete(struct slabhash* table); - -/** - * Clear hash table. Entries are all deleted. - * @param table: to make empty. - */ -void slabhash_clear(struct slabhash* table); - -/** - * Insert a new element into the hashtable, uses lruhash_insert. - * If key is already present data pointer in that entry is updated. - * - * @param table: hash table. - * @param hash: hash value. User calculates the hash. - * @param entry: identifies the entry. - * If key already present, this entry->key is deleted immediately. - * But entry->data is set to NULL before deletion, and put into - * the existing entry. The data is then freed. - * @param data: the data. - * @param cb_override: if not NULL overrides the cb_arg for deletefunc. - */ -void slabhash_insert(struct slabhash* table, hashvalue_type hash, - struct lruhash_entry* entry, void* data, void* cb_override); - -/** - * Lookup an entry in the hashtable. Uses lruhash_lookup. - * At the end of the function you hold a (read/write)lock on the entry. - * The LRU is updated for the entry (if found). - * @param table: hash table. - * @param hash: hash of key. - * @param key: what to look for, compared against entries in overflow chain. - * the hash value must be set, and must work with compare function. - * @param wr: set to true if you desire a writelock on the entry. - * with a writelock you can update the data part. - * @return: pointer to the entry or NULL. The entry is locked. - * The user must unlock the entry when done. - */ -struct lruhash_entry* slabhash_lookup(struct slabhash* table, - hashvalue_type hash, void* key, int wr); - -/** - * Remove entry from hashtable. Does nothing if not found in hashtable. - * Delfunc is called for the entry. Uses lruhash_remove. - * @param table: hash table. - * @param hash: hash of key. - * @param key: what to look for. - */ -void slabhash_remove(struct slabhash* table, hashvalue_type hash, void* key); - -/** - * Output debug info to the log as to state of the hash table. - * @param table: hash table. - * @param id: string printed with table to identify the hash table. - * @param extended: set to true to print statistics on overflow bin lengths. - */ -void slabhash_status(struct slabhash* table, const char* id, int extended); - -/** - * Retrieve slab hash total size. - * @param table: hash table. - * @return size configured as max. - */ -size_t slabhash_get_size(struct slabhash* table); - -/** - * See if slabhash is of given (size, slabs) configuration. - * @param table: hash table - * @param size: max size to test for - * @param slabs: slab count to test for. - * @return true if equal - */ -int slabhash_is_size(struct slabhash* table, size_t size, size_t slabs); - -/** - * Retrieve slab hash current memory use. - * @param table: hash table. - * @return memory in use. - */ -size_t slabhash_get_mem(struct slabhash* table); - -/** - * Get lruhash table for a given hash value - * @param table: slabbed hash table. - * @param hash: hash value. - * @return the lru hash table. - */ -struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_type hash); - -/** - * Set markdel function - * @param table: slabbed hash table. - * @param md: markdel function ptr. - */ -void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_type md); - -/** - * Traverse a slabhash. - * @param table: slabbed hash table. - * @param wr: if true, writelock is obtained, otherwise readlock. - * @param func: function to call for every element. - * @param arg: user argument to function. - */ -void slabhash_traverse(struct slabhash* table, int wr, - void (*func)(struct lruhash_entry*, void*), void* arg); - -/* - * Count entries in slabhash. - * @param table: slabbed hash table; - * @return the number of items - */ -size_t count_slabhash_entries(struct slabhash* table); - -/** - * Retrieves number of items in slabhash and the current max collision level - * @param table: slabbed hash table. - * @param entries_count: where to save the current number of elements. - * @param max_collisions: where to save the current max collisions level. - */ -void get_slabhash_stats(struct slabhash* table, - long long* entries_count, long long* max_collisions); - -/* --- test representation --- */ -/** test structure contains test key */ -struct slabhash_testkey { - /** the key id */ - int id; - /** the entry */ - struct lruhash_entry entry; -}; -/** test structure contains test data */ -struct slabhash_testdata { - /** data value */ - int data; -}; - -/** test sizefunc for lruhash */ -size_t test_slabhash_sizefunc(void*, void*); -/** test comparefunc for lruhash */ -int test_slabhash_compfunc(void*, void*); -/** test delkey for lruhash */ -void test_slabhash_delkey(void*, void*); -/** test deldata for lruhash */ -void test_slabhash_deldata(void*, void*); -/* --- end test representation --- */ - -#endif /* UTIL_STORAGE_SLABHASH_H */ diff --git a/crates/libunbound-sys/unbound/util/tcp_conn_limit.c b/crates/libunbound-sys/unbound/util/tcp_conn_limit.c deleted file mode 100644 index d7d86a54..00000000 --- a/crates/libunbound-sys/unbound/util/tcp_conn_limit.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * daemon/tcp_conn_limit.c - client TCP connection limit storage for the server. - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file helps the server discard excess TCP connections. - */ -#include "config.h" -#include "util/regional.h" -#include "util/log.h" -#include "util/config_file.h" -#include "util/net_help.h" -#include "util/tcp_conn_limit.h" -#include "services/localzone.h" -#include "sldns/str2wire.h" - -struct tcl_list* -tcl_list_create(void) -{ - struct tcl_list* tcl = (struct tcl_list*)calloc(1, - sizeof(struct tcl_list)); - if(!tcl) - return NULL; - tcl->region = regional_create(); - if(!tcl->region) { - tcl_list_delete(tcl); - return NULL; - } - return tcl; -} - -static void -tcl_list_free_node(rbnode_type* node, void* ATTR_UNUSED(arg)) -{ - struct tcl_addr* n = (struct tcl_addr*) node; - lock_quick_destroy(&n->lock); -#ifdef THREADS_DISABLED - (void)n; -#endif -} - -void -tcl_list_delete(struct tcl_list* tcl) -{ - if(!tcl) - return; - traverse_postorder(&tcl->tree, tcl_list_free_node, NULL); - regional_destroy(tcl->region); - free(tcl); -} - -/** insert new address into tcl_list structure */ -static struct tcl_addr* -tcl_list_insert(struct tcl_list* tcl, struct sockaddr_storage* addr, - socklen_t addrlen, int net, uint32_t limit, - int complain_duplicates) -{ - struct tcl_addr* node = regional_alloc_zero(tcl->region, - sizeof(struct tcl_addr)); - if(!node) - return NULL; - lock_quick_init(&node->lock); - node->limit = limit; - if(!addr_tree_insert(&tcl->tree, &node->node, addr, addrlen, net)) { - if(complain_duplicates) - verbose(VERB_QUERY, "duplicate tcl address ignored."); - } - return node; -} - -/** apply tcl_list string */ -static int -tcl_list_str_cfg(struct tcl_list* tcl, const char* str, const char* s2, - int complain_duplicates) -{ - struct sockaddr_storage addr; - int net; - socklen_t addrlen; - uint32_t limit; - if(atoi(s2) < 0) { - log_err("bad connection limit %s", s2); - return 0; - } - limit = (uint32_t)atoi(s2); - if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { - log_err("cannot parse connection limit netblock: %s", str); - return 0; - } - if(!tcl_list_insert(tcl, &addr, addrlen, net, limit, - complain_duplicates)) { - log_err("out of memory"); - return 0; - } - return 1; -} - -/** read tcl_list config */ -static int -read_tcl_list(struct tcl_list* tcl, struct config_file* cfg) -{ - struct config_str2list* p; - for(p = cfg->tcp_connection_limits; p; p = p->next) { - log_assert(p->str && p->str2); - if(!tcl_list_str_cfg(tcl, p->str, p->str2, 1)) - return 0; - } - return 1; -} - -int -tcl_list_apply_cfg(struct tcl_list* tcl, struct config_file* cfg) -{ - regional_free_all(tcl->region); - addr_tree_init(&tcl->tree); - if(!read_tcl_list(tcl, cfg)) - return 0; - addr_tree_init_parents(&tcl->tree); - return 1; -} - -int -tcl_new_connection(struct tcl_addr* tcl) -{ - if(tcl) { - int res = 1; - lock_quick_lock(&tcl->lock); - if(tcl->count >= tcl->limit) - res = 0; - else - tcl->count++; - lock_quick_unlock(&tcl->lock); - return res; - } - return 1; -} - -void -tcl_close_connection(struct tcl_addr* tcl) -{ - if(tcl) { - lock_quick_lock(&tcl->lock); - log_assert(tcl->count > 0); - tcl->count--; - lock_quick_unlock(&tcl->lock); - } -} - -struct tcl_addr* -tcl_addr_lookup(struct tcl_list* tcl, struct sockaddr_storage* addr, - socklen_t addrlen) -{ - return (struct tcl_addr*)addr_tree_lookup(&tcl->tree, - addr, addrlen); -} - -size_t -tcl_list_get_mem(struct tcl_list* tcl) -{ - if(!tcl) return 0; - return sizeof(*tcl) + regional_get_mem(tcl->region); -} diff --git a/crates/libunbound-sys/unbound/util/tcp_conn_limit.h b/crates/libunbound-sys/unbound/util/tcp_conn_limit.h deleted file mode 100644 index 4fb71a32..00000000 --- a/crates/libunbound-sys/unbound/util/tcp_conn_limit.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * daemon/tcp_conn_limit.h - client TCP connection limit storage for the server. - * - * Copyright (c) 2018, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file keeps track of the limit on the number of TCP connections - * each client makes the server. - */ - -#ifndef DAEMON_TCP_CONN_LIMIT_H -#define DAEMON_TCP_CONN_LIMIT_H -#include "util/storage/dnstree.h" -#include "util/locks.h" -struct config_file; -struct regional; - -/** - * TCP connection limit storage structure - */ -struct tcl_list { - /** regional for allocation */ - struct regional* region; - /** - * Tree of the addresses that are TCP connection limited. - * contents of type tcl_addr. - */ - rbtree_type tree; -}; - -/** - * - * An address span with connection limit information - */ -struct tcl_addr { - /** node in address tree */ - struct addr_tree_node node; - /** lock on structure data */ - lock_quick_type lock; - /** connection limit on this netblock */ - uint32_t limit; - /** current connection count on this netblock */ - uint32_t count; -}; - -/** - * Create TCP connection limit structure - * @return new structure or NULL on error. - */ -struct tcl_list* tcl_list_create(void); - -/** - * Delete TCP connection limit structure. - * @param tcl: to delete. - */ -void tcl_list_delete(struct tcl_list* tcl); - -/** - * Process TCP connection limit config. - * @param tcl: where to store. - * @param cfg: config options. - * @return 0 on error. - */ -int tcl_list_apply_cfg(struct tcl_list* tcl, struct config_file* cfg); - -/** - * Increment TCP connection count if found, provided the - * count was below the limit. - * @param tcl: structure for tcl storage, or NULL. - * @return: 0 if limit reached, 1 if tcl was NULL or limit not reached. - */ -int tcl_new_connection(struct tcl_addr* tcl); - -/** - * Decrement TCP connection count if found. - * @param tcl: structure for tcl storage, or NULL. - */ -void tcl_close_connection(struct tcl_addr* tcl); - -/** - * Lookup address to see its TCP connection limit structure - * @param tcl: structure for address storage. - * @param addr: address to check - * @param addrlen: length of addr. - * @return: tcl structure from this address. - */ -struct tcl_addr* -tcl_addr_lookup(struct tcl_list* tcl, struct sockaddr_storage* addr, - socklen_t addrlen); - -/** - * Get memory used by TCP connection limit structure. - * @param tcl: structure for address storage. - * @return bytes in use. - */ -size_t tcl_list_get_mem(struct tcl_list* tcl); - -#endif /* DAEMON_TCP_CONN_LIMIT_H */ diff --git a/crates/libunbound-sys/unbound/util/timehist.c b/crates/libunbound-sys/unbound/util/timehist.c deleted file mode 100644 index 2063fe80..00000000 --- a/crates/libunbound-sys/unbound/util/timehist.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * util/timehist.c - make histogram of time values. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to make a histogram of time values. - */ -#include "config.h" -#ifdef HAVE_TIME_H -#include -#endif -#include -#include -#include "util/timehist.h" -#include "util/log.h" -#include "util/timeval_func.h" - -/** special timestwo operation for time values in histogram setup */ -static void -timestwo(struct timeval* v) -{ -#ifndef S_SPLINT_S - if(v->tv_sec == 0 && v->tv_usec == 0) { - v->tv_usec = 1; - return; - } - v->tv_sec *= 2; - v->tv_usec *= 2; - if(v->tv_usec == 1024*1024) { - /* nice values and easy to compute */ - v->tv_sec = 1; - v->tv_usec = 0; - } -#endif -} - -/** do setup exponentially */ -static void -dosetup(struct timehist* hist) -{ - struct timeval last; - size_t i; - memset(&last, 0, sizeof(last)); - for(i=0; inum; i++) { - hist->buckets[i].lower = last; - timestwo(&last); - hist->buckets[i].upper = last; - hist->buckets[i].count = 0; - } -} - -struct timehist* timehist_setup(void) -{ - struct timehist* hist = (struct timehist*)calloc(1, - sizeof(struct timehist)); - if(!hist) - return NULL; - hist->num = NUM_BUCKETS_HIST; - hist->buckets = (struct th_buck*)calloc(hist->num, - sizeof(struct th_buck)); - if(!hist->buckets) { - free(hist); - return NULL; - } - /* setup the buckets */ - dosetup(hist); - return hist; -} - -void timehist_delete(struct timehist* hist) -{ - if(!hist) - return; - free(hist->buckets); - free(hist); -} - -void timehist_clear(struct timehist* hist) -{ - size_t i; - for(i=0; inum; i++) - hist->buckets[i].count = 0; -} - -void timehist_insert(struct timehist* hist, struct timeval* tv) -{ - size_t i; - for(i=0; inum; i++) { - if(timeval_smaller(tv, &hist->buckets[i].upper)) { - hist->buckets[i].count++; - return; - } - } - /* dump in last bucket */ - hist->buckets[hist->num-1].count++; -} - -void timehist_print(struct timehist* hist) -{ -#ifndef S_SPLINT_S - size_t i; - for(i=0; inum; i++) { - if(hist->buckets[i].count != 0) { - printf("%4d.%6.6d %4d.%6.6d %u\n", - (int)hist->buckets[i].lower.tv_sec, - (int)hist->buckets[i].lower.tv_usec, - (int)hist->buckets[i].upper.tv_sec, - (int)hist->buckets[i].upper.tv_usec, - (unsigned)hist->buckets[i].count); - } - } -#endif -} - -void timehist_log(struct timehist* hist, const char* name) -{ -#ifndef S_SPLINT_S - size_t i; - log_info("[25%%]=%g median[50%%]=%g [75%%]=%g", - timehist_quartile(hist, 0.25), - timehist_quartile(hist, 0.50), - timehist_quartile(hist, 0.75)); - /* 0000.000000 0000.000000 0 */ - log_info("lower(secs) upper(secs) %s", name); - for(i=0; inum; i++) { - if(hist->buckets[i].count != 0) { - log_info("%4d.%6.6d %4d.%6.6d %u", - (int)hist->buckets[i].lower.tv_sec, - (int)hist->buckets[i].lower.tv_usec, - (int)hist->buckets[i].upper.tv_sec, - (int)hist->buckets[i].upper.tv_usec, - (unsigned)hist->buckets[i].count); - } - } -#endif -} - -/** total number in histogram */ -static size_t -timehist_count(struct timehist* hist) -{ - size_t i, res = 0; - for(i=0; inum; i++) - res += hist->buckets[i].count; - return res; -} - -double -timehist_quartile(struct timehist* hist, double q) -{ - double lookfor, passed, res; - double low = 0, up = 0; - size_t i; - if(!hist || hist->num == 0) - return 0.; - /* look for i'th element, interpolated */ - lookfor = (double)timehist_count(hist); - if(lookfor < 4) - return 0.; /* not enough elements for a good estimate */ - lookfor *= q; - passed = 0; - i = 0; - while(i+1 < hist->num && - passed+(double)hist->buckets[i].count < lookfor) { - passed += (double)hist->buckets[i++].count; - } - /* got the right bucket */ -#ifndef S_SPLINT_S - low = (double)hist->buckets[i].lower.tv_sec + - (double)hist->buckets[i].lower.tv_usec/1000000.; - up = (double)hist->buckets[i].upper.tv_sec + - (double)hist->buckets[i].upper.tv_usec/1000000.; -#endif - res = (lookfor - passed)*(up-low)/((double)hist->buckets[i].count); - return low+res; -} - -void -timehist_export(struct timehist* hist, long long* array, size_t sz) -{ - size_t i; - if(!hist) return; - if(sz > hist->num) - sz = hist->num; - for(i=0; ibuckets[i].count; -} - -void -timehist_import(struct timehist* hist, long long* array, size_t sz) -{ - size_t i; - if(!hist) return; - if(sz > hist->num) - sz = hist->num; - for(i=0; ibuckets[i].count = (size_t)array[i]; -} diff --git a/crates/libunbound-sys/unbound/util/timehist.h b/crates/libunbound-sys/unbound/util/timehist.h deleted file mode 100644 index 5f88a38a..00000000 --- a/crates/libunbound-sys/unbound/util/timehist.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * util/timehist.h - make histogram of time values. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions to make a histogram of time values. - */ - -#ifndef UTIL_TIMEHIST_H -#define UTIL_TIMEHIST_H - -/** Number of buckets in a histogram */ -#define NUM_BUCKETS_HIST 40 - -/** - * Bucket of time history information - */ -struct th_buck { - /** lower bound */ - struct timeval lower; - /** upper bound */ - struct timeval upper; - /** number of items */ - size_t count; -}; - -/** - * Keep histogram of time values. - */ -struct timehist { - /** number of buckets */ - size_t num; - /** bucket array */ - struct th_buck* buckets; -}; - -/** - * Setup a histogram, default - * @return histogram or NULL on malloc failure. - */ -struct timehist* timehist_setup(void); - -/** - * Delete histogram - * @param hist: to delete - */ -void timehist_delete(struct timehist* hist); - -/** - * Clear histogram - * @param hist: to clear all data from - */ -void timehist_clear(struct timehist* hist); - -/** - * Add time value to histogram. - * @param hist: histogram - * @param tv: time value - */ -void timehist_insert(struct timehist* hist, struct timeval* tv); - -/** - * Find time value for given quartile, such as 0.25, 0.50, 0.75. - * The looks up the value for the i-th element in the sorted list of time - * values, as approximated using the histogram. - * @param hist: histogram. Interpolated information is used from it. - * @param q: quartile, 0.50 results in the median. Must be >0 and <1. - * @return: the time in seconds for that percentage. - */ -double timehist_quartile(struct timehist* hist, double q); - -/** - * Printout histogram - * @param hist: histogram - */ -void timehist_print(struct timehist* hist); - -/** - * Log histogram, print it to the logfile. - * @param hist: histogram - * @param name: the name of the value column - */ -void timehist_log(struct timehist* hist, const char* name); - -/** - * Export histogram to an array. - * @param hist: histogram - * @param array: the array to export to. - * @param sz: number of items in array. - */ -void timehist_export(struct timehist* hist, long long* array, size_t sz); - -/** - * Import histogram from an array. - * @param hist: histogram - * @param array: the array to import from. - * @param sz: number of items in array. - */ -void timehist_import(struct timehist* hist, long long* array, size_t sz); - -#endif /* UTIL_TIMEHIST_H */ diff --git a/crates/libunbound-sys/unbound/util/timeval_func.c b/crates/libunbound-sys/unbound/util/timeval_func.c deleted file mode 100644 index 90250e15..00000000 --- a/crates/libunbound-sys/unbound/util/timeval_func.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * util/timeval_func.c - helpers to work with struct timeval values. - * - * Copyright (c) 2023, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helpers to manipulate struct timeval values. - */ - -#include "config.h" -#include "timeval_func.h" - -/** subtract timers and the values do not overflow or become negative */ -void -timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start) -{ -#ifndef S_SPLINT_S - time_t end_usec = end->tv_usec; - d->tv_sec = end->tv_sec - start->tv_sec; - if(end_usec < start->tv_usec) { - end_usec += 1000000; - d->tv_sec--; - } - d->tv_usec = end_usec - start->tv_usec; -#endif -} - -/** add timers and the values do not overflow or become negative */ -void -timeval_add(struct timeval* d, const struct timeval* add) -{ -#ifndef S_SPLINT_S - d->tv_sec += add->tv_sec; - d->tv_usec += add->tv_usec; - if(d->tv_usec >= 1000000 ) { - d->tv_usec -= 1000000; - d->tv_sec++; - } -#endif -} - -/** divide sum of timers to get average */ -void -timeval_divide(struct timeval* avg, const struct timeval* sum, long long d) -{ -#ifndef S_SPLINT_S - long long leftover; - if(d <= 0) { - avg->tv_sec = 0; - avg->tv_usec = 0; - return; - } - avg->tv_sec = sum->tv_sec / d; - avg->tv_usec = sum->tv_usec / d; - /* handle fraction from seconds divide */ - leftover = sum->tv_sec - avg->tv_sec*d; - if(leftover <= 0) - leftover = 0; - avg->tv_usec += (((long long)leftover)*((long long)1000000))/d; - if(avg->tv_sec < 0) - avg->tv_sec = 0; - if(avg->tv_usec < 0) - avg->tv_usec = 0; -#endif -} - -/** histogram compare of time values */ -int -timeval_smaller(const struct timeval* x, const struct timeval* y) -{ -#ifndef S_SPLINT_S - if(x->tv_sec < y->tv_sec) - return 1; - else if(x->tv_sec == y->tv_sec) { - if(x->tv_usec <= y->tv_usec) - return 1; - else return 0; - } - else return 0; -#endif -} diff --git a/crates/libunbound-sys/unbound/util/timeval_func.h b/crates/libunbound-sys/unbound/util/timeval_func.h deleted file mode 100644 index 819d1dd8..00000000 --- a/crates/libunbound-sys/unbound/util/timeval_func.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * util/timeval_func.h - definitions of helpers for struct timeval values. - * - * Copyright (c) 2023, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains definitions of helpers to manipulate struct timeval - * values, implemented in the corresponding C file. - */ -#include - -#ifndef timeval_isset -#define timeval_isset(tv) ((tv)->tv_sec || (tv)->tv_usec) -#endif -#ifndef timeval_clear -#define timeval_clear(tv) ((tv)->tv_sec = (tv)->tv_usec = 0) -#endif -void timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start); -void timeval_add(struct timeval* d, const struct timeval* add); -void timeval_divide(struct timeval* avg, const struct timeval* sum, long long d); -int timeval_smaller(const struct timeval* x, const struct timeval* y); diff --git a/crates/libunbound-sys/unbound/util/tube.c b/crates/libunbound-sys/unbound/util/tube.c deleted file mode 100644 index 7d98b93c..00000000 --- a/crates/libunbound-sys/unbound/util/tube.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * util/tube.c - pipe service - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains pipe service functions. - */ -#include "config.h" -#include "util/tube.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/netevent.h" -#include "util/fptr_wlist.h" -#include "util/ub_event.h" -#ifdef HAVE_POLL_H -#include -#endif - -#ifndef USE_WINSOCK -/* on unix */ - -#ifndef HAVE_SOCKETPAIR -/** no socketpair() available, like on Minix 3.1.7, use pipe */ -#define socketpair(f, t, p, sv) pipe(sv) -#endif /* HAVE_SOCKETPAIR */ - -struct tube* tube_create(void) -{ - struct tube* tube = (struct tube*)calloc(1, sizeof(*tube)); - int sv[2]; - if(!tube) { - int err = errno; - log_err("tube_create: out of memory"); - errno = err; - return NULL; - } - tube->sr = -1; - tube->sw = -1; - if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { - int err = errno; - log_err("socketpair: %s", strerror(errno)); - free(tube); - errno = err; - return NULL; - } - tube->sr = sv[0]; - tube->sw = sv[1]; - if(!fd_set_nonblock(tube->sr) || !fd_set_nonblock(tube->sw)) { - int err = errno; - log_err("tube: cannot set nonblocking"); - tube_delete(tube); - errno = err; - return NULL; - } - return tube; -} - -void tube_delete(struct tube* tube) -{ - if(!tube) return; - tube_remove_bg_listen(tube); - tube_remove_bg_write(tube); - /* close fds after deleting commpoints, to be sure. - * Also epoll does not like closing fd before event_del */ - tube_close_read(tube); - tube_close_write(tube); - free(tube); -} - -void tube_close_read(struct tube* tube) -{ - if(tube->sr != -1) { - close(tube->sr); - tube->sr = -1; - } -} - -void tube_close_write(struct tube* tube) -{ - if(tube->sw != -1) { - close(tube->sw); - tube->sw = -1; - } -} - -void tube_remove_bg_listen(struct tube* tube) -{ - if(tube->listen_com) { - comm_point_delete(tube->listen_com); - tube->listen_com = NULL; - } - free(tube->cmd_msg); - tube->cmd_msg = NULL; -} - -void tube_remove_bg_write(struct tube* tube) -{ - if(tube->res_com) { - comm_point_delete(tube->res_com); - tube->res_com = NULL; - } - if(tube->res_list) { - struct tube_res_list* np, *p = tube->res_list; - tube->res_list = NULL; - tube->res_last = NULL; - while(p) { - np = p->next; - free(p->buf); - free(p); - p = np; - } - } -} - -int -tube_handle_listen(struct comm_point* c, void* arg, int error, - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - struct tube* tube = (struct tube*)arg; - ssize_t r; - if(error != NETEVENT_NOERROR) { - fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); - (*tube->listen_cb)(tube, NULL, 0, error, tube->listen_arg); - return 0; - } - - if(tube->cmd_read < sizeof(tube->cmd_len)) { - /* complete reading the length of control msg */ - r = read(c->fd, ((uint8_t*)&tube->cmd_len) + tube->cmd_read, - sizeof(tube->cmd_len) - tube->cmd_read); - if(r==0) { - /* error has happened or */ - /* parent closed pipe, must have exited somehow */ - fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); - (*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, - tube->listen_arg); - return 0; - } - if(r==-1) { - if(errno != EAGAIN && errno != EINTR) { - log_err("rpipe error: %s", strerror(errno)); - } - /* nothing to read now, try later */ - return 0; - } - tube->cmd_read += r; - if(tube->cmd_read < sizeof(tube->cmd_len)) { - /* not complete, try later */ - return 0; - } - tube->cmd_msg = (uint8_t*)calloc(1, tube->cmd_len); - if(!tube->cmd_msg) { - log_err("malloc failure"); - tube->cmd_read = 0; - return 0; - } - } - /* cmd_len has been read, read remainder */ - r = read(c->fd, tube->cmd_msg+tube->cmd_read-sizeof(tube->cmd_len), - tube->cmd_len - (tube->cmd_read - sizeof(tube->cmd_len))); - if(r==0) { - /* error has happened or */ - /* parent closed pipe, must have exited somehow */ - fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); - (*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, - tube->listen_arg); - return 0; - } - if(r==-1) { - /* nothing to read now, try later */ - if(errno != EAGAIN && errno != EINTR) { - log_err("rpipe error: %s", strerror(errno)); - } - return 0; - } - tube->cmd_read += r; - if(tube->cmd_read < sizeof(tube->cmd_len) + tube->cmd_len) { - /* not complete, try later */ - return 0; - } - tube->cmd_read = 0; - - fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); - (*tube->listen_cb)(tube, tube->cmd_msg, tube->cmd_len, - NETEVENT_NOERROR, tube->listen_arg); - /* also frees the buf */ - tube->cmd_msg = NULL; - return 0; -} - -int -tube_handle_write(struct comm_point* c, void* arg, int error, - struct comm_reply* ATTR_UNUSED(reply_info)) -{ - struct tube* tube = (struct tube*)arg; - struct tube_res_list* item = tube->res_list; - ssize_t r; - if(error != NETEVENT_NOERROR) { - log_err("tube_handle_write net error %d", error); - return 0; - } - - if(!item) { - comm_point_stop_listening(c); - return 0; - } - - if(tube->res_write < sizeof(item->len)) { - r = write(c->fd, ((uint8_t*)&item->len) + tube->res_write, - sizeof(item->len) - tube->res_write); - if(r == -1) { - if(errno != EAGAIN && errno != EINTR) { - log_err("wpipe error: %s", strerror(errno)); - } - return 0; /* try again later */ - } - if(r == 0) { - /* error on pipe, must have exited somehow */ - /* cannot signal this to pipe user */ - return 0; - } - tube->res_write += r; - if(tube->res_write < sizeof(item->len)) - return 0; - } - r = write(c->fd, item->buf + tube->res_write - sizeof(item->len), - item->len - (tube->res_write - sizeof(item->len))); - if(r == -1) { - if(errno != EAGAIN && errno != EINTR) { - log_err("wpipe error: %s", strerror(errno)); - } - return 0; /* try again later */ - } - if(r == 0) { - /* error on pipe, must have exited somehow */ - /* cannot signal this to pipe user */ - return 0; - } - tube->res_write += r; - if(tube->res_write < sizeof(item->len) + item->len) - return 0; - /* done this result, remove it */ - free(item->buf); - item->buf = NULL; - tube->res_list = tube->res_list->next; - free(item); - if(!tube->res_list) { - tube->res_last = NULL; - comm_point_stop_listening(c); - } - tube->res_write = 0; - return 0; -} - -int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, - int nonblock) -{ - ssize_t r, d; - int fd = tube->sw; - - /* test */ - if(nonblock) { - r = write(fd, &len, sizeof(len)); - if(r == -1) { - if(errno==EINTR || errno==EAGAIN) - return -1; - log_err("tube msg write failed: %s", strerror(errno)); - return -1; /* can still continue, perhaps */ - } - } else r = 0; - if(!fd_set_block(fd)) - return 0; - /* write remainder */ - d = r; - while(d != (ssize_t)sizeof(len)) { - if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) { - if(errno == EAGAIN) - continue; /* temporarily unavail: try again*/ - log_err("tube msg write failed: %s", strerror(errno)); - (void)fd_set_nonblock(fd); - return 0; - } - d += r; - } - d = 0; - while(d != (ssize_t)len) { - if((r=write(fd, buf+d, len-d)) == -1) { - if(errno == EAGAIN) - continue; /* temporarily unavail: try again*/ - log_err("tube msg write failed: %s", strerror(errno)); - (void)fd_set_nonblock(fd); - return 0; - } - d += r; - } - if(!fd_set_nonblock(fd)) - return 0; - return 1; -} - -int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, - int nonblock) -{ - ssize_t r, d; - int fd = tube->sr; - - /* test */ - *len = 0; - if(nonblock) { - r = read(fd, len, sizeof(*len)); - if(r == -1) { - if(errno==EINTR || errno==EAGAIN) - return -1; - log_err("tube msg read failed: %s", strerror(errno)); - return -1; /* we can still continue, perhaps */ - } - if(r == 0) /* EOF */ - return 0; - } else r = 0; - if(!fd_set_block(fd)) - return 0; - /* read remainder */ - d = r; - while(d != (ssize_t)sizeof(*len)) { - if((r=read(fd, ((char*)len)+d, sizeof(*len)-d)) == -1) { - log_err("tube msg read failed: %s", strerror(errno)); - (void)fd_set_nonblock(fd); - return 0; - } - if(r == 0) /* EOF */ { - (void)fd_set_nonblock(fd); - return 0; - } - d += r; - } - if (*len >= 65536*2) { - log_err("tube msg length %u is too big", (unsigned)*len); - (void)fd_set_nonblock(fd); - return 0; - } - *buf = (uint8_t*)malloc(*len); - if(!*buf) { - log_err("tube read out of memory"); - (void)fd_set_nonblock(fd); - return 0; - } - d = 0; - while(d < (ssize_t)*len) { - if((r=read(fd, (*buf)+d, (size_t)((ssize_t)*len)-d)) == -1) { - log_err("tube msg read failed: %s", strerror(errno)); - (void)fd_set_nonblock(fd); - free(*buf); - return 0; - } - if(r == 0) { /* EOF */ - (void)fd_set_nonblock(fd); - free(*buf); - return 0; - } - d += r; - } - if(!fd_set_nonblock(fd)) { - free(*buf); - return 0; - } - return 1; -} - -/** perform poll() on the fd */ -static int -pollit(int fd, struct timeval* t) -{ - struct pollfd fds; - int pret; - int msec = -1; - memset(&fds, 0, sizeof(fds)); - fds.fd = fd; - fds.events = POLLIN | POLLERR | POLLHUP; -#ifndef S_SPLINT_S - if(t) - msec = t->tv_sec*1000 + t->tv_usec/1000; -#endif - - pret = poll(&fds, 1, msec); - - if(pret == -1) - return 0; - if(pret != 0) - return 1; - return 0; -} - -int tube_poll(struct tube* tube) -{ - struct timeval t; - memset(&t, 0, sizeof(t)); - return pollit(tube->sr, &t); -} - -int tube_wait(struct tube* tube) -{ - return pollit(tube->sr, NULL); -} - -int tube_wait_timeout(struct tube* tube, int msec) -{ - int ret = 0; - - while(1) { - struct pollfd fds; - memset(&fds, 0, sizeof(fds)); - - fds.fd = tube->sr; - fds.events = POLLIN | POLLERR | POLLHUP; - ret = poll(&fds, 1, msec); - - if(ret == -1) { - if(errno == EAGAIN || errno == EINTR) - continue; - return -1; - } - break; - } - - if(ret != 0) - return 1; - return 0; -} - -int tube_read_fd(struct tube* tube) -{ - return tube->sr; -} - -int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, - tube_callback_type* cb, void* arg) -{ - tube->listen_cb = cb; - tube->listen_arg = arg; - if(!(tube->listen_com = comm_point_create_raw(base, tube->sr, - 0, tube_handle_listen, tube))) { - int err = errno; - log_err("tube_setup_bg_l: commpoint creation failed"); - errno = err; - return 0; - } - return 1; -} - -int tube_setup_bg_write(struct tube* tube, struct comm_base* base) -{ - if(!(tube->res_com = comm_point_create_raw(base, tube->sw, - 1, tube_handle_write, tube))) { - int err = errno; - log_err("tube_setup_bg_w: commpoint creation failed"); - errno = err; - return 0; - } - return 1; -} - -int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len) -{ - struct tube_res_list* item; - if(!tube || !tube->res_com) return 0; - item = (struct tube_res_list*)malloc(sizeof(*item)); - if(!item) { - free(msg); - log_err("out of memory for async answer"); - return 0; - } - item->buf = msg; - item->len = len; - item->next = NULL; - /* add at back of list, since the first one may be partially written */ - if(tube->res_last) - tube->res_last->next = item; - else tube->res_list = item; - tube->res_last = item; - if(tube->res_list == tube->res_last) { - /* first added item, start the write process */ - comm_point_start_listening(tube->res_com, -1, -1); - } - return 1; -} - -void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), - void* ATTR_UNUSED(arg)) -{ - log_assert(0); -} - -#else /* USE_WINSOCK */ -/* on windows */ - - -struct tube* tube_create(void) -{ - /* windows does not have forks like unix, so we only support - * threads on windows. And thus the pipe need only connect - * threads. We use a mutex and a list of datagrams. */ - struct tube* tube = (struct tube*)calloc(1, sizeof(*tube)); - if(!tube) { - int err = errno; - log_err("tube_create: out of memory"); - errno = err; - return NULL; - } - tube->event = WSACreateEvent(); - if(tube->event == WSA_INVALID_EVENT) { - free(tube); - log_err("WSACreateEvent: %s", wsa_strerror(WSAGetLastError())); - return NULL; - } - if(!WSAResetEvent(tube->event)) { - log_err("WSAResetEvent: %s", wsa_strerror(WSAGetLastError())); - } - lock_basic_init(&tube->res_lock); - verbose(VERB_ALGO, "tube created"); - return tube; -} - -void tube_delete(struct tube* tube) -{ - if(!tube) return; - tube_remove_bg_listen(tube); - tube_remove_bg_write(tube); - tube_close_read(tube); - tube_close_write(tube); - if(!WSACloseEvent(tube->event)) - log_err("WSACloseEvent: %s", wsa_strerror(WSAGetLastError())); - lock_basic_destroy(&tube->res_lock); - verbose(VERB_ALGO, "tube deleted"); - free(tube); -} - -void tube_close_read(struct tube* ATTR_UNUSED(tube)) -{ - verbose(VERB_ALGO, "tube close_read"); -} - -void tube_close_write(struct tube* ATTR_UNUSED(tube)) -{ - verbose(VERB_ALGO, "tube close_write"); - /* wake up waiting reader with an empty queue */ - if(!WSASetEvent(tube->event)) { - log_err("WSASetEvent: %s", wsa_strerror(WSAGetLastError())); - } -} - -void tube_remove_bg_listen(struct tube* tube) -{ - verbose(VERB_ALGO, "tube remove_bg_listen"); - ub_winsock_unregister_wsaevent(tube->ev_listen); -} - -void tube_remove_bg_write(struct tube* tube) -{ - verbose(VERB_ALGO, "tube remove_bg_write"); - if(tube->res_list) { - struct tube_res_list* np, *p = tube->res_list; - tube->res_list = NULL; - tube->res_last = NULL; - while(p) { - np = p->next; - free(p->buf); - free(p); - p = np; - } - } -} - -int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, - int ATTR_UNUSED(nonblock)) -{ - uint8_t* a; - verbose(VERB_ALGO, "tube write_msg len %d", (int)len); - a = (uint8_t*)memdup(buf, len); - if(!a) { - log_err("out of memory in tube_write_msg"); - return 0; - } - /* always nonblocking, this pipe cannot get full */ - return tube_queue_item(tube, a, len); -} - -int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, - int nonblock) -{ - struct tube_res_list* item = NULL; - verbose(VERB_ALGO, "tube read_msg %s", nonblock?"nonblock":"blocking"); - *buf = NULL; - if(!tube_poll(tube)) { - verbose(VERB_ALGO, "tube read_msg nodata"); - /* nothing ready right now, wait if we want to */ - if(nonblock) - return -1; /* would block waiting for items */ - if(!tube_wait(tube)) - return 0; - } - lock_basic_lock(&tube->res_lock); - if(tube->res_list) { - item = tube->res_list; - tube->res_list = item->next; - if(tube->res_last == item) { - /* the list is now empty */ - tube->res_last = NULL; - verbose(VERB_ALGO, "tube read_msg lastdata"); - if(!WSAResetEvent(tube->event)) { - log_err("WSAResetEvent: %s", - wsa_strerror(WSAGetLastError())); - } - } - } - lock_basic_unlock(&tube->res_lock); - if(!item) - return 0; /* would block waiting for items */ - *buf = item->buf; - *len = item->len; - free(item); - verbose(VERB_ALGO, "tube read_msg len %d", (int)*len); - return 1; -} - -int tube_poll(struct tube* tube) -{ - struct tube_res_list* item = NULL; - lock_basic_lock(&tube->res_lock); - item = tube->res_list; - lock_basic_unlock(&tube->res_lock); - if(item) - return 1; - return 0; -} - -int tube_wait(struct tube* tube) -{ - /* block on eventhandle */ - DWORD res = WSAWaitForMultipleEvents( - 1 /* one event in array */, - &tube->event /* the event to wait for, our pipe signal */, - 0 /* wait for all events is false */, - WSA_INFINITE /* wait, no timeout */, - 0 /* we are not alertable for IO completion routines */ - ); - if(res == WSA_WAIT_TIMEOUT) { - return 0; - } - if(res == WSA_WAIT_IO_COMPLETION) { - /* a bit unexpected, since we were not alertable */ - return 0; - } - return 1; -} - -int tube_wait_timeout(struct tube* tube, int msec) -{ - /* block on eventhandle */ - DWORD res = WSAWaitForMultipleEvents( - 1 /* one event in array */, - &tube->event /* the event to wait for, our pipe signal */, - 0 /* wait for all events is false */, - msec /* wait for timeout */, - 0 /* we are not alertable for IO completion routines */ - ); - if(res == WSA_WAIT_TIMEOUT) { - return 0; - } - if(res == WSA_WAIT_IO_COMPLETION) { - /* a bit unexpected, since we were not alertable */ - return -1; - } - return 1; -} - -int tube_read_fd(struct tube* ATTR_UNUSED(tube)) -{ - /* nothing sensible on Windows */ - return -1; -} - -int -tube_handle_listen(struct comm_point* ATTR_UNUSED(c), void* ATTR_UNUSED(arg), - int ATTR_UNUSED(error), struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -int -tube_handle_write(struct comm_point* ATTR_UNUSED(c), void* ATTR_UNUSED(arg), - int ATTR_UNUSED(error), struct comm_reply* ATTR_UNUSED(reply_info)) -{ - log_assert(0); - return 0; -} - -int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, - tube_callback_type* cb, void* arg) -{ - tube->listen_cb = cb; - tube->listen_arg = arg; - if(!comm_base_internal(base)) - return 1; /* ignore when no comm base - testing */ - tube->ev_listen = ub_winsock_register_wsaevent( - comm_base_internal(base), tube->event, &tube_handle_signal, tube); - return tube->ev_listen ? 1 : 0; -} - -int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube), - struct comm_base* ATTR_UNUSED(base)) -{ - /* the queue item routine performs the signaling */ - return 1; -} - -int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len) -{ - struct tube_res_list* item; - if(!tube) return 0; - item = (struct tube_res_list*)malloc(sizeof(*item)); - verbose(VERB_ALGO, "tube queue_item len %d", (int)len); - if(!item) { - free(msg); - log_err("out of memory for async answer"); - return 0; - } - item->buf = msg; - item->len = len; - item->next = NULL; - lock_basic_lock(&tube->res_lock); - /* add at back of list, since the first one may be partially written */ - if(tube->res_last) - tube->res_last->next = item; - else tube->res_list = item; - tube->res_last = item; - /* signal the eventhandle */ - if(!WSASetEvent(tube->event)) { - log_err("WSASetEvent: %s", wsa_strerror(WSAGetLastError())); - } - lock_basic_unlock(&tube->res_lock); - return 1; -} - -void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), - void* arg) -{ - struct tube* tube = (struct tube*)arg; - uint8_t* buf; - uint32_t len = 0; - verbose(VERB_ALGO, "tube handle_signal"); - while(tube_poll(tube)) { - if(tube_read_msg(tube, &buf, &len, 1)) { - fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); - (*tube->listen_cb)(tube, buf, len, NETEVENT_NOERROR, - tube->listen_arg); - } - } -} - -#endif /* USE_WINSOCK */ diff --git a/crates/libunbound-sys/unbound/util/tube.h b/crates/libunbound-sys/unbound/util/tube.h deleted file mode 100644 index 5e4fb864..00000000 --- a/crates/libunbound-sys/unbound/util/tube.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * util/tube.h - pipe service - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains pipe service functions. - */ - -#ifndef UTIL_TUBE_H -#define UTIL_TUBE_H -struct comm_reply; -struct comm_point; -struct comm_base; -struct tube; -struct tube_res_list; -#ifdef USE_WINSOCK -#include "util/locks.h" -#endif - -/** - * Callback from pipe listen function - * void mycallback(tube, msg, len, error, user_argument); - * if error is true (NETEVENT_*), msg is probably NULL. - */ -typedef void tube_callback_type(struct tube*, uint8_t*, size_t, int, void*); - -/** - * A pipe - */ -struct tube { -#ifndef USE_WINSOCK - /** pipe end to read from */ - int sr; - /** pipe end to write on */ - int sw; - - /** listen commpoint */ - struct comm_point* listen_com; - /** listen callback */ - tube_callback_type* listen_cb; - /** listen callback user arg */ - void* listen_arg; - /** are we currently reading a command, 0 if not, else bytecount */ - size_t cmd_read; - /** size of current read command, may be partially read */ - uint32_t cmd_len; - /** the current read command content, malloced, can be partially read*/ - uint8_t* cmd_msg; - - /** background write queue, commpoint to write results back */ - struct comm_point* res_com; - /** are we currently writing a result, 0 if not, else bytecount into - * the res_list first entry. */ - size_t res_write; - /** list of outstanding results to be written back */ - struct tube_res_list* res_list; - /** last in list */ - struct tube_res_list* res_last; - -#else /* USE_WINSOCK */ - /** listen callback */ - tube_callback_type* listen_cb; - /** listen callback user arg */ - void* listen_arg; - /** the windows sockets event (signaled if items in pipe) */ - WSAEVENT event; - /** winsock event storage when registered with event base */ - struct ub_event* ev_listen; - - /** lock on the list of outstanding items */ - lock_basic_type res_lock; - /** list of outstanding results on pipe */ - struct tube_res_list* res_list; - /** last in list */ - struct tube_res_list* res_last; -#endif /* USE_WINSOCK */ -}; - -/** - * List of results (arbitrary command serializations) to write back - */ -struct tube_res_list { - /** next in list */ - struct tube_res_list* next; - /** serialized buffer to write */ - uint8_t* buf; - /** length to write */ - uint32_t len; -}; - -/** - * Create a pipe - * @return: new tube struct or NULL on error. - */ -struct tube* tube_create(void); - -/** - * Delete and destroy a pipe - * @param tube: to delete - */ -void tube_delete(struct tube* tube); - -/** - * Write length bytes followed by message. - * @param tube: the tube to write on. - * If that tube is a pipe, its write fd is used as - * the socket to write on. Is nonblocking. - * Set to blocking by the function, - * and back to non-blocking at exit of function. - * @param buf: the message. - * @param len: length of message. - * @param nonblock: if set to true, the first write is nonblocking. - * If the first write fails the function returns -1. - * If set false, the first write is blocking. - * @return: all remainder writes are nonblocking. - * return 0 on error, in that case blocking/nonblocking of socket is - * unknown. - * return 1 if all OK. - */ -int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, - int nonblock); - -/** - * Read length bytes followed by message. - * @param tube: The tube to read on. - * If that tube is a pipe, its read fd is used as - * the socket to read on. Is nonblocking. - * Set to blocking by the function, - * and back to non-blocking at exit of function. - * @param buf: the message, malloced. - * @param len: length of message, returned. - * @param nonblock: if set to true, the first read is nonblocking. - * If the first read fails the function returns -1. - * If set false, the first read is blocking. - * @return: all remainder reads are nonblocking. - * return 0 on error, in that case blocking/nonblocking of socket is - * unknown. On EOF 0 is returned. - * return 1 if all OK. - */ -int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, - int nonblock); - -/** - * Close read part of the pipe. - * The tube can no longer be read from. - * @param tube: tube to operate on. - */ -void tube_close_read(struct tube* tube); - -/** - * Close write part of the pipe. - * The tube can no longer be written to. - * @param tube: tube to operate on. - */ -void tube_close_write(struct tube* tube); - -/** - * See if data is ready for reading on the tube without blocking. - * @param tube: tube to check for readable items - * @return true if readable items are present. False if not (or error). - * true on pipe_closed. - */ -int tube_poll(struct tube* tube); - -/** - * Wait for data to be ready for reading on the tube. is blocking. - * No timeout. - * @param tube: the tube to wait on. - * @return: if there was something to read (false on error). - * true on pipe_closed. - */ -int tube_wait(struct tube* tube); - -/** - * Wait for data to be ready with a timeout. - * @param tube: the tube to wait on. - * @param msec: timeout in milliseconds. - * @return 1 if there is something to read within timeout, readability. - * 0 on a timeout. On failures -1, like errors. */ -int tube_wait_timeout(struct tube* tube, int msec); - -/** - * Get FD that is readable when new information arrives. - * @param tube - * @return file descriptor. - */ -int tube_read_fd(struct tube* tube); - -/** - * Start listening for information over the pipe. - * Background registration of a read listener, callback when read completed. - * Do not mix with tube_read_msg style direct reads from the pipe. - * @param tube: tube to listen on - * @param base: what base to register event callback. - * @param cb: callback routine. - * @param arg: user argument for callback routine. - * @return true if successful, false on error. - */ -int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, - tube_callback_type* cb, void* arg); - -/** - * Remove bg listen setup from event base. - * @param tube: what tube to cleanup - */ -void tube_remove_bg_listen(struct tube* tube); - -/** - * Start background write handler for the pipe. - * Do not mix with tube_write_msg style direct writes to the pipe. - * @param tube: tube to write on - * @param base: what base to register event handler on. - * @return true if successful, false on error. - */ -int tube_setup_bg_write(struct tube* tube, struct comm_base* base); - -/** - * Remove bg write setup from event base. - * @param tube: what tube to cleanup - */ -void tube_remove_bg_write(struct tube* tube); - - -/** - * Append data item to background list of writes. - * Mallocs a list entry behind the scenes. - * Not locked behind the scenes, call from one thread or lock on outside. - * @param tube: what tube to queue on. - * @param msg: memory message to send. Is free()d after use. - * Put at the end of the to-send queue. - * @param len: length of item. - * @return 0 on failure (msg freed). - */ -int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len); - -/** for fptr wlist, callback function */ -int tube_handle_listen(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** for fptr wlist, callback function */ -int tube_handle_write(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** for fptr wlist, winsock signal event callback function */ -void tube_handle_signal(int fd, short events, void* arg); - -#endif /* UTIL_TUBE_H */ diff --git a/crates/libunbound-sys/unbound/util/ub_event.c b/crates/libunbound-sys/unbound/util/ub_event.c deleted file mode 100644 index 8cd87ec4..00000000 --- a/crates/libunbound-sys/unbound/util/ub_event.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * util/ub_event.c - directly call libevent (compatibility) functions - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains and implementation for the indirection layer for pluggable - * events that transparently passes it either directly to libevent, or calls - * the libevent compatibility layer functions. - */ -#include "config.h" -#include -#include "util/ub_event.h" -#include "util/log.h" -#include "util/netevent.h" -#include "util/tube.h" - -/* We define libevent structures here to hide the libevent stuff. */ - -#ifdef USE_MINI_EVENT -# ifdef USE_WINSOCK -# include "util/winsock_event.h" -# else -# include "util/mini_event.h" -# endif /* USE_WINSOCK */ -#else /* USE_MINI_EVENT */ - /* we use libevent */ -# ifdef HAVE_EVENT_H -# include -# else -# include "event2/event.h" -# include "event2/event_struct.h" -# include "event2/event_compat.h" -# endif -#endif /* USE_MINI_EVENT */ - -#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \ - UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \ - UB_EV_PERSIST != EV_PERSIST -/* Only necessary for libev */ -# define NATIVE_BITS(b) ( \ - (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \ - | (((b) & UB_EV_READ ) ? EV_READ : 0) \ - | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \ - | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \ - | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0)) - -# define UB_EV_BITS(b) ( \ - (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \ - | (((b) & EV_READ ) ? UB_EV_READ : 0) \ - | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \ - | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \ - | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0)) - -# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \ - { (C)(fd, UB_EV_BITS(bits), arg); } - -UB_EV_BITS_CB(comm_point_udp_callback); -UB_EV_BITS_CB(comm_point_udp_ancil_callback) -UB_EV_BITS_CB(comm_point_tcp_accept_callback) -UB_EV_BITS_CB(comm_point_tcp_handle_callback) -UB_EV_BITS_CB(comm_timer_callback) -UB_EV_BITS_CB(comm_signal_callback) -UB_EV_BITS_CB(comm_point_local_handle_callback) -UB_EV_BITS_CB(comm_point_raw_handle_callback) -UB_EV_BITS_CB(comm_point_http_handle_callback) -UB_EV_BITS_CB(tube_handle_signal) -UB_EV_BITS_CB(comm_base_handle_slow_accept) - -static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*) -{ - if(cb == comm_point_udp_callback) - return my_comm_point_udp_callback; - else if(cb == comm_point_udp_ancil_callback) - return my_comm_point_udp_ancil_callback; - else if(cb == comm_point_tcp_accept_callback) - return my_comm_point_tcp_accept_callback; - else if(cb == comm_point_tcp_handle_callback) - return my_comm_point_tcp_handle_callback; - else if(cb == comm_timer_callback) - return my_comm_timer_callback; - else if(cb == comm_signal_callback) - return my_comm_signal_callback; - else if(cb == comm_point_local_handle_callback) - return my_comm_point_local_handle_callback; - else if(cb == comm_point_raw_handle_callback) - return my_comm_point_raw_handle_callback; - else if(cb == comm_point_http_handle_callback) - return my_comm_point_http_handle_callback; - else if(cb == tube_handle_signal) - return my_tube_handle_signal; - else if(cb == comm_base_handle_slow_accept) - return my_comm_base_handle_slow_accept; - else { - log_assert(0); /* this NULL callback pointer should not happen, - we should have the necessary routine listed above */ - return NULL; - } -} -#else -# define NATIVE_BITS(b) (b) -# define NATIVE_BITS_CB(c) (c) -#endif - -#ifndef EVFLAG_AUTO -#define EVFLAG_AUTO 0 -#endif - -#define AS_EVENT_BASE(x) ((struct event_base*)x) -#define AS_UB_EVENT_BASE(x) ((struct ub_event_base*)x) -#define AS_EVENT(x) ((struct event*)x) -#define AS_UB_EVENT(x) ((struct ub_event*)x) - -const char* ub_event_get_version(void) -{ - return event_get_version(); -} - -#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EV_FEATURE_BACKENDS) -static const char* ub_ev_backend2str(int b) -{ - switch(b) { - case EVBACKEND_SELECT: return "select"; - case EVBACKEND_POLL: return "poll"; - case EVBACKEND_EPOLL: return "epoll"; - case EVBACKEND_KQUEUE: return "kqueue"; - case EVBACKEND_DEVPOLL: return "devpoll"; - case EVBACKEND_PORT: return "evport"; - } - return "unknown"; -} -#endif - -void -ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s, - const char** m) -{ -#ifdef USE_WINSOCK - (void)base; - *n = "event"; - *s = "winsock"; - *m = "WSAWaitForMultipleEvents"; -#elif defined(USE_MINI_EVENT) - (void)base; - *n = "mini-event"; - *s = "internal"; - *m = "select"; -#else - struct event_base* b = AS_EVENT_BASE(base); - *s = event_get_version(); -# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) - *n = "libev"; - if (!b) - b = (struct event_base*)ev_default_loop(EVFLAG_AUTO); -# ifdef EV_FEATURE_BACKENDS - *m = ub_ev_backend2str(ev_backend((struct ev_loop*)b)); -# else - *m = "not obtainable"; -# endif -# elif defined(HAVE_EVENT_BASE_GET_METHOD) - *n = "libevent"; - if (!b) - b = event_base_new(); - *m = event_base_get_method(b); -# else - *n = "unknown"; - *m = "not obtainable"; - (void)b; -# endif -# ifdef HAVE_EVENT_BASE_FREE - if (b && b != AS_EVENT_BASE(base)) - event_base_free(b); -# endif -#endif -} - -struct ub_event_base* -ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv) -{ - void* base; - - (void)base; -#ifdef USE_MINI_EVENT - (void)sigs; - /* use mini event time-sharing feature */ - base = event_init(time_secs, time_tv); -#else - (void)time_secs; - (void)time_tv; -# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) - /* libev */ - if(sigs) - base = ev_default_loop(EVFLAG_AUTO); - else - base = ev_loop_new(EVFLAG_AUTO); -# else - (void)sigs; -# ifdef HAVE_EVENT_BASE_NEW - base = event_base_new(); -# else - base = event_init(); -# endif -# endif -#endif - return (struct ub_event_base*)base; -} - -struct ub_event_base * -ub_libevent_event_base(struct event_base* libevent_base) -{ -#ifdef USE_MINI_EVENT - (void)libevent_base; - return NULL; -#else - return AS_UB_EVENT_BASE(libevent_base); -#endif -} - -struct event_base * -ub_libevent_get_event_base(struct ub_event_base* base) -{ -#ifdef USE_MINI_EVENT - (void)base; - return NULL; -#else - return AS_EVENT_BASE(base); -#endif -} - -void -ub_event_base_free(struct ub_event_base* base) -{ -#ifdef USE_MINI_EVENT - event_base_free(AS_EVENT_BASE(base)); -#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE) - /* only libevent 1.2+ has it, but in 1.2 it is broken - - assertion fails on signal handling ev that is not deleted - in libevent 1.3c (event_base_once appears) this is fixed. */ - event_base_free(AS_EVENT_BASE(base)); -#else - (void)base; -#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */ -} - -int -ub_event_base_dispatch(struct ub_event_base* base) -{ - return event_base_dispatch(AS_EVENT_BASE(base)); -} - -int -ub_event_base_loopexit(struct ub_event_base* base) -{ - return event_base_loopexit(AS_EVENT_BASE(base), NULL); -} - -struct ub_event* -ub_event_new(struct ub_event_base* base, int fd, short bits, - void (*cb)(int, short, void*), void* arg) -{ - struct event *ev = (struct event*)calloc(1, sizeof(struct event)); - - if (!ev) - return NULL; - -#ifndef HAVE_EVENT_ASSIGN - event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg); - if (event_base_set(AS_EVENT_BASE(base), ev) != 0) { - free(ev); - return NULL; - } -#else - if (event_assign(ev, AS_EVENT_BASE(base), fd, bits, cb, arg) != 0) { - free(ev); - return NULL; - } -#endif - return AS_UB_EVENT(ev); -} - -struct ub_event* -ub_signal_new(struct ub_event_base* base, int fd, - void (*cb)(int, short, void*), void* arg) -{ - struct event *ev = (struct event*)calloc(1, sizeof(struct event)); - - if (!ev) - return NULL; - -#if !HAVE_DECL_EVSIGNAL_ASSIGN - signal_set(ev, fd, NATIVE_BITS_CB(cb), arg); - if (event_base_set(AS_EVENT_BASE(base), ev) != 0) { - free(ev); - return NULL; - } -#else - if (evsignal_assign(ev, AS_EVENT_BASE(base), fd, cb, arg) != 0) { - free(ev); - return NULL; - } -#endif - return AS_UB_EVENT(ev); -} - -struct ub_event* -ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent, - void (*cb)(int, short, void*), void* arg) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - struct event *ev = (struct event*)calloc(1, sizeof(struct event)); - - if (!ev) - return NULL; - - if (winsock_register_wsaevent(AS_EVENT_BASE(base), ev, wsaevent, cb, - arg)) - return AS_UB_EVENT(ev); - free(ev); - return NULL; -#else - (void)base; - (void)wsaevent; - (void)cb; - (void)arg; - return NULL; -#endif -} - -void -ub_event_add_bits(struct ub_event* ev, short bits) -{ - AS_EVENT(ev)->ev_events |= NATIVE_BITS(bits); -} - -void -ub_event_del_bits(struct ub_event* ev, short bits) -{ - AS_EVENT(ev)->ev_events &= ~NATIVE_BITS(bits); -} - -void -ub_event_set_fd(struct ub_event* ev, int fd) -{ - AS_EVENT(ev)->ev_fd = fd; -} - -void -ub_event_free(struct ub_event* ev) -{ - if (ev) - free(AS_EVENT(ev)); -} - -int -ub_event_add(struct ub_event* ev, struct timeval* tv) -{ - return event_add(AS_EVENT(ev), tv); -} - -int -ub_event_del(struct ub_event* ev) -{ - return event_del(AS_EVENT(ev)); -} - -int -ub_timer_add(struct ub_event* ev, struct ub_event_base* base, - void (*cb)(int, short, void*), void* arg, struct timeval* tv) -{ - event_set(AS_EVENT(ev), -1, EV_TIMEOUT, NATIVE_BITS_CB(cb), arg); - if (event_base_set(AS_EVENT_BASE(base), AS_EVENT(ev)) != 0) - return -1; - return evtimer_add(AS_EVENT(ev), tv); -} - -int -ub_timer_del(struct ub_event* ev) -{ - return evtimer_del(AS_EVENT(ev)); -} - -int -ub_signal_add(struct ub_event* ev, struct timeval* tv) -{ - return signal_add(AS_EVENT(ev), tv); -} - -int -ub_signal_del(struct ub_event* ev) -{ - return signal_del(AS_EVENT(ev)); -} - -void -ub_winsock_unregister_wsaevent(struct ub_event* ev) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - winsock_unregister_wsaevent(AS_EVENT(ev)); - free(AS_EVENT(ev)); -#else - (void)ev; -#endif -} - -void -ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - winsock_tcp_wouldblock(AS_EVENT(ev), NATIVE_BITS(eventbits)); -#else - (void)ev; - (void)eventbits; -#endif -} - -void ub_comm_base_now(struct comm_base* cb) -{ -#ifdef USE_MINI_EVENT -/** minievent updates the time when it blocks. */ - (void)cb; /* nothing to do */ -#else /* !USE_MINI_EVENT */ -/** fillup the time values in the event base */ - time_t *tt; - struct timeval *tv; - comm_base_timept(cb, &tt, &tv); - if(gettimeofday(tv, NULL) < 0) { - log_err("gettimeofday: %s", strerror(errno)); - } -#ifndef S_SPLINT_S - *tt = tv->tv_sec; -#endif -#endif /* USE_MINI_EVENT */ -} - diff --git a/crates/libunbound-sys/unbound/util/ub_event.h b/crates/libunbound-sys/unbound/util/ub_event.h deleted file mode 100644 index b00a9bf6..00000000 --- a/crates/libunbound-sys/unbound/util/ub_event.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * util/ub_event.h - indirection layer for pluggable events - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains prototypes for event loop functions. - * - */ - -#ifndef UB_EVENT_H -#define UB_EVENT_H - -struct ub_event_base; -struct ub_event; -struct comm_base; -struct event_base; - -/** event timeout */ -#define UB_EV_TIMEOUT 0x01 -/** event fd readable */ -#define UB_EV_READ 0x02 -/** event fd writable */ -#define UB_EV_WRITE 0x04 -/** event signal */ -#define UB_EV_SIGNAL 0x08 -/** event must persist */ -#define UB_EV_PERSIST 0x10 - -/** Returns event-base type. Could be "mini-event", "winsock-event" for the - * daemon compile, and will be "pluggable-event" for - * libunbound. - */ -const char* ub_event_get_version(void); -/** Return the name, system and method for the pluggable event base */ -void ub_get_event_sys(struct ub_event_base*, const char** n, const char** s, - const char** m); -/** Return a default event base. In the daemon this will be the only event - * bases used. - */ -struct ub_event_base* ub_default_event_base(int, time_t*, struct timeval*); -/** Return an ub_event_base constructed for the given libevent event base */ -struct ub_event_base* ub_libevent_event_base(struct event_base*); -/** Return the libevent base underlying the given ub_event_base. Will return - * NULL when the ub_event_base does not have an underlying libevent event base - */ -struct event_base* ub_libevent_get_event_base(struct ub_event_base*); -/** Free event base. Free events yourself */ -void ub_event_base_free(struct ub_event_base*); -/** Run the event base */ -int ub_event_base_dispatch(struct ub_event_base*); -/** exit that loop */ -int ub_event_base_loopexit(struct ub_event_base*); - -/** Create a new ub_event for the event base */ -struct ub_event* ub_event_new(struct ub_event_base*, - int fd, short bits, void (*cb)(int, short, void*), void* arg); -/** Create a new ub_event signal for the event base */ -struct ub_event* ub_signal_new(struct ub_event_base*, int fd, - void (*cb)(int, short, void*), void* arg); -/** Create a new ub_event associated with the wsaevent for the event base */ -struct ub_event* ub_winsock_register_wsaevent(struct ub_event_base*, - void* wsaevent, void (*cb)(int, short, void*), void* arg); - -/** Add event bits for this event to fire on */ -void ub_event_add_bits(struct ub_event*, short bits); - /** Configure the event so it will not longer fire on given bits */ -void ub_event_del_bits(struct ub_event*, short bits); -/** Change or set the file descriptor on the event */ -void ub_event_set_fd(struct ub_event*, int fd); -/** free the event */ -void ub_event_free(struct ub_event*); -/** Activate the event. The given timeval is an timeout value. */ -int ub_event_add(struct ub_event*, struct timeval*); -/** Deactivate the event */ -int ub_event_del(struct ub_event*); -/** Reconfigure and activate a timeout event */ -int ub_timer_add(struct ub_event*, struct ub_event_base*, - void (*cb)(int, short, void*), void* arg, struct timeval*); -/** Deactivate the timeout event */ -int ub_timer_del(struct ub_event*); -/** Activate a signal event */ -int ub_signal_add(struct ub_event*, struct timeval*); -/** Deactivate a signal event */ -int ub_signal_del(struct ub_event*); -/** Free a with a wsaevent associated event */ -void ub_winsock_unregister_wsaevent(struct ub_event* ev); -/** Signal the eventloop when a TCP windows socket will block on next read - * or write (given by the eventbits) - */ -void ub_winsock_tcp_wouldblock(struct ub_event*, int bits); -/** Equip the comm_base with the current time */ -void ub_comm_base_now(struct comm_base* cb); - -#endif /* UB_EVENT_H */ diff --git a/crates/libunbound-sys/unbound/util/ub_event_pluggable.c b/crates/libunbound-sys/unbound/util/ub_event_pluggable.c deleted file mode 100644 index 4280d4db..00000000 --- a/crates/libunbound-sys/unbound/util/ub_event_pluggable.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * util/ub_event_pluggable.c - call registered pluggable event functions - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains an implementation for the indirection layer for pluggable - * events that calls the registered pluggable event loop. It also defines a - * default pluggable event loop based on the default libevent (compatibility) - * functions. - */ -#include "config.h" -#include -#include "util/ub_event.h" -#include "libunbound/unbound-event.h" -#include "util/netevent.h" -#include "util/log.h" -#include "util/fptr_wlist.h" - -/* We define libevent structures here to hide the libevent stuff. */ - -#ifdef USE_MINI_EVENT -# ifdef USE_WINSOCK -# include "util/winsock_event.h" -# else -# include "util/mini_event.h" -# endif /* USE_WINSOCK */ -#else /* USE_MINI_EVENT */ - /* we use libevent */ -# ifdef HAVE_EVENT_H -# include -# else -# include "event2/event.h" -# include "event2/event_struct.h" -# include "event2/event_compat.h" -# endif -#endif /* USE_MINI_EVENT */ - -#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \ - UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \ - UB_EV_PERSIST != EV_PERSIST -/* Only necessary for libev */ -# define NATIVE_BITS(b) ( \ - (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \ - | (((b) & UB_EV_READ ) ? EV_READ : 0) \ - | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \ - | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \ - | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0)) - -# define UB_EV_BITS(b) ( \ - (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \ - | (((b) & EV_READ ) ? UB_EV_READ : 0) \ - | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \ - | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \ - | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0)) - -# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \ - { (C)(fd, UB_EV_BITS(bits), arg); } - -UB_EV_BITS_CB(comm_point_udp_callback); -UB_EV_BITS_CB(comm_point_udp_ancil_callback) -UB_EV_BITS_CB(comm_point_tcp_accept_callback) -UB_EV_BITS_CB(comm_point_tcp_handle_callback) -UB_EV_BITS_CB(comm_timer_callback) -UB_EV_BITS_CB(comm_signal_callback) -UB_EV_BITS_CB(comm_point_local_handle_callback) -UB_EV_BITS_CB(comm_point_raw_handle_callback) -UB_EV_BITS_CB(tube_handle_signal) -UB_EV_BITS_CB(comm_base_handle_slow_accept) - -static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*) -{ - if(cb == comm_point_udp_callback) - return my_comm_point_udp_callback; - else if(cb == comm_point_udp_ancil_callback) - return my_comm_point_udp_ancil_callback; - else if(cb == comm_point_tcp_accept_callback) - return my_comm_point_tcp_accept_callback; - else if(cb == comm_point_tcp_handle_callback) - return my_comm_point_tcp_handle_callback; - else if(cb == comm_timer_callback) - return my_comm_timer_callback; - else if(cb == comm_signal_callback) - return my_comm_signal_callback; - else if(cb == comm_point_local_handle_callback) - return my_comm_point_local_handle_callback; - else if(cb == comm_point_raw_handle_callback) - return my_comm_point_raw_handle_callback; - else if(cb == tube_handle_signal) - return my_tube_handle_signal; - else if(cb == comm_base_handle_slow_accept) - return my_comm_base_handle_slow_accept; - else - return NULL; -} -#else -# define NATIVE_BITS(b) (b) -# define NATIVE_BITS_CB(c) (c) -#endif - -#ifndef EVFLAG_AUTO -#define EVFLAG_AUTO 0 -#endif - -struct my_event_base { - struct ub_event_base super; - struct event_base* base; -}; - -struct my_event { - struct ub_event super; - struct event ev; -}; - -#define AS_MY_EVENT_BASE(x) ((struct my_event_base*)x) -#define AS_MY_EVENT(x) ((struct my_event*)x) - -const char* ub_event_get_version(void) -{ - return "pluggable-event"PACKAGE_VERSION; -} - -static void -my_event_add_bits(struct ub_event* ev, short bits) -{ - AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits); -} - -static void -my_event_del_bits(struct ub_event* ev, short bits) -{ - AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits); -} - -static void -my_event_set_fd(struct ub_event* ev, int fd) -{ - AS_MY_EVENT(ev)->ev.ev_fd = fd; -} - -static void -my_event_free(struct ub_event* ev) -{ - free(AS_MY_EVENT(ev)); -} - -static int -my_event_add(struct ub_event* ev, struct timeval* tv) -{ - return event_add(&AS_MY_EVENT(ev)->ev, tv); -} - -static int -my_event_del(struct ub_event* ev) -{ - return event_del(&AS_MY_EVENT(ev)->ev); -} - -static int -my_timer_add(struct ub_event* ev, struct ub_event_base* base, - void (*cb)(int, short, void*), void* arg, struct timeval* tv) -{ - event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg); - if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev) - != 0) - return -1; - return evtimer_add(&AS_MY_EVENT(ev)->ev, tv); -} - -static int -my_timer_del(struct ub_event* ev) -{ - return evtimer_del(&AS_MY_EVENT(ev)->ev); -} - -static int -my_signal_add(struct ub_event* ev, struct timeval* tv) -{ - return signal_add(&AS_MY_EVENT(ev)->ev, tv); -} - -static int -my_signal_del(struct ub_event* ev) -{ - return signal_del(&AS_MY_EVENT(ev)->ev); -} - -static void -my_winsock_unregister_wsaevent(struct ub_event* ev) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev); - free(AS_MY_EVENT(ev)); -#else - (void)ev; -#endif -} - -static void -my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits)); -#else - (void)ev; - (void)eventbits; -#endif -} - -static struct ub_event_vmt default_event_vmt = { - my_event_add_bits, my_event_del_bits, my_event_set_fd, - my_event_free, my_event_add, my_event_del, - my_timer_add, my_timer_del, my_signal_add, my_signal_del, - my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock -}; - -static void -my_event_base_free(struct ub_event_base* base) -{ -#ifdef USE_MINI_EVENT - event_base_free(AS_MY_EVENT_BASE(base)->base); -#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE) - /* only libevent 1.2+ has it, but in 1.2 it is broken - - assertion fails on signal handling ev that is not deleted - in libevent 1.3c (event_base_once appears) this is fixed. */ - event_base_free(AS_MY_EVENT_BASE(base)->base); -#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */ - free(AS_MY_EVENT_BASE(base)); -} - -static int -my_event_base_dispatch(struct ub_event_base* base) -{ - return event_base_dispatch(AS_MY_EVENT_BASE(base)->base); -} - -static int -my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv) -{ - return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv); -} - -static struct ub_event* -my_event_new(struct ub_event_base* base, int fd, short bits, - void (*cb)(int, short, void*), void* arg) -{ - struct my_event *my_ev = (struct my_event*)calloc(1, - sizeof(struct my_event)); - - if (!my_ev) - return NULL; - - event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg); - if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) { - free(my_ev); - return NULL; - } - my_ev->super.magic = UB_EVENT_MAGIC; - my_ev->super.vmt = &default_event_vmt; - return &my_ev->super; -} - -static struct ub_event* -my_signal_new(struct ub_event_base* base, int fd, - void (*cb)(int, short, void*), void* arg) -{ - struct my_event *my_ev = (struct my_event*)calloc(1, - sizeof(struct my_event)); - - if (!my_ev) - return NULL; - - signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg); - if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) { - free(my_ev); - return NULL; - } - my_ev->super.magic = UB_EVENT_MAGIC; - my_ev->super.vmt = &default_event_vmt; - return &my_ev->super; -} - -static struct ub_event* -my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent, - void (*cb)(int, short, void*), void* arg) -{ -#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) - struct my_event *my_ev = (struct my_event*)calloc(1, - sizeof(struct my_event)); - - if (!my_ev) - return NULL; - - if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base, - &my_ev->ev, wsaevent, cb, arg)) { - free(my_ev); - return NULL; - - } - my_ev->super.magic = UB_EVENT_MAGIC; - my_ev->super.vmt = &default_event_vmt; - return &my_ev->super; -#else - (void)base; - (void)wsaevent; - (void)cb; - (void)arg; - return NULL; -#endif -} - -static struct ub_event_base_vmt default_event_base_vmt = { - my_event_base_free, my_event_base_dispatch, - my_event_base_loopexit, my_event_new, my_signal_new, - my_winsock_register_wsaevent -}; - -struct ub_event_base* -ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv) -{ - struct my_event_base* my_base = (struct my_event_base*)calloc(1, - sizeof(struct my_event_base)); - - if (!my_base) - return NULL; - -#ifdef USE_MINI_EVENT - (void)sigs; - /* use mini event time-sharing feature */ - my_base->base = event_init(time_secs, time_tv); -#else - (void)time_secs; - (void)time_tv; -# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) - /* libev */ - if(sigs) - my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO); - else - my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO); -# else - (void)sigs; -# ifdef HAVE_EVENT_BASE_NEW - my_base->base = event_base_new(); -# else - my_base->base = event_init(); -# endif -# endif -#endif - if (!my_base->base) { - free(my_base); - return NULL; - } - my_base->super.magic = UB_EVENT_MAGIC; - my_base->super.vmt = &default_event_base_vmt; - return &my_base->super; -} - -struct ub_event_base* -ub_libevent_event_base(struct event_base* base) -{ -#ifdef USE_MINI_EVENT - (void)base; - return NULL; -#else - struct my_event_base* my_base = (struct my_event_base*)calloc(1, - sizeof(struct my_event_base)); - - if (!my_base) - return NULL; - my_base->super.magic = UB_EVENT_MAGIC; - my_base->super.vmt = &default_event_base_vmt; - my_base->base = base; - return &my_base->super; -#endif -} - -struct event_base* -ub_libevent_get_event_base(struct ub_event_base* base) -{ -#ifndef USE_MINI_EVENT - if (base->vmt == &default_event_base_vmt) - return AS_MY_EVENT_BASE(base)->base; -#else - (void)base; -#endif - return NULL; -} - -#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT) -static const char* ub_ev_backend2str_pluggable(int b) -{ - switch(b) { - case EVBACKEND_SELECT: return "select"; - case EVBACKEND_POLL: return "poll"; - case EVBACKEND_EPOLL: return "epoll"; - case EVBACKEND_KQUEUE: return "kqueue"; - case EVBACKEND_DEVPOLL: return "devpoll"; - case EVBACKEND_PORT: return "evport"; - } - return "unknown"; -} -#endif - -void -ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s, - const char** m) -{ -#ifdef USE_WINSOCK - (void)ub_base; - *n = "pluggable-event"; - *s = "winsock"; - *m = "WSAWaitForMultipleEvents"; -#elif defined(USE_MINI_EVENT) - (void)ub_base; - *n = "pluggable-event"; - *s = "internal"; - *m = "select"; -#else - struct event_base* b = ub_libevent_get_event_base(ub_base); - /* This function is only called from comm_base_create, so - * ub_base is guaranteed to exist and to be the default - * event base. - */ - assert(b != NULL); - *n = "pluggable-event"; - *s = event_get_version(); -# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) - *n = "pluggable-libev"; -# ifdef EVBACKEND_SELECT - *m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b)); -# else - *m = "not obtainable"; -# endif -# elif defined(HAVE_EVENT_BASE_GET_METHOD) - *n = "pluggable-libevent"; - *m = event_base_get_method(b); -# else - *m = "not obtainable"; -# endif -#endif -} - -void -ub_event_base_free(struct ub_event_base* base) -{ - if (base && base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->free == my_event_base_free); - (*base->vmt->free)(base); - } -} - -int -ub_event_base_dispatch(struct ub_event_base* base) -{ - if (base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->dispatch == my_event_base_dispatch); - return (*base->vmt->dispatch)(base); - } - return -1; -} - -int -ub_event_base_loopexit(struct ub_event_base* base) -{ - if (base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->loopexit == my_event_base_loopexit); - return (*base->vmt->loopexit)(base, NULL); - } - return -1; -} - -struct ub_event* -ub_event_new(struct ub_event_base* base, int fd, short bits, - void (*cb)(int, short, void*), void* arg) -{ - if (base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->new_event == my_event_new); - return (*base->vmt->new_event)(base, fd, bits, cb, arg); - } - return NULL; -} - -struct ub_event* -ub_signal_new(struct ub_event_base* base, int fd, - void (*cb)(int, short, void*), void* arg) -{ - if (base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->new_signal == my_signal_new); - return (*base->vmt->new_signal)(base, fd, cb, arg); - } - return NULL; -} - -struct ub_event* -ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent, - void (*cb)(int, short, void*), void* arg) -{ - if (base->magic == UB_EVENT_MAGIC) { - fptr_ok(base->vmt != &default_event_base_vmt || - base->vmt->winsock_register_wsaevent == - my_winsock_register_wsaevent); - return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg); - } - return NULL; -} - -void -ub_event_add_bits(struct ub_event* ev, short bits) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->add_bits == my_event_add_bits); - (*ev->vmt->add_bits)(ev, bits); - } -} - -void -ub_event_del_bits(struct ub_event* ev, short bits) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->del_bits == my_event_del_bits); - (*ev->vmt->del_bits)(ev, bits); - } -} - -void -ub_event_set_fd(struct ub_event* ev, int fd) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->set_fd == my_event_set_fd); - (*ev->vmt->set_fd)(ev, fd); - } -} - -void -ub_event_free(struct ub_event* ev) -{ - if (ev && ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->free == my_event_free); - (*ev->vmt->free)(ev); - } -} - -int -ub_event_add(struct ub_event* ev, struct timeval* tv) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->add == my_event_add); - return (*ev->vmt->add)(ev, tv); - } - return -1; -} - -int -ub_event_del(struct ub_event* ev) -{ - if (ev && ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->del == my_event_del); - return (*ev->vmt->del)(ev); - } - return -1; -} - -int -ub_timer_add(struct ub_event* ev, struct ub_event_base* base, - void (*cb)(int, short, void*), void* arg, struct timeval* tv) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->add_timer == my_timer_add); - return (*ev->vmt->add_timer)(ev, base, cb, arg, tv); - } - return -1; -} - -int -ub_timer_del(struct ub_event* ev) -{ - if (ev && ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->del_timer == my_timer_del); - return (*ev->vmt->del_timer)(ev); - } - return -1; -} - -int -ub_signal_add(struct ub_event* ev, struct timeval* tv) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->add_signal == my_signal_add); - return (*ev->vmt->add_signal)(ev, tv); - } - return -1; -} - -int -ub_signal_del(struct ub_event* ev) -{ - if (ev && ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->del_signal == my_signal_del); - return (*ev->vmt->del_signal)(ev); - } - return -1; -} - -void -ub_winsock_unregister_wsaevent(struct ub_event* ev) -{ - if (ev && ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->winsock_unregister_wsaevent == - my_winsock_unregister_wsaevent); - (*ev->vmt->winsock_unregister_wsaevent)(ev); - } -} - -void -ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits) -{ - if (ev->magic == UB_EVENT_MAGIC) { - fptr_ok(ev->vmt != &default_event_vmt || - ev->vmt->winsock_tcp_wouldblock == - my_winsock_tcp_wouldblock); - if (ev->vmt->winsock_tcp_wouldblock) - (*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits); - } -} - -void ub_comm_base_now(struct comm_base* cb) -{ - time_t *tt; - struct timeval *tv; - -#ifdef USE_MINI_EVENT -/** minievent updates the time when it blocks. */ - if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC && - comm_base_internal(cb)->vmt == &default_event_base_vmt) - return; /* Actually using mini event, so do not set time */ -#endif /* USE_MINI_EVENT */ - -/** fillup the time values in the event base */ - comm_base_timept(cb, &tt, &tv); - if(gettimeofday(tv, NULL) < 0) { - log_err("gettimeofday: %s", strerror(errno)); - } -#ifndef S_SPLINT_S - *tt = tv->tv_sec; -#endif -} - diff --git a/crates/libunbound-sys/unbound/util/winsock_event.c b/crates/libunbound-sys/unbound/util/winsock_event.c deleted file mode 100644 index de6c28ec..00000000 --- a/crates/libunbound-sys/unbound/util/winsock_event.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * util/winsock_event.c - implementation of the unbound winsock event handler. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/** - * \file - * Implementation of the unbound WinSock2 API event notification handler - * for the Windows port. - */ - -#include "config.h" -#ifdef USE_WINSOCK -#include -#ifdef HAVE_TIME_H -#include -#endif -#include -#include "util/winsock_event.h" -#include "util/fptr_wlist.h" - -int mini_ev_cmp(const void* a, const void* b) -{ - const struct event *e = (const struct event*)a; - const struct event *f = (const struct event*)b; - if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) - return -1; - if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) - return 1; - if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) - return -1; - if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) - return 1; - if(e < f) - return -1; - if(e > f) - return 1; - return 0; -} - -/** set time */ -static int -settime(struct event_base* base) -{ - if(gettimeofday(base->time_tv, NULL) < 0) { - return -1; - } -#ifndef S_SPLINT_S - *base->time_secs = (time_t)base->time_tv->tv_sec; -#endif - return 0; -} - -#ifdef UNBOUND_DEBUG -/** - * Find a fd in the list of items. - * Note that not all items have a fd associated (those are -1). - * Signals are stored separately, and not searched. - * @param base: event base to look in. - * @param fd: what socket to look for. - * @return the index in the array, or -1 on failure. - */ -static int -find_fd(struct event_base* base, int fd) -{ - int i; - for(i=0; imax; i++) { - if(base->items[i]->ev_fd == fd) - return i; - } - return -1; -} -#endif - -/** Find ptr in base array */ -static void -zero_waitfor(WSAEVENT waitfor[], WSAEVENT x) -{ - int i; - for(i=0; itime_secs = time_secs; - base->time_tv = time_tv; - if(settime(base) < 0) { - event_base_free(base); - return NULL; - } - base->items = (struct event**)calloc(WSK_MAX_ITEMS, - sizeof(struct event*)); - if(!base->items) { - event_base_free(base); - return NULL; - } - base->cap = WSK_MAX_ITEMS; - base->max = 0; - base->times = rbtree_create(mini_ev_cmp); - if(!base->times) { - event_base_free(base); - return NULL; - } - base->signals = (struct event**)calloc(MAX_SIG, sizeof(struct event*)); - if(!base->signals) { - event_base_free(base); - return NULL; - } - base->tcp_stickies = 0; - base->tcp_reinvigorated = 0; - verbose(VERB_CLIENT, "winsock_event inited"); - return base; -} - -const char *event_get_version(void) -{ - return "winsock-event-"PACKAGE_VERSION; -} - -const char *event_get_method(void) -{ - return "WSAWaitForMultipleEvents"; -} - -/** call timeouts handlers, and return how long to wait for next one or -1 */ -static void handle_timeouts(struct event_base* base, struct timeval* now, - struct timeval* wait) -{ - struct event* p; -#ifndef S_SPLINT_S - wait->tv_sec = (time_t)-1; -#endif - verbose(VERB_CLIENT, "winsock_event handle_timeouts"); - - while((rbnode_type*)(p = (struct event*)rbtree_first(base->times)) - !=RBTREE_NULL) { -#ifndef S_SPLINT_S - if(p->ev_timeout.tv_sec > now->tv_sec || - (p->ev_timeout.tv_sec==now->tv_sec && - p->ev_timeout.tv_usec > now->tv_usec)) { - /* there is a next larger timeout. wait for it */ - wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; - if(now->tv_usec > p->ev_timeout.tv_usec) { - wait->tv_sec--; - wait->tv_usec = 1000000 - (now->tv_usec - - p->ev_timeout.tv_usec); - } else { - wait->tv_usec = p->ev_timeout.tv_usec - - now->tv_usec; - } - verbose(VERB_CLIENT, "winsock_event wait=" ARG_LL "d.%6.6d", - (long long)wait->tv_sec, (int)wait->tv_usec); - return; - } -#endif - /* event times out, remove it */ - (void)rbtree_delete(base->times, p); - p->ev_events &= ~EV_TIMEOUT; - fptr_ok(fptr_whitelist_event(p->ev_callback)); - (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); - } - verbose(VERB_CLIENT, "winsock_event wait=(-1)"); -} - -/** handle is_signal events and see if signalled */ -static void handle_signal(struct event* ev) -{ - DWORD ret; - log_assert(ev->is_signal && ev->hEvent); - /* see if the event is signalled */ - ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */, - 0 /* return immediately */, 0 /* not alertable for IOcomple*/); - if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) { - log_err("WSAWaitForMultipleEvents(signal) failed: %s", - wsa_strerror(WSAGetLastError())); - return; - } - if(ret == WSA_WAIT_TIMEOUT) { - /* not signalled */ - return; - } - - /* reset the signal */ - if(!WSAResetEvent(ev->hEvent)) - log_err("WSAResetEvent failed: %s", - wsa_strerror(WSAGetLastError())); - /* do the callback (which may set the signal again) */ - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - (*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg); -} - -/** call select and callbacks for that */ -static int handle_select(struct event_base* base, struct timeval* wait) -{ - DWORD timeout = 0; /* in milliseconds */ - DWORD ret; - struct event* eventlist[WSK_MAX_ITEMS]; - WSANETWORKEVENTS netev; - int i, numwait = 0, startidx = 0, was_timeout = 0; - int newstickies = 0; - struct timeval nultm; - - verbose(VERB_CLIENT, "winsock_event handle_select"); - -#ifndef S_SPLINT_S - if(wait->tv_sec==(time_t)-1) - wait = NULL; - if(wait) - timeout = wait->tv_sec*1000 + wait->tv_usec/1000; - if(base->tcp_stickies) { - wait = &nultm; - nultm.tv_sec = 0; - nultm.tv_usec = 0; - timeout = 0; /* no waiting, we have sticky events */ - } -#endif - - /* prepare event array */ - for(i=0; imax; i++) { - if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal) - continue; /* skip timer only events */ - eventlist[numwait] = base->items[i]; - base->waitfor[numwait++] = base->items[i]->hEvent; - if(numwait == WSK_MAX_ITEMS) - break; /* sanity check */ - } - log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS); - verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%s " - "timeout=%d", base->max, numwait, (wait?"":""), - (int)timeout); - - /* do the wait */ - if(numwait == 0) { - /* WSAWaitFor.. doesn't like 0 event objects */ - if(wait) { - Sleep(timeout); - } - was_timeout = 1; - } else { - ret = WSAWaitForMultipleEvents(numwait, base->waitfor, - 0 /* do not wait for all, just one will do */, - wait?timeout:WSA_INFINITE, - 0); /* we are not alertable (IO completion events) */ - if(ret == WSA_WAIT_IO_COMPLETION) { - log_err("WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION"); - return -1; - } else if(ret == WSA_WAIT_FAILED) { - log_err("WSAWaitForMultipleEvents failed: %s", - wsa_strerror(WSAGetLastError())); - return -1; - } else if(ret == WSA_WAIT_TIMEOUT) { - was_timeout = 1; - } else - startidx = ret - WSA_WAIT_EVENT_0; - } - verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", - was_timeout, startidx); - - /* get new time after wait */ - if(settime(base) < 0) - return -1; - - /* callbacks */ - if(base->tcp_stickies) - startidx = 0; /* process all events, some are sticky */ - for(i=startidx; ijust_checked = 1; - - verbose(VERB_CLIENT, "winsock_event signals"); - for(i=startidx; iwaitfor[i]) - continue; /* was deleted */ - if(eventlist[i]->is_signal) { - eventlist[i]->just_checked = 0; - handle_signal(eventlist[i]); - } - } - /* early exit - do not process network, exit quickly */ - if(base->need_to_exit) - return 0; - - verbose(VERB_CLIENT, "winsock_event net"); - for(i=startidx; iwaitfor[i]) - continue; /* was deleted */ - if(!eventlist[i]->just_checked) - continue; /* added by other callback */ - if(eventlist[i]->is_signal) - continue; /* not a network event at all */ - eventlist[i]->just_checked = 0; - - if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, - base->waitfor[i], /* reset the event handle */ - /*NULL,*/ /* do not reset the event handle */ - &netev) != 0) { - log_err("WSAEnumNetworkEvents failed: %s", - wsa_strerror(WSAGetLastError())); - return -1; - } - if((netev.lNetworkEvents & FD_READ)) { - if(netev.iErrorCode[FD_READ_BIT] != 0) - verbose(VERB_ALGO, "FD_READ_BIT error: %s", - wsa_strerror(netev.iErrorCode[FD_READ_BIT])); - bits |= EV_READ; - } - if((netev.lNetworkEvents & FD_WRITE)) { - if(netev.iErrorCode[FD_WRITE_BIT] != 0) - verbose(VERB_ALGO, "FD_WRITE_BIT error: %s", - wsa_strerror(netev.iErrorCode[FD_WRITE_BIT])); - bits |= EV_WRITE; - } - if((netev.lNetworkEvents & FD_CONNECT)) { - if(netev.iErrorCode[FD_CONNECT_BIT] != 0) - verbose(VERB_ALGO, "FD_CONNECT_BIT error: %s", - wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT])); - bits |= EV_READ; - bits |= EV_WRITE; - } - if((netev.lNetworkEvents & FD_ACCEPT)) { - if(netev.iErrorCode[FD_ACCEPT_BIT] != 0) - verbose(VERB_ALGO, "FD_ACCEPT_BIT error: %s", - wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT])); - bits |= EV_READ; - } - if((netev.lNetworkEvents & FD_CLOSE)) { - if(netev.iErrorCode[FD_CLOSE_BIT] != 0) - verbose(VERB_ALGO, "FD_CLOSE_BIT error: %s", - wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT])); - bits |= EV_READ; - bits |= EV_WRITE; - } - if(eventlist[i]->is_tcp && eventlist[i]->stick_events) { - verbose(VERB_ALGO, "winsock %d pass sticky %s%s", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); - bits |= eventlist[i]->old_events; - } - if(eventlist[i]->is_tcp && bits) { - eventlist[i]->old_events = bits; - eventlist[i]->stick_events = 1; - if((eventlist[i]->ev_events & bits)) { - newstickies = 1; - } - verbose(VERB_ALGO, "winsock %d store sticky %s%s", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); - } - if((bits & eventlist[i]->ev_events)) { - verbose(VERB_ALGO, "winsock event callback %p fd=%d " - "%s%s%s%s%s ; %s%s%s", - eventlist[i], eventlist[i]->ev_fd, - (netev.lNetworkEvents&FD_READ)?" FD_READ":"", - (netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"", - (netev.lNetworkEvents&FD_CONNECT)? - " FD_CONNECT":"", - (netev.lNetworkEvents&FD_ACCEPT)? - " FD_ACCEPT":"", - (netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"", - (bits&EV_READ)?" EV_READ":"", - (bits&EV_WRITE)?" EV_WRITE":"", - (bits&EV_TIMEOUT)?" EV_TIMEOUT":""); - - fptr_ok(fptr_whitelist_event( - eventlist[i]->ev_callback)); - (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd, - bits & eventlist[i]->ev_events, - eventlist[i]->ev_arg); - } - if(eventlist[i]->is_tcp && bits) - verbose(VERB_ALGO, "winsock %d got sticky %s%s", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); - } - verbose(VERB_CLIENT, "winsock_event net"); - if(base->tcp_reinvigorated) { - verbose(VERB_CLIENT, "winsock_event reinvigorated"); - base->tcp_reinvigorated = 0; - newstickies = 1; - } - base->tcp_stickies = newstickies; - verbose(VERB_CLIENT, "winsock_event handle_select end"); - return 0; -} - -int event_base_dispatch(struct event_base *base) -{ - struct timeval wait; - if(settime(base) < 0) - return -1; - while(!base->need_to_exit) - { - /* see if timeouts need handling */ - handle_timeouts(base, base->time_tv, &wait); - if(base->need_to_exit) - return 0; - /* do select */ - if(handle_select(base, &wait) < 0) { - if(base->need_to_exit) - return 0; - return -1; - } - } - return 0; -} - -int event_base_loopexit(struct event_base *base, - struct timeval * ATTR_UNUSED(tv)) -{ - verbose(VERB_CLIENT, "winsock_event loopexit"); - base->need_to_exit = 1; - return 0; -} - -void event_base_free(struct event_base *base) -{ - verbose(VERB_CLIENT, "winsock_event event_base_free"); - if(!base) - return; - free(base->items); - free(base->times); - free(base->signals); - free(base); -} - -void event_set(struct event *ev, int fd, short bits, - void (*cb)(int, short, void *), void *arg) -{ - ev->node.key = ev; - ev->ev_fd = fd; - ev->ev_events = bits; - ev->ev_callback = cb; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - ev->ev_arg = arg; - ev->just_checked = 0; - ev->added = 0; -} - -int event_base_set(struct event_base *base, struct event *ev) -{ - ev->ev_base = base; - ev->old_events = 0; - ev->stick_events = 0; - ev->added = 0; - return 0; -} - -int event_add(struct event *ev, struct timeval *tv) -{ - verbose(VERB_ALGO, "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s", - ev, ev->added, ev->ev_fd, - (tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1), - (ev->ev_events&EV_READ)?" EV_READ":"", - (ev->ev_events&EV_WRITE)?" EV_WRITE":"", - (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); - if(ev->added) - event_del(ev); - log_assert(ev->ev_fd==-1 || find_fd(ev->ev_base, ev->ev_fd) == -1); - ev->is_tcp = 0; - ev->is_signal = 0; - ev->just_checked = 0; - - if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - BOOL b=0; - int t, l; - long events = 0; - - if(ev->ev_base->max == ev->ev_base->cap) - return -1; - ev->idx = ev->ev_base->max++; - ev->ev_base->items[ev->idx] = ev; - - if( (ev->ev_events&EV_READ) ) - events |= FD_READ; - if( (ev->ev_events&EV_WRITE) ) - events |= FD_WRITE; - l = sizeof(t); - if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE, - (void*)&t, &l) != 0) - log_err("getsockopt(SO_TYPE) failed: %s", - wsa_strerror(WSAGetLastError())); - if(t == SOCK_STREAM) { - /* TCP socket */ - ev->is_tcp = 1; - events |= FD_CLOSE; - if( (ev->ev_events&EV_WRITE) ) - events |= FD_CONNECT; - l = sizeof(b); - if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN, - (void*)&b, &l) != 0) - log_err("getsockopt(SO_ACCEPTCONN) failed: %s", - wsa_strerror(WSAGetLastError())); - if(b) /* TCP accept socket */ - events |= FD_ACCEPT; - } - ev->hEvent = WSACreateEvent(); - if(ev->hEvent == WSA_INVALID_EVENT) - log_err("WSACreateEvent failed: %s", - wsa_strerror(WSAGetLastError())); - /* automatically sets fd to nonblocking mode. - * nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */ - if(WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) { - log_err("WSAEventSelect failed: %s", - wsa_strerror(WSAGetLastError())); - } - if(ev->is_tcp && ev->stick_events && - (ev->ev_events & ev->old_events)) { - /* go to processing the sticky event right away */ - ev->ev_base->tcp_reinvigorated = 1; - } - } - - if(tv && (ev->ev_events&EV_TIMEOUT)) { -#ifndef S_SPLINT_S - struct timeval *now = ev->ev_base->time_tv; - ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; - ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; - while(ev->ev_timeout.tv_usec >= 1000000) { - ev->ev_timeout.tv_usec -= 1000000; - ev->ev_timeout.tv_sec++; - } -#endif - (void)rbtree_insert(ev->ev_base->times, &ev->node); - } - ev->added = 1; - return 0; -} - -int event_del(struct event *ev) -{ - verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=" ARG_LL "d %s%s%s", - ev, ev->added, ev->ev_fd, - (ev->ev_events&EV_TIMEOUT)?(long long)ev->ev_timeout.tv_sec*1000+ - (long long)ev->ev_timeout.tv_usec/1000:-1, - (ev->ev_events&EV_READ)?" EV_READ":"", - (ev->ev_events&EV_WRITE)?" EV_WRITE":"", - (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); - if(!ev->added) - return 0; - log_assert(ev->added); - if((ev->ev_events&EV_TIMEOUT)) - (void)rbtree_delete(ev->ev_base->times, &ev->node); - if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - log_assert(ev->ev_base->max > 0); - /* remove item and compact the list */ - ev->ev_base->items[ev->idx] = - ev->ev_base->items[ev->ev_base->max-1]; - ev->ev_base->items[ev->ev_base->max-1] = NULL; - ev->ev_base->max--; - if(ev->idx < ev->ev_base->max) - ev->ev_base->items[ev->idx]->idx = ev->idx; - zero_waitfor(ev->ev_base->waitfor, ev->hEvent); - - if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0) - log_err("WSAEventSelect(disable) failed: %s", - wsa_strerror(WSAGetLastError())); - if(!WSACloseEvent(ev->hEvent)) - log_err("WSACloseEvent failed: %s", - wsa_strerror(WSAGetLastError())); - } - ev->just_checked = 0; - ev->added = 0; - return 0; -} - -/** which base gets to handle signals */ -static struct event_base* signal_base = NULL; -/** signal handler */ -static RETSIGTYPE sigh(int sig) -{ - struct event* ev; - if(!signal_base || sig < 0 || sig >= MAX_SIG) - return; - ev = signal_base->signals[sig]; - if(!ev) - return; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - (*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg); -} - -int signal_add(struct event *ev, struct timeval * ATTR_UNUSED(tv)) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - signal_base = ev->ev_base; - ev->ev_base->signals[ev->ev_fd] = ev; - ev->added = 1; - if(signal(ev->ev_fd, sigh) == SIG_ERR) { - return -1; - } - return 0; -} - -int signal_del(struct event *ev) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - ev->ev_base->signals[ev->ev_fd] = NULL; - ev->added = 0; - return 0; -} - -void winsock_tcp_wouldblock(struct event* ev, int eventbits) -{ - verbose(VERB_ALGO, "winsock: tcp wouldblock %s", - eventbits==EV_READ?"EV_READ":"EV_WRITE"); - ev->old_events &= (~eventbits); - if(ev->old_events == 0) - ev->stick_events = 0; - /* in case this is the last sticky event, we could - * possibly run an empty handler loop to reset the base - * tcp_stickies variable - */ -} - -int winsock_register_wsaevent(struct event_base* base, struct event* ev, - WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg) -{ - if(base->max == base->cap) - return 0; - memset(ev, 0, sizeof(*ev)); - ev->ev_fd = -1; - ev->ev_events = EV_READ; - ev->ev_callback = cb; - ev->ev_arg = arg; - ev->is_signal = 1; - ev->hEvent = wsaevent; - ev->added = 1; - ev->ev_base = base; - ev->idx = ev->ev_base->max++; - ev->ev_base->items[ev->idx] = ev; - return 1; -} - -void winsock_unregister_wsaevent(struct event* ev) -{ - if(!ev || !ev->added) return; - log_assert(ev->added && ev->ev_base->max > 0) - /* remove item and compact the list */ - ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1]; - ev->ev_base->items[ev->ev_base->max-1] = NULL; - ev->ev_base->max--; - if(ev->idx < ev->ev_base->max) - ev->ev_base->items[ev->idx]->idx = ev->idx; - ev->added = 0; -} - -#else /* USE_WINSOCK */ -/** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */ -int winsock_unused_symbol = 1; -#endif /* USE_WINSOCK */ diff --git a/crates/libunbound-sys/unbound/util/winsock_event.h b/crates/libunbound-sys/unbound/util/winsock_event.h deleted file mode 100644 index d6dafac8..00000000 --- a/crates/libunbound-sys/unbound/util/winsock_event.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * util/winsock_event.h - unbound event handling for winsock on windows - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains interface functions with the WinSock2 API on Windows. - * It uses the winsock WSAWaitForMultipleEvents interface on a number of - * sockets. - * - * Note that windows can only wait for max 64 events at one time. - * - * Also, file descriptors cannot be waited for. - * - * Named pipes are not easily available (and are not usable in select() ). - * For interprocess communication, it is possible to wait for a hEvent to - * be signaled by another thread. - * - * When a socket becomes readable, then it will not be flagged as - * readable again until you have gotten WOULDBLOCK from a recv routine. - * That means the event handler must store the readability (edge notify) - * and process the incoming data until it blocks. - * The function performing recv then has to inform the event handler that - * the socket has blocked, and the event handler can mark it as such. - * Thus, this file transforms the edge notify from windows to a level notify - * that is compatible with UNIX. - * The WSAEventSelect page says that it does do level notify, as long - * as you call a recv/write/accept at least once when it is signalled. - * This last bit is not true, even though documented in server2008 api docs - * from microsoft, it does not happen at all. Instead you have to test for - * WSAEWOULDBLOCK on a tcp stream, and only then retest the socket. - * And before that remember the previous result as still valid. - * - * To stay 'fair', instead of emptying a socket completely, the event handler - * can test the other (marked as blocking) sockets for new events. - * - * Additionally, TCP accept sockets get special event support. - * - * Socket numbers are not starting small, they can be any number (say 33060). - * Therefore, bitmaps are not used, but arrays. - * - * on winsock, you must use recv() and send() for TCP reads and writes, - * not read() and write(), those work only on files. - * - * Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode. - * - * When under a high load windows gives out lots of errors, from recvfrom - * on udp sockets for example (WSAECONNRESET). Even though the udp socket - * has no connection per se. - */ - -#ifndef UTIL_WINSOCK_EVENT_H -#define UTIL_WINSOCK_EVENT_H - -#ifdef USE_WINSOCK - -#ifndef HAVE_EVENT_BASE_FREE -#define HAVE_EVENT_BASE_FREE -#endif - -/* redefine the calls to different names so that there is no name - * collision with other code that uses libevent names. (that uses libunbound)*/ -#define event_init winsockevent_init -#define event_get_version winsockevent_get_version -#define event_get_method winsockevent_get_method -#define event_base_dispatch winsockevent_base_dispatch -#define event_base_loopexit winsockevent_base_loopexit -#define event_base_free winsockevent_base_free -#define event_set winsockevent_set -#define event_base_set winsockevent_base_set -#define event_add winsockevent_add -#define event_del winsockevent_del -#define signal_add winsocksignal_add -#define signal_del winsocksignal_del - -/** event timeout */ -#define EV_TIMEOUT 0x01 -/** event fd readable */ -#define EV_READ 0x02 -/** event fd writable */ -#define EV_WRITE 0x04 -/** event signal */ -#define EV_SIGNAL 0x08 -/** event must persist */ -#define EV_PERSIST 0x10 - -/* needs our redblack tree */ -#include "rbtree.h" - -/** max number of signals to support */ -#define MAX_SIG 32 - -/** The number of items that the winsock event handler can service. - * Windows cannot handle more anyway */ -#define WSK_MAX_ITEMS 64 - -/** - * event base for winsock event handler - */ -struct event_base -{ - /** sorted by timeout (absolute), ptr */ - rbtree_type* times; - /** array (first part in use) of handles to work on */ - struct event** items; - /** number of items in use in array */ - int max; - /** capacity of array, size of array in items */ - int cap; - /** array of 0 - maxsig of ptr to event for it */ - struct event** signals; - /** if we need to exit */ - int need_to_exit; - /** where to store time in seconds */ - time_t* time_secs; - /** where to store time in microseconds */ - struct timeval* time_tv; - /** - * TCP streams have sticky events to them, these are not - * reported by the windows event system anymore, we have to - * keep reporting those events as present until wouldblock() is - * signalled by the handler back to use. - */ - int tcp_stickies; - /** - * should next cycle process reinvigorated stickies, - * these are stickies that have been stored, but due to a new - * event_add a sudden interest in the event has incepted. - */ - int tcp_reinvigorated; - /** The list of events that is currently being processed. */ - WSAEVENT waitfor[WSK_MAX_ITEMS]; -}; - -/** - * Event structure. Has some of the event elements. - */ -struct event { - /** node in timeout rbtree */ - rbnode_type node; - /** is event already added */ - int added; - - /** event base it belongs to */ - struct event_base *ev_base; - /** fd to poll or -1 for timeouts. signal number for sigs. */ - int ev_fd; - /** what events this event is interested in, see EV_.. above. */ - short ev_events; - /** timeout value */ - struct timeval ev_timeout; - - /** callback to call: fd, eventbits, userarg */ - void (*ev_callback)(int, short, void *); - /** callback user arg */ - void *ev_arg; - - /* ----- nonpublic part, for winsock_event only ----- */ - /** index of this event in the items array (if added) */ - int idx; - /** the event handle to wait for new events to become ready */ - WSAEVENT hEvent; - /** true if this filedes is a TCP socket and needs special attention */ - int is_tcp; - /** remembered EV_ values */ - short old_events; - /** should remembered EV_ values be used for TCP streams. - * Reset after WOULDBLOCK is signaled using the function. */ - int stick_events; - - /** true if this event is a signaling WSAEvent by the user. - * User created and user closed WSAEvent. Only signaled/unsignaled, - * no read/write/distinctions needed. */ - int is_signal; - /** used during callbacks to see which events were just checked */ - int just_checked; -}; - -/** create event base */ -void *event_init(time_t* time_secs, struct timeval* time_tv); -/** get version */ -const char *event_get_version(void); -/** get polling method (select,epoll) */ -const char *event_get_method(void); -/** run select in a loop */ -int event_base_dispatch(struct event_base *); -/** exit that loop */ -int event_base_loopexit(struct event_base *, struct timeval *); -/** free event base. Free events yourself */ -void event_base_free(struct event_base *); -/** set content of event */ -void event_set(struct event *, int, short, void (*)(int, short, void *), void *); - -/** add event to a base. You *must* call this for every event. */ -int event_base_set(struct event_base *, struct event *); -/** add event to make it active. You may not change it with event_set anymore */ -int event_add(struct event *, struct timeval *); -/** remove event. You may change it again */ -int event_del(struct event *); - -#define evtimer_add(ev, tv) event_add(ev, tv) -#define evtimer_del(ev) event_del(ev) - -/* uses different implementation. Cannot mix fd/timeouts and signals inside - * the same struct event. create several event structs for that. */ -/** install signal handler */ -int signal_add(struct event *, struct timeval *); -/** set signal event contents */ -#define signal_set(ev, x, cb, arg) \ - event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -/** remove signal handler */ -int signal_del(struct event *); - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int mini_ev_cmp(const void* a, const void* b); - -/** - * Routine for windows only, where the handling layer can signal that - * a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs - * retesting the event. - * Pass if EV_READ or EV_WRITE gave wouldblock. - */ -void winsock_tcp_wouldblock(struct event* ev, int eventbit); - -/** - * Routine for windows only. where you pass a signal WSAEvent that - * you wait for. When the event is signaled, the callback gets called. - * The callback has to WSAResetEvent to disable the signal. - * @param base: the event base. - * @param ev: the event structure for data storage - * can be passed uninitialised. - * @param wsaevent: the WSAEvent that gets signaled. - * @param cb: callback routine. - * @param arg: user argument to callback routine. - * @return false on error. - */ -int winsock_register_wsaevent(struct event_base* base, struct event* ev, - WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg); - -/** - * Unregister a wsaevent. User has to close the WSAEVENT itself. - * @param ev: event data storage. - */ -void winsock_unregister_wsaevent(struct event* ev); - -#endif /* USE_WINSOCK */ -#endif /* UTIL_WINSOCK_EVENT_H */ diff --git a/crates/libunbound-sys/unbound/validator/autotrust.c b/crates/libunbound-sys/unbound/validator/autotrust.c deleted file mode 100644 index 3011a0ac..00000000 --- a/crates/libunbound-sys/unbound/validator/autotrust.c +++ /dev/null @@ -1,2457 +0,0 @@ -/* - * validator/autotrust.c - RFC5011 trust anchor management for unbound. - * - * Copyright (c) 2009, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * Contains autotrust implementation. The implementation was taken from - * the autotrust daemon (BSD licensed), written by Matthijs Mekking. - * It was modified to fit into unbound. The state table process is the same. - */ -#include "config.h" -#include "validator/autotrust.h" -#include "validator/val_anchor.h" -#include "validator/val_utils.h" -#include "validator/val_sigcrypt.h" -#include "util/data/dname.h" -#include "util/data/packed_rrset.h" -#include "util/log.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "util/regional.h" -#include "util/random.h" -#include "util/data/msgparse.h" -#include "services/mesh.h" -#include "services/cache/rrset.h" -#include "validator/val_kcache.h" -#include "sldns/sbuffer.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" -#include "sldns/keyraw.h" -#include "sldns/rrdef.h" -#include -#include - -/** number of times a key must be seen before it can become valid */ -#define MIN_PENDINGCOUNT 2 - -/** Event: Revoked */ -static void do_revoked(struct module_env* env, struct autr_ta* anchor, int* c); - -struct autr_global_data* autr_global_create(void) -{ - struct autr_global_data* global; - global = (struct autr_global_data*)malloc(sizeof(*global)); - if(!global) - return NULL; - rbtree_init(&global->probe, &probetree_cmp); - return global; -} - -void autr_global_delete(struct autr_global_data* global) -{ - if(!global) - return; - /* elements deleted by parent */ - free(global); -} - -int probetree_cmp(const void* x, const void* y) -{ - struct trust_anchor* a = (struct trust_anchor*)x; - struct trust_anchor* b = (struct trust_anchor*)y; - log_assert(a->autr && b->autr); - if(a->autr->next_probe_time < b->autr->next_probe_time) - return -1; - if(a->autr->next_probe_time > b->autr->next_probe_time) - return 1; - /* time is equal, sort on trust point identity */ - return anchor_cmp(x, y); -} - -size_t -autr_get_num_anchors(struct val_anchors* anchors) -{ - size_t res = 0; - if(!anchors) - return 0; - lock_basic_lock(&anchors->lock); - if(anchors->autr) - res = anchors->autr->probe.count; - lock_basic_unlock(&anchors->lock); - return res; -} - -/** Position in string */ -static int -position_in_string(char *str, const char* sub) -{ - char* pos = strstr(str, sub); - if(pos) - return (int)(pos-str)+(int)strlen(sub); - return -1; -} - -/** Debug routine to print pretty key information */ -static void -verbose_key(struct autr_ta* ta, enum verbosity_value level, - const char* format, ...) ATTR_FORMAT(printf, 3, 4); - -/** - * Implementation of debug pretty key print - * @param ta: trust anchor key with DNSKEY data. - * @param level: verbosity level to print at. - * @param format: printf style format string. - */ -static void -verbose_key(struct autr_ta* ta, enum verbosity_value level, - const char* format, ...) -{ - va_list args; - va_start(args, format); - if(verbosity >= level) { - char* str = sldns_wire2str_dname(ta->rr, ta->dname_len); - int keytag = (int)sldns_calc_keytag_raw(sldns_wirerr_get_rdata( - ta->rr, ta->rr_len, ta->dname_len), - sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len, - ta->dname_len)); - char msg[MAXSYSLOGMSGLEN]; - vsnprintf(msg, sizeof(msg), format, args); - verbose(level, "%s key %d %s", str?str:"??", keytag, msg); - free(str); - } - va_end(args); -} - -/** - * Parse comments - * @param str: to parse - * @param ta: trust key autotrust metadata - * @return false on failure. - */ -static int -parse_comments(char* str, struct autr_ta* ta) -{ - int len = (int)strlen(str), pos = 0, timestamp = 0; - char* comment = (char*) malloc(sizeof(char)*len+1); - char* comments = comment; - if(!comment) { - log_err("malloc failure in parse"); - return 0; - } - /* skip over whitespace and data at start of line */ - while (*str != '\0' && *str != ';') - str++; - if (*str == ';') - str++; - /* copy comments */ - while (*str != '\0') - { - *comments = *str; - comments++; - str++; - } - *comments = '\0'; - - comments = comment; - - /* read state */ - pos = position_in_string(comments, "state="); - if (pos >= (int) strlen(comments)) - { - log_err("parse error"); - free(comment); - return 0; - } - if (pos <= 0) - ta->s = AUTR_STATE_VALID; - else - { - int s = (int) comments[pos] - '0'; - switch(s) - { - case AUTR_STATE_START: - case AUTR_STATE_ADDPEND: - case AUTR_STATE_VALID: - case AUTR_STATE_MISSING: - case AUTR_STATE_REVOKED: - case AUTR_STATE_REMOVED: - ta->s = s; - break; - default: - verbose_key(ta, VERB_OPS, "has undefined " - "state, considered NewKey"); - ta->s = AUTR_STATE_START; - break; - } - } - /* read pending count */ - pos = position_in_string(comments, "count="); - if (pos >= (int) strlen(comments)) - { - log_err("parse error"); - free(comment); - return 0; - } - if (pos <= 0) - ta->pending_count = 0; - else - { - comments += pos; - ta->pending_count = (uint8_t)atoi(comments); - } - - /* read last change */ - pos = position_in_string(comments, "lastchange="); - if (pos >= (int) strlen(comments)) - { - log_err("parse error"); - free(comment); - return 0; - } - if (pos >= 0) - { - comments += pos; - timestamp = atoi(comments); - } - if (pos < 0 || !timestamp) - ta->last_change = 0; - else - ta->last_change = (time_t)timestamp; - - free(comment); - return 1; -} - -/** Check if a line contains data (besides comments) */ -static int -str_contains_data(char* str, char comment) -{ - while (*str != '\0') { - if (*str == comment || *str == '\n') - return 0; - if (*str != ' ' && *str != '\t') - return 1; - str++; - } - return 0; -} - -/** Get DNSKEY flags - * rdata without rdatalen in front of it. */ -static int -dnskey_flags(uint16_t t, uint8_t* rdata, size_t len) -{ - uint16_t f; - if(t != LDNS_RR_TYPE_DNSKEY) - return 0; - if(len < 2) - return 0; - memmove(&f, rdata, 2); - f = ntohs(f); - return (int)f; -} - -/** Check if KSK DNSKEY. - * pass rdata without rdatalen in front of it */ -static int -rr_is_dnskey_sep(uint16_t t, uint8_t* rdata, size_t len) -{ - return (dnskey_flags(t, rdata, len)&DNSKEY_BIT_SEP); -} - -/** Check if TA is KSK DNSKEY */ -static int -ta_is_dnskey_sep(struct autr_ta* ta) -{ - return (dnskey_flags( - sldns_wirerr_get_type(ta->rr, ta->rr_len, ta->dname_len), - sldns_wirerr_get_rdata(ta->rr, ta->rr_len, ta->dname_len), - sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len, ta->dname_len) - ) & DNSKEY_BIT_SEP); -} - -/** Check if REVOKED DNSKEY - * pass rdata without rdatalen in front of it */ -static int -rr_is_dnskey_revoked(uint16_t t, uint8_t* rdata, size_t len) -{ - return (dnskey_flags(t, rdata, len)&LDNS_KEY_REVOKE_KEY); -} - -/** create ta */ -static struct autr_ta* -autr_ta_create(uint8_t* rr, size_t rr_len, size_t dname_len) -{ - struct autr_ta* ta = (struct autr_ta*)calloc(1, sizeof(*ta)); - if(!ta) { - free(rr); - return NULL; - } - ta->rr = rr; - ta->rr_len = rr_len; - ta->dname_len = dname_len; - return ta; -} - -/** create tp */ -static struct trust_anchor* -autr_tp_create(struct val_anchors* anchors, uint8_t* own, size_t own_len, - uint16_t dc) -{ - struct trust_anchor* tp = (struct trust_anchor*)calloc(1, sizeof(*tp)); - if(!tp) return NULL; - tp->name = memdup(own, own_len); - if(!tp->name) { - free(tp); - return NULL; - } - tp->namelen = own_len; - tp->namelabs = dname_count_labels(tp->name); - tp->node.key = tp; - tp->dclass = dc; - tp->autr = (struct autr_point_data*)calloc(1, sizeof(*tp->autr)); - if(!tp->autr) { - free(tp->name); - free(tp); - return NULL; - } - tp->autr->pnode.key = tp; - - lock_basic_lock(&anchors->lock); - if(!rbtree_insert(anchors->tree, &tp->node)) { - lock_basic_unlock(&anchors->lock); - log_err("trust anchor presented twice"); - free(tp->name); - free(tp->autr); - free(tp); - return NULL; - } - if(!rbtree_insert(&anchors->autr->probe, &tp->autr->pnode)) { - (void)rbtree_delete(anchors->tree, tp); - lock_basic_unlock(&anchors->lock); - log_err("trust anchor in probetree twice"); - free(tp->name); - free(tp->autr); - free(tp); - return NULL; - } - lock_basic_init(&tp->lock); - lock_protect(&tp->lock, tp, sizeof(*tp)); - lock_protect(&tp->lock, tp->autr, sizeof(*tp->autr)); - lock_basic_unlock(&anchors->lock); - return tp; -} - -/** delete assembled rrsets */ -static void -autr_rrset_delete(struct ub_packed_rrset_key* r) -{ - if(r) { - free(r->rk.dname); - free(r->entry.data); - free(r); - } -} - -void autr_point_delete(struct trust_anchor* tp) -{ - if(!tp) - return; - lock_unprotect(&tp->lock, tp); - lock_unprotect(&tp->lock, tp->autr); - lock_basic_destroy(&tp->lock); - autr_rrset_delete(tp->ds_rrset); - autr_rrset_delete(tp->dnskey_rrset); - if(tp->autr) { - struct autr_ta* p = tp->autr->keys, *np; - while(p) { - np = p->next; - free(p->rr); - free(p); - p = np; - } - free(tp->autr->file); - free(tp->autr); - } - free(tp->name); - free(tp); -} - -/** find or add a new trust point for autotrust */ -static struct trust_anchor* -find_add_tp(struct val_anchors* anchors, uint8_t* rr, size_t rr_len, - size_t dname_len) -{ - struct trust_anchor* tp; - tp = anchor_find(anchors, rr, dname_count_labels(rr), dname_len, - sldns_wirerr_get_class(rr, rr_len, dname_len)); - if(tp) { - if(!tp->autr) { - log_err("anchor cannot be with and without autotrust"); - lock_basic_unlock(&tp->lock); - return NULL; - } - return tp; - } - tp = autr_tp_create(anchors, rr, dname_len, sldns_wirerr_get_class(rr, - rr_len, dname_len)); - if(!tp) - return NULL; - lock_basic_lock(&tp->lock); - return tp; -} - -/** Add trust anchor from RR */ -static struct autr_ta* -add_trustanchor_frm_rr(struct val_anchors* anchors, uint8_t* rr, size_t rr_len, - size_t dname_len, struct trust_anchor** tp) -{ - struct autr_ta* ta = autr_ta_create(rr, rr_len, dname_len); - if(!ta) - return NULL; - *tp = find_add_tp(anchors, rr, rr_len, dname_len); - if(!*tp) { - free(ta->rr); - free(ta); - return NULL; - } - /* add ta to tp */ - ta->next = (*tp)->autr->keys; - (*tp)->autr->keys = ta; - lock_basic_unlock(&(*tp)->lock); - return ta; -} - -/** - * Add new trust anchor from a string in file. - * @param anchors: all anchors - * @param str: string with anchor and comments, if any comments. - * @param tp: trust point returned. - * @param origin: what to use for @ - * @param origin_len: length of origin - * @param prev: previous rr name - * @param prev_len: length of prev - * @param skip: if true, the result is NULL, but not an error, skip it. - * @return new key in trust point. - */ -static struct autr_ta* -add_trustanchor_frm_str(struct val_anchors* anchors, char* str, - struct trust_anchor** tp, uint8_t* origin, size_t origin_len, - uint8_t** prev, size_t* prev_len, int* skip) -{ - uint8_t rr[LDNS_RR_BUF_SIZE]; - size_t rr_len = sizeof(rr), dname_len; - uint8_t* drr; - int lstatus; - if (!str_contains_data(str, ';')) { - *skip = 1; - return NULL; /* empty line */ - } - if(0 != (lstatus = sldns_str2wire_rr_buf(str, rr, &rr_len, &dname_len, - 0, origin, origin_len, *prev, *prev_len))) - { - log_err("ldns error while converting string to RR at%d: %s: %s", - LDNS_WIREPARSE_OFFSET(lstatus), - sldns_get_errorstr_parse(lstatus), str); - return NULL; - } - free(*prev); - *prev = memdup(rr, dname_len); - *prev_len = dname_len; - if(!*prev) { - log_err("malloc failure in add_trustanchor"); - return NULL; - } - if(sldns_wirerr_get_type(rr, rr_len, dname_len)!=LDNS_RR_TYPE_DNSKEY && - sldns_wirerr_get_type(rr, rr_len, dname_len)!=LDNS_RR_TYPE_DS) { - *skip = 1; - return NULL; /* only DS and DNSKEY allowed */ - } - drr = memdup(rr, rr_len); - if(!drr) { - log_err("malloc failure in add trustanchor"); - return NULL; - } - return add_trustanchor_frm_rr(anchors, drr, rr_len, dname_len, tp); -} - -/** - * Load single anchor - * @param anchors: all points. - * @param str: comments line - * @param fname: filename - * @param origin: the $ORIGIN. - * @param origin_len: length of origin - * @param prev: passed to ldns. - * @param prev_len: length of prev - * @param skip: if true, the result is NULL, but not an error, skip it. - * @return false on failure, otherwise the tp read. - */ -static struct trust_anchor* -load_trustanchor(struct val_anchors* anchors, char* str, const char* fname, - uint8_t* origin, size_t origin_len, uint8_t** prev, size_t* prev_len, - int* skip) -{ - struct autr_ta* ta = NULL; - struct trust_anchor* tp = NULL; - - ta = add_trustanchor_frm_str(anchors, str, &tp, origin, origin_len, - prev, prev_len, skip); - if(!ta) - return NULL; - lock_basic_lock(&tp->lock); - if(!parse_comments(str, ta)) { - lock_basic_unlock(&tp->lock); - return NULL; - } - if(!tp->autr->file) { - tp->autr->file = strdup(fname); - if(!tp->autr->file) { - lock_basic_unlock(&tp->lock); - log_err("malloc failure"); - return NULL; - } - } - lock_basic_unlock(&tp->lock); - return tp; -} - -/** iterator for DSes from keylist. return true if a next element exists */ -static int -assemble_iterate_ds(struct autr_ta** list, uint8_t** rr, size_t* rr_len, - size_t* dname_len) -{ - while(*list) { - if(sldns_wirerr_get_type((*list)->rr, (*list)->rr_len, - (*list)->dname_len) == LDNS_RR_TYPE_DS) { - *rr = (*list)->rr; - *rr_len = (*list)->rr_len; - *dname_len = (*list)->dname_len; - *list = (*list)->next; - return 1; - } - *list = (*list)->next; - } - return 0; -} - -/** iterator for DNSKEYs from keylist. return true if a next element exists */ -static int -assemble_iterate_dnskey(struct autr_ta** list, uint8_t** rr, size_t* rr_len, - size_t* dname_len) -{ - while(*list) { - if(sldns_wirerr_get_type((*list)->rr, (*list)->rr_len, - (*list)->dname_len) != LDNS_RR_TYPE_DS && - ((*list)->s == AUTR_STATE_VALID || - (*list)->s == AUTR_STATE_MISSING)) { - *rr = (*list)->rr; - *rr_len = (*list)->rr_len; - *dname_len = (*list)->dname_len; - *list = (*list)->next; - return 1; - } - *list = (*list)->next; - } - return 0; -} - -/** see if iterator-list has any elements in it, or it is empty */ -static int -assemble_iterate_hasfirst(int iter(struct autr_ta**, uint8_t**, size_t*, - size_t*), struct autr_ta* list) -{ - uint8_t* rr = NULL; - size_t rr_len = 0, dname_len = 0; - return iter(&list, &rr, &rr_len, &dname_len); -} - -/** number of elements in iterator list */ -static size_t -assemble_iterate_count(int iter(struct autr_ta**, uint8_t**, size_t*, - size_t*), struct autr_ta* list) -{ - uint8_t* rr = NULL; - size_t i = 0, rr_len = 0, dname_len = 0; - while(iter(&list, &rr, &rr_len, &dname_len)) { - i++; - } - return i; -} - -/** - * Create a ub_packed_rrset_key allocated on the heap. - * It therefore does not have the correct ID value, and cannot be used - * inside the cache. It can be used in storage outside of the cache. - * Keys for the cache have to be obtained from alloc.h . - * @param iter: iterator over the elements in the list. It filters elements. - * @param list: the list. - * @return key allocated or NULL on failure. - */ -static struct ub_packed_rrset_key* -ub_packed_rrset_heap_key(int iter(struct autr_ta**, uint8_t**, size_t*, - size_t*), struct autr_ta* list) -{ - uint8_t* rr = NULL; - size_t rr_len = 0, dname_len = 0; - struct ub_packed_rrset_key* k; - if(!iter(&list, &rr, &rr_len, &dname_len)) - return NULL; - k = (struct ub_packed_rrset_key*)calloc(1, sizeof(*k)); - if(!k) - return NULL; - k->rk.type = htons(sldns_wirerr_get_type(rr, rr_len, dname_len)); - k->rk.rrset_class = htons(sldns_wirerr_get_class(rr, rr_len, dname_len)); - k->rk.dname_len = dname_len; - k->rk.dname = memdup(rr, dname_len); - if(!k->rk.dname) { - free(k); - return NULL; - } - return k; -} - -/** - * Create packed_rrset data on the heap. - * @param iter: iterator over the elements in the list. It filters elements. - * @param list: the list. - * @return data allocated or NULL on failure. - */ -static struct packed_rrset_data* -packed_rrset_heap_data(int iter(struct autr_ta**, uint8_t**, size_t*, - size_t*), struct autr_ta* list) -{ - uint8_t* rr = NULL; - size_t rr_len = 0, dname_len = 0; - struct packed_rrset_data* data; - size_t count=0, rrsig_count=0, len=0, i, total; - uint8_t* nextrdata; - struct autr_ta* list_i; - time_t ttl = 0; - - list_i = list; - while(iter(&list_i, &rr, &rr_len, &dname_len)) { - if(sldns_wirerr_get_type(rr, rr_len, dname_len) == - LDNS_RR_TYPE_RRSIG) - rrsig_count++; - else count++; - /* sizeof the rdlength + rdatalen */ - len += 2 + sldns_wirerr_get_rdatalen(rr, rr_len, dname_len); - ttl = (time_t)sldns_wirerr_get_ttl(rr, rr_len, dname_len); - } - if(count == 0 && rrsig_count == 0) - return NULL; - - /* allocate */ - total = count + rrsig_count; - len += sizeof(*data) + total*(sizeof(size_t) + sizeof(time_t) + - sizeof(uint8_t*)); - data = (struct packed_rrset_data*)calloc(1, len); - if(!data) - return NULL; - - /* fill it */ - data->ttl = ttl; - data->count = count; - data->rrsig_count = rrsig_count; - data->rr_len = (size_t*)((uint8_t*)data + - sizeof(struct packed_rrset_data)); - data->rr_data = (uint8_t**)&(data->rr_len[total]); - data->rr_ttl = (time_t*)&(data->rr_data[total]); - nextrdata = (uint8_t*)&(data->rr_ttl[total]); - - /* fill out len, ttl, fields */ - list_i = list; - i = 0; - while(iter(&list_i, &rr, &rr_len, &dname_len)) { - data->rr_ttl[i] = (time_t)sldns_wirerr_get_ttl(rr, rr_len, - dname_len); - if(data->rr_ttl[i] < data->ttl) - data->ttl = data->rr_ttl[i]; - data->rr_len[i] = 2 /* the rdlength */ + - sldns_wirerr_get_rdatalen(rr, rr_len, dname_len); - i++; - } - - /* fixup rest of ptrs */ - for(i=0; irr_data[i] = nextrdata; - nextrdata += data->rr_len[i]; - } - - /* copy data in there */ - list_i = list; - i = 0; - while(iter(&list_i, &rr, &rr_len, &dname_len)) { - log_assert(data->rr_data[i]); - memmove(data->rr_data[i], - sldns_wirerr_get_rdatawl(rr, rr_len, dname_len), - data->rr_len[i]); - i++; - } - - if(data->rrsig_count && data->count == 0) { - data->count = data->rrsig_count; /* rrset type is RRSIG */ - data->rrsig_count = 0; - } - return data; -} - -/** - * Assemble the trust anchors into DS and DNSKEY packed rrsets. - * Uses only VALID and MISSING DNSKEYs. - * Read the sldns_rrs and builds packed rrsets - * @param tp: the trust point. Must be locked. - * @return false on malloc failure. - */ -static int -autr_assemble(struct trust_anchor* tp) -{ - struct ub_packed_rrset_key* ubds=NULL, *ubdnskey=NULL; - - /* make packed rrset keys - malloced with no ID number, they - * are not in the cache */ - /* make packed rrset data (if there is a key) */ - if(assemble_iterate_hasfirst(assemble_iterate_ds, tp->autr->keys)) { - ubds = ub_packed_rrset_heap_key( - assemble_iterate_ds, tp->autr->keys); - if(!ubds) - goto error_cleanup; - ubds->entry.data = packed_rrset_heap_data( - assemble_iterate_ds, tp->autr->keys); - if(!ubds->entry.data) - goto error_cleanup; - } - - /* make packed DNSKEY data */ - if(assemble_iterate_hasfirst(assemble_iterate_dnskey, tp->autr->keys)) { - ubdnskey = ub_packed_rrset_heap_key( - assemble_iterate_dnskey, tp->autr->keys); - if(!ubdnskey) - goto error_cleanup; - ubdnskey->entry.data = packed_rrset_heap_data( - assemble_iterate_dnskey, tp->autr->keys); - if(!ubdnskey->entry.data) { - error_cleanup: - autr_rrset_delete(ubds); - autr_rrset_delete(ubdnskey); - return 0; - } - } - - /* we have prepared the new keys so nothing can go wrong any more. - * And we are sure we cannot be left without trustanchor after - * any errors. Put in the new keys and remove old ones. */ - - /* free the old data */ - autr_rrset_delete(tp->ds_rrset); - autr_rrset_delete(tp->dnskey_rrset); - - /* assign the data to replace the old */ - tp->ds_rrset = ubds; - tp->dnskey_rrset = ubdnskey; - tp->numDS = assemble_iterate_count(assemble_iterate_ds, - tp->autr->keys); - tp->numDNSKEY = assemble_iterate_count(assemble_iterate_dnskey, - tp->autr->keys); - return 1; -} - -/** parse integer */ -static unsigned int -parse_int(char* line, int* ret) -{ - char *e; - unsigned int x = (unsigned int)strtol(line, &e, 10); - if(line == e) { - *ret = -1; /* parse error */ - return 0; - } - *ret = 1; /* matched */ - return x; -} - -/** parse id sequence for anchor */ -static struct trust_anchor* -parse_id(struct val_anchors* anchors, char* line) -{ - struct trust_anchor *tp; - int r; - uint16_t dclass; - uint8_t* dname; - size_t dname_len; - /* read the owner name */ - char* next = strchr(line, ' '); - if(!next) - return NULL; - next[0] = 0; - dname = sldns_str2wire_dname(line, &dname_len); - if(!dname) - return NULL; - - /* read the class */ - dclass = parse_int(next+1, &r); - if(r == -1) { - free(dname); - return NULL; - } - - /* find the trust point */ - tp = autr_tp_create(anchors, dname, dname_len, dclass); - free(dname); - return tp; -} - -/** - * Parse variable from trustanchor header - * @param line: to parse - * @param anchors: the anchor is added to this, if "id:" is seen. - * @param anchor: the anchor as result value or previously returned anchor - * value to read the variable lines into. - * @return: 0 no match, -1 failed syntax error, +1 success line read. - * +2 revoked trust anchor file. - */ -static int -parse_var_line(char* line, struct val_anchors* anchors, - struct trust_anchor** anchor) -{ - struct trust_anchor* tp = *anchor; - int r = 0; - if(strncmp(line, ";;id: ", 6) == 0) { - *anchor = parse_id(anchors, line+6); - if(!*anchor) return -1; - else return 1; - } else if(strncmp(line, ";;REVOKED", 9) == 0) { - if(tp) { - log_err("REVOKED statement must be at start of file"); - return -1; - } - return 2; - } else if(strncmp(line, ";;last_queried: ", 16) == 0) { - if(!tp) return -1; - lock_basic_lock(&tp->lock); - tp->autr->last_queried = (time_t)parse_int(line+16, &r); - lock_basic_unlock(&tp->lock); - } else if(strncmp(line, ";;last_success: ", 16) == 0) { - if(!tp) return -1; - lock_basic_lock(&tp->lock); - tp->autr->last_success = (time_t)parse_int(line+16, &r); - lock_basic_unlock(&tp->lock); - } else if(strncmp(line, ";;next_probe_time: ", 19) == 0) { - if(!tp) return -1; - lock_basic_lock(&anchors->lock); - lock_basic_lock(&tp->lock); - (void)rbtree_delete(&anchors->autr->probe, tp); - tp->autr->next_probe_time = (time_t)parse_int(line+19, &r); - (void)rbtree_insert(&anchors->autr->probe, &tp->autr->pnode); - lock_basic_unlock(&tp->lock); - lock_basic_unlock(&anchors->lock); - } else if(strncmp(line, ";;query_failed: ", 16) == 0) { - if(!tp) return -1; - lock_basic_lock(&tp->lock); - tp->autr->query_failed = (uint8_t)parse_int(line+16, &r); - lock_basic_unlock(&tp->lock); - } else if(strncmp(line, ";;query_interval: ", 18) == 0) { - if(!tp) return -1; - lock_basic_lock(&tp->lock); - tp->autr->query_interval = (time_t)parse_int(line+18, &r); - lock_basic_unlock(&tp->lock); - } else if(strncmp(line, ";;retry_time: ", 14) == 0) { - if(!tp) return -1; - lock_basic_lock(&tp->lock); - tp->autr->retry_time = (time_t)parse_int(line+14, &r); - lock_basic_unlock(&tp->lock); - } - return r; -} - -/** handle origin lines */ -static int -handle_origin(char* line, uint8_t** origin, size_t* origin_len) -{ - size_t len = 0; - while(isspace((unsigned char)*line)) - line++; - if(strncmp(line, "$ORIGIN", 7) != 0) - return 0; - free(*origin); - line += 7; - while(isspace((unsigned char)*line)) - line++; - *origin = sldns_str2wire_dname(line, &len); - *origin_len = len; - if(!*origin) - log_warn("malloc failure or parse error in $ORIGIN"); - return 1; -} - -/** Read one line and put multiline RRs onto one line string */ -static int -read_multiline(char* buf, size_t len, FILE* in, int* linenr) -{ - char* pos = buf; - size_t left = len; - int depth = 0; - buf[len-1] = 0; - while(left > 0 && fgets(pos, (int)left, in) != NULL) { - size_t i, poslen = strlen(pos); - (*linenr)++; - - /* check what the new depth is after the line */ - /* this routine cannot handle braces inside quotes, - say for TXT records, but this routine only has to read keys */ - for(i=0; i0) - pos[poslen-1] = 0; /* strip newline */ - if(strchr(pos, ';')) - strchr(pos, ';')[0] = 0; /* strip comments */ - - /* move to paste other lines behind this one */ - poslen = strlen(pos); - pos += poslen; - left -= poslen; - /* the newline is changed into a space */ - if(left <= 2 /* space and eos */) { - log_err("line too long"); - return -1; - } - pos[0] = ' '; - pos[1] = 0; - pos += 1; - left -= 1; - } - if(depth != 0) { - log_err("mismatch: too many '('"); - return -1; - } - if(pos != buf) - return 1; - return 0; -} - -int autr_read_file(struct val_anchors* anchors, const char* nm) -{ - /* the file descriptor */ - FILE* fd; - /* keep track of line numbers */ - int line_nr = 0; - /* single line */ - char line[10240]; - /* trust point being read */ - struct trust_anchor *tp = NULL, *tp2; - int r; - /* for $ORIGIN parsing */ - uint8_t *origin=NULL, *prev=NULL; - size_t origin_len=0, prev_len=0; - - if (!(fd = fopen(nm, "r"))) { - log_err("unable to open %s for reading: %s", - nm, strerror(errno)); - return 0; - } - verbose(VERB_ALGO, "reading autotrust anchor file %s", nm); - while ( (r=read_multiline(line, sizeof(line), fd, &line_nr)) != 0) { - if(r == -1 || (r = parse_var_line(line, anchors, &tp)) == -1) { - log_err("could not parse auto-trust-anchor-file " - "%s line %d", nm, line_nr); - fclose(fd); - free(origin); - free(prev); - return 0; - } else if(r == 1) { - continue; - } else if(r == 2) { - log_warn("trust anchor %s has been revoked", nm); - fclose(fd); - free(origin); - free(prev); - return 1; - } - if (!str_contains_data(line, ';')) - continue; /* empty lines allowed */ - if(handle_origin(line, &origin, &origin_len)) - continue; - r = 0; - if(!(tp2=load_trustanchor(anchors, line, nm, origin, - origin_len, &prev, &prev_len, &r))) { - if(!r) log_err("failed to load trust anchor from %s " - "at line %i, skipping", nm, line_nr); - /* try to do the rest */ - continue; - } - if(tp && tp != tp2) { - log_err("file %s has mismatching data inside: " - "the file may only contain keys for one name, " - "remove keys for other domain names", nm); - fclose(fd); - free(origin); - free(prev); - return 0; - } - tp = tp2; - } - fclose(fd); - free(origin); - free(prev); - if(!tp) { - log_err("failed to read %s", nm); - return 0; - } - - /* now assemble the data into DNSKEY and DS packed rrsets */ - lock_basic_lock(&tp->lock); - if(!autr_assemble(tp)) { - lock_basic_unlock(&tp->lock); - log_err("malloc failure assembling %s", nm); - return 0; - } - lock_basic_unlock(&tp->lock); - return 1; -} - -/** string for a trustanchor state */ -static const char* -trustanchor_state2str(autr_state_type s) -{ - switch (s) { - case AUTR_STATE_START: return " START "; - case AUTR_STATE_ADDPEND: return " ADDPEND "; - case AUTR_STATE_VALID: return " VALID "; - case AUTR_STATE_MISSING: return " MISSING "; - case AUTR_STATE_REVOKED: return " REVOKED "; - case AUTR_STATE_REMOVED: return " REMOVED "; - } - return " UNKNOWN "; -} - -/** ctime r for autotrust */ -static char* autr_ctime_r(time_t* t, char* s) -{ - ctime_r(t, s); -#ifdef USE_WINSOCK - if(strlen(s) > 10 && s[7]==' ' && s[8]=='0') - s[8]=' '; /* fix error in windows ctime */ -#endif - return s; -} - -/** print ID to file */ -static int -print_id(FILE* out, char* fname, uint8_t* nm, size_t nmlen, uint16_t dclass) -{ - char* s = sldns_wire2str_dname(nm, nmlen); - if(!s) { - log_err("malloc failure in write to %s", fname); - return 0; - } - if(fprintf(out, ";;id: %s %d\n", s, (int)dclass) < 0) { - log_err("could not write to %s: %s", fname, strerror(errno)); - free(s); - return 0; - } - free(s); - return 1; -} - -static int -autr_write_contents(FILE* out, char* fn, struct trust_anchor* tp) -{ - char tmi[32]; - struct autr_ta* ta; - char* str; - - /* write pretty header */ - if(fprintf(out, "; autotrust trust anchor file\n") < 0) { - log_err("could not write to %s: %s", fn, strerror(errno)); - return 0; - } - if(tp->autr->revoked) { - if(fprintf(out, ";;REVOKED\n") < 0 || - fprintf(out, "; The zone has all keys revoked, and is\n" - "; considered as if it has no trust anchors.\n" - "; the remainder of the file is the last probe.\n" - "; to restart the trust anchor, overwrite this file.\n" - "; with one containing valid DNSKEYs or DSes.\n") < 0) { - log_err("could not write to %s: %s", fn, strerror(errno)); - return 0; - } - } - if(!print_id(out, fn, tp->name, tp->namelen, tp->dclass)) { - return 0; - } - if(fprintf(out, ";;last_queried: %u ;;%s", - (unsigned int)tp->autr->last_queried, - autr_ctime_r(&(tp->autr->last_queried), tmi)) < 0 || - fprintf(out, ";;last_success: %u ;;%s", - (unsigned int)tp->autr->last_success, - autr_ctime_r(&(tp->autr->last_success), tmi)) < 0 || - fprintf(out, ";;next_probe_time: %u ;;%s", - (unsigned int)tp->autr->next_probe_time, - autr_ctime_r(&(tp->autr->next_probe_time), tmi)) < 0 || - fprintf(out, ";;query_failed: %d\n", (int)tp->autr->query_failed)<0 - || fprintf(out, ";;query_interval: %d\n", - (int)tp->autr->query_interval) < 0 || - fprintf(out, ";;retry_time: %d\n", (int)tp->autr->retry_time) < 0) { - log_err("could not write to %s: %s", fn, strerror(errno)); - return 0; - } - - /* write anchors */ - for(ta=tp->autr->keys; ta; ta=ta->next) { - /* by default do not store START and REMOVED keys */ - if(ta->s == AUTR_STATE_START) - continue; - if(ta->s == AUTR_STATE_REMOVED) - continue; - /* only store keys */ - if(sldns_wirerr_get_type(ta->rr, ta->rr_len, ta->dname_len) - != LDNS_RR_TYPE_DNSKEY) - continue; - str = sldns_wire2str_rr(ta->rr, ta->rr_len); - if(!str || !str[0]) { - free(str); - log_err("malloc failure writing %s", fn); - return 0; - } - str[strlen(str)-1] = 0; /* remove newline */ - if(fprintf(out, "%s ;;state=%d [%s] ;;count=%d " - ";;lastchange=%u ;;%s", str, (int)ta->s, - trustanchor_state2str(ta->s), (int)ta->pending_count, - (unsigned int)ta->last_change, - autr_ctime_r(&(ta->last_change), tmi)) < 0) { - log_err("could not write to %s: %s", fn, strerror(errno)); - free(str); - return 0; - } - free(str); - } - return 1; -} - -void autr_write_file(struct module_env* env, struct trust_anchor* tp) -{ - FILE* out; - char* fname = tp->autr->file; -#ifndef S_SPLINT_S - long long llvalue; -#endif - char tempf[2048]; - log_assert(tp->autr); - if(!env) { - log_err("autr_write_file: Module environment is NULL."); - return; - } - /* unique name with pid number, thread number, and struct pointer - * (the pointer uniquifies for multiple libunbound contexts) */ -#ifndef S_SPLINT_S -#if defined(SIZE_MAX) && defined(UINT32_MAX) && (UINT32_MAX == SIZE_MAX || INT32_MAX == SIZE_MAX) - /* avoid warning about upcast on 32bit systems */ - llvalue = (unsigned long)tp; -#else - llvalue = (unsigned long long)tp; -#endif - snprintf(tempf, sizeof(tempf), "%s.%d-%d-" ARG_LL "x", fname, (int)getpid(), - env->worker?*(int*)env->worker:0, llvalue); -#endif /* S_SPLINT_S */ - verbose(VERB_ALGO, "autotrust: write to disk: %s", tempf); - out = fopen(tempf, "w"); - if(!out) { - fatal_exit("could not open autotrust file for writing, %s: %s", - tempf, strerror(errno)); - return; - } - if(!autr_write_contents(out, tempf, tp)) { - /* failed to write contents (completely) */ - fclose(out); - unlink(tempf); - fatal_exit("could not completely write: %s", fname); - return; - } - if(fflush(out) != 0) - log_err("could not fflush(%s): %s", fname, strerror(errno)); -#ifdef HAVE_FSYNC - if(fsync(fileno(out)) != 0) - log_err("could not fsync(%s): %s", fname, strerror(errno)); -#else - FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out))); -#endif - if(fclose(out) != 0) { - fatal_exit("could not complete write: %s: %s", - fname, strerror(errno)); - unlink(tempf); - return; - } - /* success; overwrite actual file */ - verbose(VERB_ALGO, "autotrust: replaced %s", fname); -#ifdef UB_ON_WINDOWS - (void)unlink(fname); /* windows does not replace file with rename() */ -#endif - if(rename(tempf, fname) < 0) { - fatal_exit("rename(%s to %s): %s", tempf, fname, strerror(errno)); - } -} - -/** - * Verify if dnskey works for trust point - * @param env: environment (with time) for verification - * @param ve: validator environment (with options) for verification. - * @param tp: trust point to verify with - * @param rrset: DNSKEY rrset to verify. - * @param qstate: qstate with region. - * @return false on failure, true if verification successful. - */ -static int -verify_dnskey(struct module_env* env, struct val_env* ve, - struct trust_anchor* tp, struct ub_packed_rrset_key* rrset, - struct module_qstate* qstate) -{ - char* reason = NULL; - uint8_t sigalg[ALGO_NEEDS_MAX+1]; - int downprot = env->cfg->harden_algo_downgrade; - enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset, - tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason, - NULL, qstate); - /* sigalg is ignored, it returns algorithms signalled to exist, but - * in 5011 there are no other rrsets to check. if downprot is - * enabled, then it checks that the DNSKEY is signed with all - * algorithms available in the trust store. */ - verbose(VERB_ALGO, "autotrust: validate DNSKEY with anchor: %s", - sec_status_to_string(sec)); - return sec == sec_status_secure; -} - -static int32_t -rrsig_get_expiry(uint8_t* d, size_t len) -{ - /* rrsig: 2(rdlen), 2(type) 1(alg) 1(v) 4(origttl), then 4(expi), (4)incep) */ - if(len < 2+8+4) - return 0; - return sldns_read_uint32(d+2+8); -} - -/** Find minimum expiration interval from signatures */ -static time_t -min_expiry(struct module_env* env, struct packed_rrset_data* dd) -{ - size_t i; - int32_t t, r = 15 * 24 * 3600; /* 15 days max */ - for(i=dd->count; icount+dd->rrsig_count; i++) { - t = rrsig_get_expiry(dd->rr_data[i], dd->rr_len[i]); - if((int32_t)t - (int32_t)*env->now > 0) { - t -= (int32_t)*env->now; - if(t < r) - r = t; - } - } - return (time_t)r; -} - -/** Is rr self-signed revoked key */ -static int -rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, size_t i, - struct module_qstate* qstate) -{ - enum sec_status sec; - char* reason = NULL; - verbose(VERB_ALGO, "seen REVOKE flag, check self-signed, rr %d", - (int)i); - /* no algorithm downgrade protection necessary, if it is selfsigned - * revoked it can be removed. */ - sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i, - &reason, NULL, LDNS_SECTION_ANSWER, qstate); - return (sec == sec_status_secure); -} - -/** Set fetched value */ -static void -seen_trustanchor(struct autr_ta* ta, uint8_t seen) -{ - ta->fetched = seen; - if(ta->pending_count < 250) /* no numerical overflow, please */ - ta->pending_count++; -} - -/** set revoked value */ -static void -seen_revoked_trustanchor(struct autr_ta* ta, uint8_t revoked) -{ - ta->revoked = revoked; -} - -/** revoke a trust anchor */ -static void -revoke_dnskey(struct autr_ta* ta, int off) -{ - uint16_t flags; - uint8_t* data; - if(sldns_wirerr_get_type(ta->rr, ta->rr_len, ta->dname_len) != - LDNS_RR_TYPE_DNSKEY) - return; - if(sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len, ta->dname_len) < 2) - return; - data = sldns_wirerr_get_rdata(ta->rr, ta->rr_len, ta->dname_len); - flags = sldns_read_uint16(data); - if (off && (flags&LDNS_KEY_REVOKE_KEY)) - flags ^= LDNS_KEY_REVOKE_KEY; /* flip */ - else - flags |= LDNS_KEY_REVOKE_KEY; - sldns_write_uint16(data, flags); -} - -/** Compare two RRs skipping the REVOKED bit. Pass rdata(no len) */ -static int -dnskey_compare_skip_revbit(uint8_t* a, size_t a_len, uint8_t* b, size_t b_len) -{ - size_t i; - if(a_len != b_len) - return -1; - /* compare RRs RDATA byte for byte. */ - for(i = 0; i < a_len; i++) - { - uint8_t rdf1, rdf2; - rdf1 = a[i]; - rdf2 = b[i]; - if(i==1) { - /* this is the second part of the flags field */ - rdf1 |= LDNS_KEY_REVOKE_KEY; - rdf2 |= LDNS_KEY_REVOKE_KEY; - } - if (rdf1 < rdf2) return -1; - else if (rdf1 > rdf2) return 1; - } - return 0; -} - - -/** compare trust anchor with rdata, 0 if equal. Pass rdata(no len) */ -static int -ta_compare(struct autr_ta* a, uint16_t t, uint8_t* b, size_t b_len) -{ - if(!a) return -1; - else if(!b) return -1; - else if(sldns_wirerr_get_type(a->rr, a->rr_len, a->dname_len) != t) - return (int)sldns_wirerr_get_type(a->rr, a->rr_len, - a->dname_len) - (int)t; - else if(t == LDNS_RR_TYPE_DNSKEY) { - return dnskey_compare_skip_revbit( - sldns_wirerr_get_rdata(a->rr, a->rr_len, a->dname_len), - sldns_wirerr_get_rdatalen(a->rr, a->rr_len, - a->dname_len), b, b_len); - } - else if(t == LDNS_RR_TYPE_DS) { - if(sldns_wirerr_get_rdatalen(a->rr, a->rr_len, a->dname_len) != - b_len) - return -1; - return memcmp(sldns_wirerr_get_rdata(a->rr, - a->rr_len, a->dname_len), b, b_len); - } - return -1; -} - -/** - * Find key - * @param tp: to search in - * @param t: rr type of the rdata. - * @param rdata: to look for (no rdatalen in it) - * @param rdata_len: length of rdata - * @param result: returns NULL or the ta key looked for. - * @return false on malloc failure during search. if true examine result. - */ -static int -find_key(struct trust_anchor* tp, uint16_t t, uint8_t* rdata, size_t rdata_len, - struct autr_ta** result) -{ - struct autr_ta* ta; - if(!tp || !rdata) { - *result = NULL; - return 0; - } - for(ta=tp->autr->keys; ta; ta=ta->next) { - if(ta_compare(ta, t, rdata, rdata_len) == 0) { - *result = ta; - return 1; - } - } - *result = NULL; - return 1; -} - -/** add key and clone RR and tp already locked. rdata without rdlen. */ -static struct autr_ta* -add_key(struct trust_anchor* tp, uint32_t ttl, uint8_t* rdata, size_t rdata_len) -{ - struct autr_ta* ta; - uint8_t* rr; - size_t rr_len, dname_len; - uint16_t rrtype = htons(LDNS_RR_TYPE_DNSKEY); - uint16_t rrclass = htons(LDNS_RR_CLASS_IN); - uint16_t rdlen = htons(rdata_len); - dname_len = tp->namelen; - ttl = htonl(ttl); - rr_len = dname_len + 10 /* type,class,ttl,rdatalen */ + rdata_len; - rr = (uint8_t*)malloc(rr_len); - if(!rr) return NULL; - memmove(rr, tp->name, tp->namelen); - memmove(rr+dname_len, &rrtype, 2); - memmove(rr+dname_len+2, &rrclass, 2); - memmove(rr+dname_len+4, &ttl, 4); - memmove(rr+dname_len+8, &rdlen, 2); - memmove(rr+dname_len+10, rdata, rdata_len); - ta = autr_ta_create(rr, rr_len, dname_len); - if(!ta) { - /* rr freed in autr_ta_create */ - return NULL; - } - /* link in, tp already locked */ - ta->next = tp->autr->keys; - tp->autr->keys = ta; - return ta; -} - -/** get TTL from DNSKEY rrset */ -static time_t -key_ttl(struct ub_packed_rrset_key* k) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - return d->ttl; -} - -/** update the time values for the trustpoint */ -static void -set_tp_times(struct trust_anchor* tp, time_t rrsig_exp_interval, - time_t origttl, int* changed) -{ - time_t x, qi = tp->autr->query_interval, rt = tp->autr->retry_time; - - /* x = MIN(15days, ttl/2, expire/2) */ - x = 15 * 24 * 3600; - if(origttl/2 < x) - x = origttl/2; - if(rrsig_exp_interval/2 < x) - x = rrsig_exp_interval/2; - /* MAX(1hr, x) */ - if(!autr_permit_small_holddown) { - if(x < 3600) - tp->autr->query_interval = 3600; - else tp->autr->query_interval = x; - } else tp->autr->query_interval = x; - - /* x= MIN(1day, ttl/10, expire/10) */ - x = 24 * 3600; - if(origttl/10 < x) - x = origttl/10; - if(rrsig_exp_interval/10 < x) - x = rrsig_exp_interval/10; - /* MAX(1hr, x) */ - if(!autr_permit_small_holddown) { - if(x < 3600) - tp->autr->retry_time = 3600; - else tp->autr->retry_time = x; - } else tp->autr->retry_time = x; - - if(qi != tp->autr->query_interval || rt != tp->autr->retry_time) { - *changed = 1; - verbose(VERB_ALGO, "orig_ttl is %d", (int)origttl); - verbose(VERB_ALGO, "rrsig_exp_interval is %d", - (int)rrsig_exp_interval); - verbose(VERB_ALGO, "query_interval: %d, retry_time: %d", - (int)tp->autr->query_interval, - (int)tp->autr->retry_time); - } -} - -/** init events to zero */ -static void -init_events(struct trust_anchor* tp) -{ - struct autr_ta* ta; - for(ta=tp->autr->keys; ta; ta=ta->next) { - ta->fetched = 0; - } -} - -/** check for revoked keys without trusting any other information */ -static void -check_contains_revoked(struct module_env* env, struct val_env* ve, - struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, - int* changed, struct module_qstate* qstate) -{ - struct packed_rrset_data* dd = (struct packed_rrset_data*) - dnskey_rrset->entry.data; - size_t i; - log_assert(ntohs(dnskey_rrset->rk.type) == LDNS_RR_TYPE_DNSKEY); - for(i=0; icount; i++) { - struct autr_ta* ta = NULL; - if(!rr_is_dnskey_sep(ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2) || - !rr_is_dnskey_revoked(ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2)) - continue; /* not a revoked KSK */ - if(!find_key(tp, ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2, &ta)) { - log_err("malloc failure"); - continue; /* malloc fail in compare*/ - } - if(!ta) - continue; /* key not found */ - if(rr_is_selfsigned_revoked(env, ve, dnskey_rrset, i, qstate)) { - /* checked if there is an rrsig signed by this key. */ - /* same keytag, but stored can be revoked already, so - * compare keytags, with +0 or +128(REVOKE flag) */ - log_assert(dnskey_calc_keytag(dnskey_rrset, i)-128 == - sldns_calc_keytag_raw(sldns_wirerr_get_rdata( - ta->rr, ta->rr_len, ta->dname_len), - sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len, - ta->dname_len)) || - dnskey_calc_keytag(dnskey_rrset, i) == - sldns_calc_keytag_raw(sldns_wirerr_get_rdata( - ta->rr, ta->rr_len, ta->dname_len), - sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len, - ta->dname_len))); /* checks conversion*/ - verbose_key(ta, VERB_ALGO, "is self-signed revoked"); - if(!ta->revoked) - *changed = 1; - seen_revoked_trustanchor(ta, 1); - do_revoked(env, ta, changed); - } - } -} - -/** See if a DNSKEY is verified by one of the DSes */ -static int -key_matches_a_ds(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, size_t key_idx, - struct ub_packed_rrset_key* ds_rrset) -{ - struct packed_rrset_data* dd = (struct packed_rrset_data*) - ds_rrset->entry.data; - size_t ds_idx, num = dd->count; - int d = val_favorite_ds_algo(ds_rrset); - char* reason = ""; - for(ds_idx=0; ds_idxentry.data; - size_t i; - log_assert(ntohs(dnskey_rrset->rk.type) == LDNS_RR_TYPE_DNSKEY); - init_events(tp); - for(i=0; icount; i++) { - struct autr_ta* ta = NULL; - if(!rr_is_dnskey_sep(ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2)) - continue; - if(rr_is_dnskey_revoked(ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2)) { - /* self-signed revoked keys already detected before, - * other revoked keys are not 'added' again */ - continue; - } - /* is a key of this type supported?. Note rr_list and - * packed_rrset are in the same order. */ - if(!dnskey_algo_is_supported(dnskey_rrset, i) || - !dnskey_size_is_supported(dnskey_rrset, i)) { - /* skip unknown algorithm key, it is useless to us */ - log_nametypeclass(VERB_DETAIL, "trust point has " - "unsupported algorithm at", - tp->name, LDNS_RR_TYPE_DNSKEY, tp->dclass); - continue; - } - - /* is it new? if revocation bit set, find the unrevoked key */ - if(!find_key(tp, ntohs(dnskey_rrset->rk.type), - dd->rr_data[i]+2, dd->rr_len[i]-2, &ta)) { - return 0; - } - if(!ta) { - ta = add_key(tp, (uint32_t)dd->rr_ttl[i], - dd->rr_data[i]+2, dd->rr_len[i]-2); - *changed = 1; - /* first time seen, do we have DSes? if match: VALID */ - if(ta && tp->ds_rrset && key_matches_a_ds(env, ve, - dnskey_rrset, i, tp->ds_rrset)) { - verbose_key(ta, VERB_ALGO, "verified by DS"); - ta->s = AUTR_STATE_VALID; - } - } - if(!ta) { - return 0; - } - seen_trustanchor(ta, 1); - verbose_key(ta, VERB_ALGO, "in DNS response"); - } - set_tp_times(tp, min_expiry(env, dd), key_ttl(dnskey_rrset), changed); - return 1; -} - -/** - * Check if the holddown time has already exceeded - * setting: add-holddown: add holddown timer - * setting: del-holddown: del holddown timer - * @param env: environment with current time - * @param ta: trust anchor to check for. - * @param holddown: the timer value - * @return number of seconds the holddown has passed. - */ -static time_t -check_holddown(struct module_env* env, struct autr_ta* ta, - unsigned int holddown) -{ - time_t elapsed; - if(*env->now < ta->last_change) { - log_warn("time goes backwards. delaying key holddown"); - return 0; - } - elapsed = *env->now - ta->last_change; - if (elapsed > (time_t)holddown) { - return elapsed-(time_t)holddown; - } - verbose_key(ta, VERB_ALGO, "holddown time " ARG_LL "d seconds to go", - (long long) ((time_t)holddown-elapsed)); - return 0; -} - - -/** Set last_change to now */ -static void -reset_holddown(struct module_env* env, struct autr_ta* ta, int* changed) -{ - ta->last_change = *env->now; - *changed = 1; -} - -/** Set the state for this trust anchor */ -static void -set_trustanchor_state(struct module_env* env, struct autr_ta* ta, int* changed, - autr_state_type s) -{ - verbose_key(ta, VERB_ALGO, "update: %s to %s", - trustanchor_state2str(ta->s), trustanchor_state2str(s)); - ta->s = s; - reset_holddown(env, ta, changed); -} - - -/** Event: NewKey */ -static void -do_newkey(struct module_env* env, struct autr_ta* anchor, int* c) -{ - if (anchor->s == AUTR_STATE_START) - set_trustanchor_state(env, anchor, c, AUTR_STATE_ADDPEND); -} - -/** Event: AddTime */ -static void -do_addtime(struct module_env* env, struct autr_ta* anchor, int* c) -{ - /* This not according to RFC, this is 30 days, but the RFC demands - * MAX(30days, TTL expire time of first DNSKEY set with this key), - * The value may be too small if a very large TTL was used. */ - time_t exceeded = check_holddown(env, anchor, env->cfg->add_holddown); - if (exceeded && anchor->s == AUTR_STATE_ADDPEND) { - verbose_key(anchor, VERB_ALGO, "add-holddown time exceeded " - ARG_LL "d seconds ago, and pending-count %d", - (long long)exceeded, anchor->pending_count); - if(anchor->pending_count >= MIN_PENDINGCOUNT) { - set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID); - anchor->pending_count = 0; - return; - } - verbose_key(anchor, VERB_ALGO, "add-holddown time sanity check " - "failed (pending count: %d)", anchor->pending_count); - } -} - -/** Event: RemTime */ -static void -do_remtime(struct module_env* env, struct autr_ta* anchor, int* c) -{ - time_t exceeded = check_holddown(env, anchor, env->cfg->del_holddown); - if(exceeded && anchor->s == AUTR_STATE_REVOKED) { - verbose_key(anchor, VERB_ALGO, "del-holddown time exceeded " - ARG_LL "d seconds ago", (long long)exceeded); - set_trustanchor_state(env, anchor, c, AUTR_STATE_REMOVED); - } -} - -/** Event: KeyRem */ -static void -do_keyrem(struct module_env* env, struct autr_ta* anchor, int* c) -{ - if(anchor->s == AUTR_STATE_ADDPEND) { - set_trustanchor_state(env, anchor, c, AUTR_STATE_START); - anchor->pending_count = 0; - } else if(anchor->s == AUTR_STATE_VALID) - set_trustanchor_state(env, anchor, c, AUTR_STATE_MISSING); -} - -/** Event: KeyPres */ -static void -do_keypres(struct module_env* env, struct autr_ta* anchor, int* c) -{ - if(anchor->s == AUTR_STATE_MISSING) - set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID); -} - -/* Event: Revoked */ -static void -do_revoked(struct module_env* env, struct autr_ta* anchor, int* c) -{ - if(anchor->s == AUTR_STATE_VALID || anchor->s == AUTR_STATE_MISSING) { - set_trustanchor_state(env, anchor, c, AUTR_STATE_REVOKED); - verbose_key(anchor, VERB_ALGO, "old id, prior to revocation"); - revoke_dnskey(anchor, 0); - verbose_key(anchor, VERB_ALGO, "new id, after revocation"); - } -} - -/** Do statestable transition matrix for anchor */ -static void -anchor_state_update(struct module_env* env, struct autr_ta* anchor, int* c) -{ - log_assert(anchor); - switch(anchor->s) { - /* START */ - case AUTR_STATE_START: - /* NewKey: ADDPEND */ - if (anchor->fetched) - do_newkey(env, anchor, c); - break; - /* ADDPEND */ - case AUTR_STATE_ADDPEND: - /* KeyRem: START */ - if (!anchor->fetched) - do_keyrem(env, anchor, c); - /* AddTime: VALID */ - else do_addtime(env, anchor, c); - break; - /* VALID */ - case AUTR_STATE_VALID: - /* RevBit: REVOKED */ - if (anchor->revoked) - do_revoked(env, anchor, c); - /* KeyRem: MISSING */ - else if (!anchor->fetched) - do_keyrem(env, anchor, c); - else if(!anchor->last_change) { - verbose_key(anchor, VERB_ALGO, "first seen"); - reset_holddown(env, anchor, c); - } - break; - /* MISSING */ - case AUTR_STATE_MISSING: - /* RevBit: REVOKED */ - if (anchor->revoked) - do_revoked(env, anchor, c); - /* KeyPres */ - else if (anchor->fetched) - do_keypres(env, anchor, c); - break; - /* REVOKED */ - case AUTR_STATE_REVOKED: - if (anchor->fetched) - reset_holddown(env, anchor, c); - /* RemTime: REMOVED */ - else do_remtime(env, anchor, c); - break; - /* REMOVED */ - case AUTR_STATE_REMOVED: - default: - break; - } -} - -/** if ZSK init then trust KSKs */ -static int -init_zsk_to_ksk(struct module_env* env, struct trust_anchor* tp, int* changed) -{ - /* search for VALID ZSKs */ - struct autr_ta* anchor; - int validzsk = 0; - int validksk = 0; - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - /* last_change test makes sure it was manually configured */ - if(sldns_wirerr_get_type(anchor->rr, anchor->rr_len, - anchor->dname_len) == LDNS_RR_TYPE_DNSKEY && - anchor->last_change == 0 && - !ta_is_dnskey_sep(anchor) && - anchor->s == AUTR_STATE_VALID) - validzsk++; - } - if(validzsk == 0) - return 0; - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - if (ta_is_dnskey_sep(anchor) && - anchor->s == AUTR_STATE_ADDPEND) { - verbose_key(anchor, VERB_ALGO, "trust KSK from " - "ZSK(config)"); - set_trustanchor_state(env, anchor, changed, - AUTR_STATE_VALID); - validksk++; - } - } - return validksk; -} - -/** Remove missing trustanchors so the list does not grow forever */ -static void -remove_missing_trustanchors(struct module_env* env, struct trust_anchor* tp, - int* changed) -{ - struct autr_ta* anchor; - time_t exceeded; - int valid = 0; - /* see if we have anchors that are valid */ - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - /* Only do KSKs */ - if (!ta_is_dnskey_sep(anchor)) - continue; - if (anchor->s == AUTR_STATE_VALID) - valid++; - } - /* if there are no SEP Valid anchors, see if we started out with - * a ZSK (last-change=0) anchor, which is VALID and there are KSKs - * now that can be made valid. Do this immediately because there - * is no guarantee that the ZSKs get announced long enough. Usually - * this is immediately after init with a ZSK trusted, unless the domain - * was not advertising any KSKs at all. In which case we perfectly - * track the zero number of KSKs. */ - if(valid == 0) { - valid = init_zsk_to_ksk(env, tp, changed); - if(valid == 0) - return; - } - - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - /* ignore ZSKs if newly added */ - if(anchor->s == AUTR_STATE_START) - continue; - /* remove ZSKs if a KSK is present */ - if (!ta_is_dnskey_sep(anchor)) { - if(valid > 0) { - verbose_key(anchor, VERB_ALGO, "remove ZSK " - "[%d key(s) VALID]", valid); - set_trustanchor_state(env, anchor, changed, - AUTR_STATE_REMOVED); - } - continue; - } - /* Only do MISSING keys */ - if (anchor->s != AUTR_STATE_MISSING) - continue; - if(env->cfg->keep_missing == 0) - continue; /* keep forever */ - - exceeded = check_holddown(env, anchor, env->cfg->keep_missing); - /* If keep_missing has exceeded and we still have more than - * one valid KSK: remove missing trust anchor */ - if (exceeded && valid > 0) { - verbose_key(anchor, VERB_ALGO, "keep-missing time " - "exceeded " ARG_LL "d seconds ago, [%d key(s) VALID]", - (long long)exceeded, valid); - set_trustanchor_state(env, anchor, changed, - AUTR_STATE_REMOVED); - } - } -} - -/** Do the statetable from RFC5011 transition matrix */ -static int -do_statetable(struct module_env* env, struct trust_anchor* tp, int* changed) -{ - struct autr_ta* anchor; - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - /* Only do KSKs */ - if(!ta_is_dnskey_sep(anchor)) - continue; - anchor_state_update(env, anchor, changed); - } - remove_missing_trustanchors(env, tp, changed); - return 1; -} - -/** See if time alone makes ADDPEND to VALID transition */ -static void -autr_holddown_exceed(struct module_env* env, struct trust_anchor* tp, int* c) -{ - struct autr_ta* anchor; - for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { - if(ta_is_dnskey_sep(anchor) && - anchor->s == AUTR_STATE_ADDPEND) - do_addtime(env, anchor, c); - } -} - -/** cleanup key list */ -static void -autr_cleanup_keys(struct trust_anchor* tp) -{ - struct autr_ta* p, **prevp; - prevp = &tp->autr->keys; - p = tp->autr->keys; - while(p) { - /* do we want to remove this key? */ - if(p->s == AUTR_STATE_START || p->s == AUTR_STATE_REMOVED || - sldns_wirerr_get_type(p->rr, p->rr_len, p->dname_len) - != LDNS_RR_TYPE_DNSKEY) { - struct autr_ta* np = p->next; - /* remove */ - free(p->rr); - free(p); - /* snip and go to next item */ - *prevp = np; - p = np; - continue; - } - /* remove pending counts if no longer pending */ - if(p->s != AUTR_STATE_ADDPEND) - p->pending_count = 0; - prevp = &p->next; - p = p->next; - } -} - -/** calculate next probe time */ -static time_t -calc_next_probe(struct module_env* env, time_t wait) -{ - /* make it random, 90-100% */ - time_t rnd, rest; - if(!autr_permit_small_holddown) { - if(wait < 3600) - wait = 3600; - } else { - if(wait == 0) wait = 1; - } - rnd = wait/10; - rest = wait-rnd; - rnd = (time_t)ub_random_max(env->rnd, (long int)rnd); - return (time_t)(*env->now + rest + rnd); -} - -/** what is first probe time (anchors must be locked) */ -static time_t -wait_probe_time(struct val_anchors* anchors) -{ - rbnode_type* t = rbtree_first(&anchors->autr->probe); - if(t != RBTREE_NULL) - return ((struct trust_anchor*)t->key)->autr->next_probe_time; - return 0; -} - -/** reset worker timer */ -static void -reset_worker_timer(struct module_env* env) -{ - struct timeval tv; -#ifndef S_SPLINT_S - time_t next = (time_t)wait_probe_time(env->anchors); - /* in case this is libunbound, no timer */ - if(!env->probe_timer) - return; - if(next > *env->now) - tv.tv_sec = (time_t)(next - *env->now); - else tv.tv_sec = 0; -#endif - tv.tv_usec = 0; - comm_timer_set(env->probe_timer, &tv); - verbose(VERB_ALGO, "scheduled next probe in " ARG_LL "d sec", (long long)tv.tv_sec); -} - -/** set next probe for trust anchor */ -static int -set_next_probe(struct module_env* env, struct trust_anchor* tp, - struct ub_packed_rrset_key* dnskey_rrset) -{ - struct trust_anchor key, *tp2; - time_t mold, mnew; - /* use memory allocated in rrset for temporary name storage */ - key.node.key = &key; - key.name = dnskey_rrset->rk.dname; - key.namelen = dnskey_rrset->rk.dname_len; - key.namelabs = dname_count_labels(key.name); - key.dclass = tp->dclass; - lock_basic_unlock(&tp->lock); - - /* fetch tp again and lock anchors, so that we can modify the trees */ - lock_basic_lock(&env->anchors->lock); - tp2 = (struct trust_anchor*)rbtree_search(env->anchors->tree, &key); - if(!tp2) { - verbose(VERB_ALGO, "trustpoint was deleted in set_next_probe"); - lock_basic_unlock(&env->anchors->lock); - return 0; - } - log_assert(tp == tp2); - lock_basic_lock(&tp->lock); - - /* schedule */ - mold = wait_probe_time(env->anchors); - (void)rbtree_delete(&env->anchors->autr->probe, tp); - tp->autr->next_probe_time = calc_next_probe(env, - tp->autr->query_interval); - (void)rbtree_insert(&env->anchors->autr->probe, &tp->autr->pnode); - mnew = wait_probe_time(env->anchors); - - lock_basic_unlock(&env->anchors->lock); - verbose(VERB_ALGO, "next probe set in %d seconds", - (int)tp->autr->next_probe_time - (int)*env->now); - if(mold != mnew) { - reset_worker_timer(env); - } - return 1; -} - -/** Revoke and Delete a trust point */ -static void -autr_tp_remove(struct module_env* env, struct trust_anchor* tp, - struct ub_packed_rrset_key* dnskey_rrset) -{ - struct trust_anchor* del_tp; - struct trust_anchor key; - struct autr_point_data pd; - time_t mold, mnew; - - log_nametypeclass(VERB_OPS, "trust point was revoked", - tp->name, LDNS_RR_TYPE_DNSKEY, tp->dclass); - tp->autr->revoked = 1; - - /* use space allocated for dnskey_rrset to save name of anchor */ - memset(&key, 0, sizeof(key)); - memset(&pd, 0, sizeof(pd)); - key.autr = &pd; - key.node.key = &key; - pd.pnode.key = &key; - pd.next_probe_time = tp->autr->next_probe_time; - key.name = dnskey_rrset->rk.dname; - key.namelen = tp->namelen; - key.namelabs = tp->namelabs; - key.dclass = tp->dclass; - - /* unlock */ - lock_basic_unlock(&tp->lock); - - /* take from tree. It could be deleted by someone else,hence (void). */ - lock_basic_lock(&env->anchors->lock); - del_tp = (struct trust_anchor*)rbtree_delete(env->anchors->tree, &key); - mold = wait_probe_time(env->anchors); - (void)rbtree_delete(&env->anchors->autr->probe, &key); - mnew = wait_probe_time(env->anchors); - anchors_init_parents_locked(env->anchors); - lock_basic_unlock(&env->anchors->lock); - - /* if !del_tp then the trust point is no longer present in the tree, - * it was deleted by someone else, who will write the zonefile and - * clean up the structure */ - if(del_tp) { - /* save on disk */ - del_tp->autr->next_probe_time = 0; /* no more probing for it */ - autr_write_file(env, del_tp); - - /* delete */ - autr_point_delete(del_tp); - } - if(mold != mnew) { - reset_worker_timer(env); - } -} - -int autr_process_prime(struct module_env* env, struct val_env* ve, - struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, - struct module_qstate* qstate) -{ - int changed = 0; - log_assert(tp && tp->autr); - /* autotrust update trust anchors */ - /* the tp is locked, and stays locked unless it is deleted */ - - /* we could just catch the anchor here while another thread - * is busy deleting it. Just unlock and let the other do its job */ - if(tp->autr->revoked) { - log_nametypeclass(VERB_ALGO, "autotrust not processed, " - "trust point revoked", tp->name, - LDNS_RR_TYPE_DNSKEY, tp->dclass); - lock_basic_unlock(&tp->lock); - return 0; /* it is revoked */ - } - - /* query_dnskeys(): */ - tp->autr->last_queried = *env->now; - - log_nametypeclass(VERB_ALGO, "autotrust process for", - tp->name, LDNS_RR_TYPE_DNSKEY, tp->dclass); - /* see if time alone makes some keys valid */ - autr_holddown_exceed(env, tp, &changed); - if(changed) { - verbose(VERB_ALGO, "autotrust: morekeys, reassemble"); - if(!autr_assemble(tp)) { - log_err("malloc failure assembling autotrust keys"); - return 1; /* unchanged */ - } - } - /* did we get any data? */ - if(!dnskey_rrset) { - verbose(VERB_ALGO, "autotrust: no dnskey rrset"); - /* no update of query_failed, because then we would have - * to write to disk. But we cannot because we maybe are - * still 'initializing' with DS records, that we cannot write - * in the full format (which only contains KSKs). */ - return 1; /* trust point exists */ - } - /* check for revoked keys to remove immediately */ - check_contains_revoked(env, ve, tp, dnskey_rrset, &changed, qstate); - if(changed) { - verbose(VERB_ALGO, "autotrust: revokedkeys, reassemble"); - if(!autr_assemble(tp)) { - log_err("malloc failure assembling autotrust keys"); - return 1; /* unchanged */ - } - if(!tp->ds_rrset && !tp->dnskey_rrset) { - /* no more keys, all are revoked */ - /* this is a success for this probe attempt */ - tp->autr->last_success = *env->now; - autr_tp_remove(env, tp, dnskey_rrset); - return 0; /* trust point removed */ - } - } - /* verify the dnskey rrset and see if it is valid. */ - if(!verify_dnskey(env, ve, tp, dnskey_rrset, qstate)) { - verbose(VERB_ALGO, "autotrust: dnskey did not verify."); - /* only increase failure count if this is not the first prime, - * this means there was a previous successful probe */ - if(tp->autr->last_success) { - tp->autr->query_failed += 1; - autr_write_file(env, tp); - } - return 1; /* trust point exists */ - } - - tp->autr->last_success = *env->now; - tp->autr->query_failed = 0; - - /* Add new trust anchors to the data structure - * - note which trust anchors are seen this probe. - * Set trustpoint query_interval and retry_time. - * - find minimum rrsig expiration interval - */ - if(!update_events(env, ve, tp, dnskey_rrset, &changed)) { - log_err("malloc failure in autotrust update_events. " - "trust point unchanged."); - return 1; /* trust point unchanged, so exists */ - } - - /* - for every SEP key do the 5011 statetable. - * - remove missing trustanchors (if veryold and we have new anchors). - */ - if(!do_statetable(env, tp, &changed)) { - log_err("malloc failure in autotrust do_statetable. " - "trust point unchanged."); - return 1; /* trust point unchanged, so exists */ - } - - autr_cleanup_keys(tp); - if(!set_next_probe(env, tp, dnskey_rrset)) - return 0; /* trust point does not exist */ - autr_write_file(env, tp); - if(changed) { - verbose(VERB_ALGO, "autotrust: changed, reassemble"); - if(!autr_assemble(tp)) { - log_err("malloc failure assembling autotrust keys"); - return 1; /* unchanged */ - } - if(!tp->ds_rrset && !tp->dnskey_rrset) { - /* no more keys, all are revoked */ - autr_tp_remove(env, tp, dnskey_rrset); - return 0; /* trust point removed */ - } - } else verbose(VERB_ALGO, "autotrust: no changes"); - - return 1; /* trust point exists */ -} - -/** debug print a trust anchor key */ -static void -autr_debug_print_ta(struct autr_ta* ta) -{ - char buf[32]; - char* str = sldns_wire2str_rr(ta->rr, ta->rr_len); - if(!str) { - log_info("out of memory in debug_print_ta"); - return; - } - if(str[0]) str[strlen(str)-1]=0; /* remove newline */ - (void)autr_ctime_r(&ta->last_change, buf); - if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ - log_info("[%s] %s ;;state:%d ;;pending_count:%d%s%s last:%s", - trustanchor_state2str(ta->s), str, ta->s, ta->pending_count, - ta->fetched?" fetched":"", ta->revoked?" revoked":"", buf); - free(str); -} - -/** debug print a trust point */ -static void -autr_debug_print_tp(struct trust_anchor* tp) -{ - struct autr_ta* ta; - char buf[257]; - if(!tp->autr) - return; - dname_str(tp->name, buf); - log_info("trust point %s : %d", buf, (int)tp->dclass); - log_info("assembled %d DS and %d DNSKEYs", - (int)tp->numDS, (int)tp->numDNSKEY); - if(tp->ds_rrset) { - log_packed_rrset(NO_VERBOSE, "DS:", tp->ds_rrset); - } - if(tp->dnskey_rrset) { - log_packed_rrset(NO_VERBOSE, "DNSKEY:", tp->dnskey_rrset); - } - log_info("file %s", tp->autr->file); - (void)autr_ctime_r(&tp->autr->last_queried, buf); - if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ - log_info("last_queried: %u %s", (unsigned)tp->autr->last_queried, buf); - (void)autr_ctime_r(&tp->autr->last_success, buf); - if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ - log_info("last_success: %u %s", (unsigned)tp->autr->last_success, buf); - (void)autr_ctime_r(&tp->autr->next_probe_time, buf); - if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ - log_info("next_probe_time: %u %s", (unsigned)tp->autr->next_probe_time, - buf); - log_info("query_interval: %u", (unsigned)tp->autr->query_interval); - log_info("retry_time: %u", (unsigned)tp->autr->retry_time); - log_info("query_failed: %u", (unsigned)tp->autr->query_failed); - - for(ta=tp->autr->keys; ta; ta=ta->next) { - autr_debug_print_ta(ta); - } -} - -void -autr_debug_print(struct val_anchors* anchors) -{ - struct trust_anchor* tp; - lock_basic_lock(&anchors->lock); - RBTREE_FOR(tp, struct trust_anchor*, anchors->tree) { - lock_basic_lock(&tp->lock); - autr_debug_print_tp(tp); - lock_basic_unlock(&tp->lock); - } - lock_basic_unlock(&anchors->lock); -} - -void probe_answer_cb(void* arg, int ATTR_UNUSED(rcode), - sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(sec), - char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited)) -{ - /* retry was set before the query was done, - * re-querytime is set when query succeeded, but that may not - * have reset this timer because the query could have been - * handled by another thread. In that case, this callback would - * get called after the original timeout is done. - * By not resetting the timer, it may probe more often, but not - * less often. - * Unless the new lookup resulted in smaller TTLs and thus smaller - * timeout values. In that case one old TTL could be mistakenly done. - */ - struct module_env* env = (struct module_env*)arg; - verbose(VERB_ALGO, "autotrust probe answer cb"); - reset_worker_timer(env); -} - -/** probe a trust anchor DNSKEY and unlocks tp */ -static void -probe_anchor(struct module_env* env, struct trust_anchor* tp) -{ - struct query_info qinfo; - uint16_t qflags = BIT_RD; - struct edns_data edns; - sldns_buffer* buf = env->scratch_buffer; - qinfo.qname = regional_alloc_init(env->scratch, tp->name, tp->namelen); - if(!qinfo.qname) { - log_err("out of memory making 5011 probe"); - return; - } - qinfo.qname_len = tp->namelen; - qinfo.qtype = LDNS_RR_TYPE_DNSKEY; - qinfo.qclass = tp->dclass; - qinfo.local_alias = NULL; - log_query_info(VERB_ALGO, "autotrust probe", &qinfo); - verbose(VERB_ALGO, "retry probe set in %d seconds", - (int)tp->autr->next_probe_time - (int)*env->now); - edns.edns_present = 1; - edns.ext_rcode = 0; - edns.edns_version = 0; - edns.bits = EDNS_DO; - edns.opt_list_in = NULL; - edns.opt_list_out = NULL; - edns.opt_list_inplace_cb_out = NULL; - edns.padding_block_size = 0; - edns.cookie_present = 0; - edns.cookie_valid = 0; - if(sldns_buffer_capacity(buf) < 65535) - edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); - else edns.udp_size = 65535; - - /* can't hold the lock while mesh_run is processing */ - lock_basic_unlock(&tp->lock); - - /* delete the DNSKEY from rrset and key cache so an active probe - * is done. First the rrset so another thread does not use it - * to recreate the key entry in a race condition. */ - rrset_cache_remove(env->rrset_cache, qinfo.qname, qinfo.qname_len, - qinfo.qtype, qinfo.qclass, 0); - key_cache_remove(env->key_cache, qinfo.qname, qinfo.qname_len, - qinfo.qclass); - - if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, - &probe_answer_cb, env, 0)) { - log_err("out of memory making 5011 probe"); - } -} - -/** fetch first to-probe trust-anchor and lock it and set retrytime */ -static struct trust_anchor* -todo_probe(struct module_env* env, time_t* next) -{ - struct trust_anchor* tp; - rbnode_type* el; - /* get first one */ - lock_basic_lock(&env->anchors->lock); - if( (el=rbtree_first(&env->anchors->autr->probe)) == RBTREE_NULL) { - /* in case of revoked anchors */ - lock_basic_unlock(&env->anchors->lock); - /* signal that there are no anchors to probe */ - *next = 0; - return NULL; - } - tp = (struct trust_anchor*)el->key; - lock_basic_lock(&tp->lock); - - /* is it eligible? */ - if((time_t)tp->autr->next_probe_time > *env->now) { - /* no more to probe */ - *next = (time_t)tp->autr->next_probe_time - *env->now; - lock_basic_unlock(&tp->lock); - lock_basic_unlock(&env->anchors->lock); - return NULL; - } - - /* reset its next probe time */ - (void)rbtree_delete(&env->anchors->autr->probe, tp); - tp->autr->next_probe_time = calc_next_probe(env, tp->autr->retry_time); - (void)rbtree_insert(&env->anchors->autr->probe, &tp->autr->pnode); - lock_basic_unlock(&env->anchors->lock); - - return tp; -} - -time_t -autr_probe_timer(struct module_env* env) -{ - struct trust_anchor* tp; - time_t next_probe = 3600; - int num = 0; - if(autr_permit_small_holddown) next_probe = 1; - verbose(VERB_ALGO, "autotrust probe timer callback"); - /* while there are still anchors to probe */ - while( (tp = todo_probe(env, &next_probe)) ) { - /* make a probe for this anchor */ - probe_anchor(env, tp); - num++; - } - regional_free_all(env->scratch); - if(next_probe == 0) - return 0; /* no trust points to probe */ - verbose(VERB_ALGO, "autotrust probe timer %d callbacks done", num); - return next_probe; -} diff --git a/crates/libunbound-sys/unbound/validator/autotrust.h b/crates/libunbound-sys/unbound/validator/autotrust.h deleted file mode 100644 index 057f2b68..00000000 --- a/crates/libunbound-sys/unbound/validator/autotrust.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * validator/autotrust.h - RFC5011 trust anchor management for unbound. - * - * Copyright (c) 2009, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * Contains autotrust definitions. - */ - -#ifndef VALIDATOR_AUTOTRUST_H -#define VALIDATOR_AUTOTRUST_H -#include "util/rbtree.h" -#include "util/data/packed_rrset.h" -struct val_anchors; -struct trust_anchor; -struct ub_packed_rrset_key; -struct module_env; -struct module_qstate; -struct val_env; -struct sldns_buffer; - -/** Autotrust anchor states */ -typedef enum { - AUTR_STATE_START = 0, - AUTR_STATE_ADDPEND = 1, - AUTR_STATE_VALID = 2, - AUTR_STATE_MISSING = 3, - AUTR_STATE_REVOKED = 4, - AUTR_STATE_REMOVED = 5 -} autr_state_type; - -/** - * Autotrust metadata for one trust anchor key. - */ -struct autr_ta { - /** next key */ - struct autr_ta* next; - /** the RR */ - uint8_t* rr; - /** length of rr */ - size_t rr_len, dname_len; - /** last update of key state (new pending count keeps date the same) */ - time_t last_change; - /** 5011 state */ - autr_state_type s; - /** pending count */ - uint8_t pending_count; - /** fresh TA was seen */ - uint8_t fetched; - /** revoked TA was seen */ - uint8_t revoked; -}; - -/** - * Autotrust metadata for a trust point. - * This is part of the struct trust_anchor data. - */ -struct autr_point_data { - /** file to store the trust point in. chrootdir already applied. */ - char* file; - /** rbtree node for probe sort, key is struct trust_anchor */ - rbnode_type pnode; - - /** the keys */ - struct autr_ta* keys; - - /** last queried DNSKEY set - * Not all failures are captured in this entry. - * If the validator did not even start (e.g. timeout or localservfail), - * then the last_queried and query_failed values are not updated. - */ - time_t last_queried; - /** last successful DNSKEY set */ - time_t last_success; - /** next probe time */ - time_t next_probe_time; - - /** when to query if !failed */ - time_t query_interval; - /** when to retry if failed */ - time_t retry_time; - - /** - * How many times did it fail. diagnostic only (has no effect). - * Only updated if there was a dnskey rrset that failed to verify. - */ - uint8_t query_failed; - /** true if the trust point has been revoked */ - uint8_t revoked; -}; - -/** - * Autotrust global metadata. - */ -struct autr_global_data { - /** rbtree of autotrust anchors sorted by next probe time. - * When time is equal, sorted by anchor class, name. */ - rbtree_type probe; -}; - -/** - * Create new global 5011 data structure. - * @return new structure or NULL on malloc failure. - */ -struct autr_global_data* autr_global_create(void); - -/** - * Delete global 5011 data structure. - * @param global: global autotrust state to delete. - */ -void autr_global_delete(struct autr_global_data* global); - -/** - * See if autotrust anchors are configured and how many. - * @param anchors: the trust anchors structure. - * @return number of autotrust trust anchors - */ -size_t autr_get_num_anchors(struct val_anchors* anchors); - -/** - * Process probe timer. Add new probes if needed. - * @param env: module environment with time, with anchors and with the mesh. - * @return time of next probe (in seconds from now). - * If 0, then there is no next probe anymore (trust points deleted). - */ -time_t autr_probe_timer(struct module_env* env); - -/** probe tree compare function */ -int probetree_cmp(const void* x, const void* y); - -/** - * Read autotrust file. - * @param anchors: the anchors structure. - * @param nm: name of the file (copied). - * @return false on failure. - */ -int autr_read_file(struct val_anchors* anchors, const char* nm); - -/** - * Write autotrust file. - * @param env: environment with scratch space. - * @param tp: trust point to write. - */ -void autr_write_file(struct module_env* env, struct trust_anchor* tp); - -/** - * Delete autr anchor, deletes the autr data but does not do - * unlinking from trees, caller does that. - * @param tp: trust point to delete. - */ -void autr_point_delete(struct trust_anchor* tp); - -/** - * Perform autotrust processing. - * @param env: qstate environment with the anchors structure. - * @param ve: validator environment for verification of rrsigs. - * @param tp: trust anchor to process. - * @param dnskey_rrset: DNSKEY rrset probed (can be NULL if bad prime result). - * allocated in a region. Has not been validated yet. - * @param qstate: qstate with region. - * @return false if trust anchor was revoked completely. - * Otherwise logs errors to log, does not change return value. - * On errors, likely the trust point has been unchanged. - */ -int autr_process_prime(struct module_env* env, struct val_env* ve, - struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, - struct module_qstate* qstate); - -/** - * Debug printout of rfc5011 tracked anchors - * @param anchors: all the anchors. - */ -void autr_debug_print(struct val_anchors* anchors); - -/** callback for query answer to 5011 probe */ -void probe_answer_cb(void* arg, int rcode, struct sldns_buffer* buf, - enum sec_status sec, char* errinf, int was_ratelimited); - -#endif /* VALIDATOR_AUTOTRUST_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_anchor.c b/crates/libunbound-sys/unbound/validator/val_anchor.c deleted file mode 100644 index b1a54e1f..00000000 --- a/crates/libunbound-sys/unbound/validator/val_anchor.c +++ /dev/null @@ -1,1324 +0,0 @@ -/* - * validator/val_anchor.c - validator trust anchor storage. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains storage for the trust anchors for the validator. - */ -#include "config.h" -#include -#include "validator/val_anchor.h" -#include "validator/val_sigcrypt.h" -#include "validator/autotrust.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "util/as112.h" -#include "sldns/sbuffer.h" -#include "sldns/rrdef.h" -#include "sldns/str2wire.h" -#ifdef HAVE_GLOB_H -#include -#endif - -int -anchor_cmp(const void* k1, const void* k2) -{ - int m; - struct trust_anchor* n1 = (struct trust_anchor*)k1; - struct trust_anchor* n2 = (struct trust_anchor*)k2; - /* no need to ntohs(class) because sort order is irrelevant */ - if(n1->dclass != n2->dclass) { - if(n1->dclass < n2->dclass) - return -1; - return 1; - } - return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, - &m); -} - -struct val_anchors* -anchors_create(void) -{ - struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a)); - if(!a) - return NULL; - a->tree = rbtree_create(anchor_cmp); - if(!a->tree) { - anchors_delete(a); - return NULL; - } - a->autr = autr_global_create(); - if(!a->autr) { - anchors_delete(a); - return NULL; - } - lock_basic_init(&a->lock); - lock_protect(&a->lock, a, sizeof(*a)); - lock_protect(&a->lock, a->autr, sizeof(*a->autr)); - return a; -} - -/** delete assembled rrset */ -static void -assembled_rrset_delete(struct ub_packed_rrset_key* pkey) -{ - if(!pkey) return; - if(pkey->entry.data) { - struct packed_rrset_data* pd = (struct packed_rrset_data*) - pkey->entry.data; - free(pd->rr_data); - free(pd->rr_ttl); - free(pd->rr_len); - free(pd); - } - free(pkey->rk.dname); - free(pkey); -} - -/** destroy locks in tree and delete autotrust anchors */ -static void -anchors_delfunc(rbnode_type* elem, void* ATTR_UNUSED(arg)) -{ - struct trust_anchor* ta = (struct trust_anchor*)elem; - if(!ta) return; - if(ta->autr) { - autr_point_delete(ta); - } else { - struct ta_key* p, *np; - lock_basic_destroy(&ta->lock); - free(ta->name); - p = ta->keylist; - while(p) { - np = p->next; - free(p->data); - free(p); - p = np; - } - assembled_rrset_delete(ta->ds_rrset); - assembled_rrset_delete(ta->dnskey_rrset); - free(ta); - } -} - -void -anchors_delete(struct val_anchors* anchors) -{ - if(!anchors) - return; - lock_unprotect(&anchors->lock, anchors->autr); - lock_unprotect(&anchors->lock, anchors); - lock_basic_destroy(&anchors->lock); - if(anchors->tree) - traverse_postorder(anchors->tree, anchors_delfunc, NULL); - free(anchors->tree); - autr_global_delete(anchors->autr); - free(anchors); -} - -void -anchors_init_parents_locked(struct val_anchors* anchors) -{ - struct trust_anchor* node, *prev = NULL, *p; - int m; - /* nobody else can grab locks because we hold the main lock. - * Thus the previous items, after unlocked, are not deleted */ - RBTREE_FOR(node, struct trust_anchor*, anchors->tree) { - lock_basic_lock(&node->lock); - node->parent = NULL; - if(!prev || prev->dclass != node->dclass) { - prev = node; - lock_basic_unlock(&node->lock); - continue; - } - (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, - node->namelabs, &m); /* we know prev is smaller */ - /* sort order like: . com. bla.com. zwb.com. net. */ - /* find the previous, or parent-parent-parent */ - for(p = prev; p; p = p->parent) - /* looking for name with few labels, a parent */ - if(p->namelabs <= m) { - /* ==: since prev matched m, this is closest*/ - /* <: prev matches more, but is not a parent, - * this one is a (grand)parent */ - node->parent = p; - break; - } - lock_basic_unlock(&node->lock); - prev = node; - } -} - -/** initialise parent pointers in the tree */ -static void -init_parents(struct val_anchors* anchors) -{ - lock_basic_lock(&anchors->lock); - anchors_init_parents_locked(anchors); - lock_basic_unlock(&anchors->lock); -} - -struct trust_anchor* -anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs, - size_t namelen, uint16_t dclass) -{ - struct trust_anchor key; - rbnode_type* n; - if(!name) return NULL; - key.node.key = &key; - key.name = name; - key.namelabs = namelabs; - key.namelen = namelen; - key.dclass = dclass; - lock_basic_lock(&anchors->lock); - n = rbtree_search(anchors->tree, &key); - if(n) { - lock_basic_lock(&((struct trust_anchor*)n->key)->lock); - } - lock_basic_unlock(&anchors->lock); - if(!n) - return NULL; - return (struct trust_anchor*)n->key; -} - -/** create new trust anchor object */ -static struct trust_anchor* -anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs, - size_t namelen, uint16_t dclass, int lockit) -{ -#ifdef UNBOUND_DEBUG - rbnode_type* r; -#endif - struct trust_anchor* ta = (struct trust_anchor*)malloc( - sizeof(struct trust_anchor)); - if(!ta) - return NULL; - memset(ta, 0, sizeof(*ta)); - ta->node.key = ta; - ta->name = memdup(name, namelen); - if(!ta->name) { - free(ta); - return NULL; - } - ta->namelabs = namelabs; - ta->namelen = namelen; - ta->dclass = dclass; - lock_basic_init(&ta->lock); - if(lockit) { - lock_basic_lock(&anchors->lock); - } -#ifdef UNBOUND_DEBUG - r = -#else - (void) -#endif - rbtree_insert(anchors->tree, &ta->node); - if(lockit) { - lock_basic_unlock(&anchors->lock); - } - log_assert(r != NULL); - return ta; -} - -/** find trustanchor key by exact data match */ -static struct ta_key* -anchor_find_key(struct trust_anchor* ta, uint8_t* rdata, size_t rdata_len, - uint16_t type) -{ - struct ta_key* k; - for(k = ta->keylist; k; k = k->next) { - if(k->type == type && k->len == rdata_len && - memcmp(k->data, rdata, rdata_len) == 0) - return k; - } - return NULL; -} - -/** create new trustanchor key */ -static struct ta_key* -anchor_new_ta_key(uint8_t* rdata, size_t rdata_len, uint16_t type) -{ - struct ta_key* k = (struct ta_key*)malloc(sizeof(*k)); - if(!k) - return NULL; - memset(k, 0, sizeof(*k)); - k->data = memdup(rdata, rdata_len); - if(!k->data) { - free(k); - return NULL; - } - k->len = rdata_len; - k->type = type; - return k; -} - -/** - * This routine adds a new RR to a trust anchor. The trust anchor may not - * exist yet, and is created if not. The RR can be DS or DNSKEY. - * This routine will also remove duplicates; storing them only once. - * @param anchors: anchor storage. - * @param name: name of trust anchor (wireformat) - * @param type: type or RR - * @param dclass: class of RR - * @param rdata: rdata wireformat, starting with rdlength. - * If NULL, nothing is stored, but an entry is created. - * @param rdata_len: length of rdata including rdlength. - * @return: NULL on error, else the trust anchor. - */ -static struct trust_anchor* -anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type, - uint16_t dclass, uint8_t* rdata, size_t rdata_len) -{ - struct ta_key* k; - struct trust_anchor* ta; - int namelabs; - size_t namelen; - namelabs = dname_count_size_labels(name, &namelen); - if(type != LDNS_RR_TYPE_DS && type != LDNS_RR_TYPE_DNSKEY) { - log_err("Bad type for trust anchor"); - return 0; - } - /* lookup or create trustanchor */ - ta = anchor_find(anchors, name, namelabs, namelen, dclass); - if(!ta) { - ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass, 1); - if(!ta) - return NULL; - lock_basic_lock(&ta->lock); - } - if(!rdata) { - lock_basic_unlock(&ta->lock); - return ta; - } - /* look for duplicates */ - if(anchor_find_key(ta, rdata, rdata_len, type)) { - lock_basic_unlock(&ta->lock); - return ta; - } - k = anchor_new_ta_key(rdata, rdata_len, type); - if(!k) { - lock_basic_unlock(&ta->lock); - return NULL; - } - /* add new key */ - if(type == LDNS_RR_TYPE_DS) - ta->numDS++; - else ta->numDNSKEY++; - k->next = ta->keylist; - ta->keylist = k; - lock_basic_unlock(&ta->lock); - return ta; -} - -/** - * Add new RR. It converts ldns RR to wire format. - * @param anchors: anchor storage. - * @param rr: the wirerr. - * @param rl: length of rr. - * @param dl: length of dname. - * @return NULL on error, else the trust anchor. - */ -static struct trust_anchor* -anchor_store_new_rr(struct val_anchors* anchors, uint8_t* rr, size_t rl, - size_t dl) -{ - struct trust_anchor* ta; - if(!(ta=anchor_store_new_key(anchors, rr, - sldns_wirerr_get_type(rr, rl, dl), - sldns_wirerr_get_class(rr, rl, dl), - sldns_wirerr_get_rdatawl(rr, rl, dl), - sldns_wirerr_get_rdatalen(rr, rl, dl)+2))) { - return NULL; - } - log_nametypeclass(VERB_QUERY, "adding trusted key", - rr, sldns_wirerr_get_type(rr, rl, dl), - sldns_wirerr_get_class(rr, rl, dl)); - return ta; -} - -/** - * Insert insecure anchor - * @param anchors: anchor storage. - * @param str: the domain name. - * @return NULL on error, Else last trust anchor point - */ -static struct trust_anchor* -anchor_insert_insecure(struct val_anchors* anchors, const char* str) -{ - struct trust_anchor* ta; - size_t dname_len = 0; - uint8_t* nm = sldns_str2wire_dname(str, &dname_len); - if(!nm) { - log_err("parse error in domain name '%s'", str); - return NULL; - } - ta = anchor_store_new_key(anchors, nm, LDNS_RR_TYPE_DS, - LDNS_RR_CLASS_IN, NULL, 0); - free(nm); - return ta; -} - -struct trust_anchor* -anchor_store_str(struct val_anchors* anchors, sldns_buffer* buffer, - const char* str) -{ - struct trust_anchor* ta; - uint8_t* rr = sldns_buffer_begin(buffer); - size_t len = sldns_buffer_capacity(buffer), dname_len = 0; - int status = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, - 0, NULL, 0, NULL, 0); - if(status != 0) { - log_err("error parsing trust anchor %s: at %d: %s", - str, LDNS_WIREPARSE_OFFSET(status), - sldns_get_errorstr_parse(status)); - return NULL; - } - if(!(ta=anchor_store_new_rr(anchors, rr, len, dname_len))) { - log_err("out of memory"); - return NULL; - } - return ta; -} - -/** - * Read a file with trust anchors - * @param anchors: anchor storage. - * @param buffer: parsing buffer. - * @param fname: string. - * @param onlyone: only one trust anchor allowed in file. - * @return NULL on error. Else last trust-anchor point. - */ -static struct trust_anchor* -anchor_read_file(struct val_anchors* anchors, sldns_buffer* buffer, - const char* fname, int onlyone) -{ - struct trust_anchor* ta = NULL, *tanew; - struct sldns_file_parse_state pst; - int status; - size_t len, dname_len; - uint8_t* rr = sldns_buffer_begin(buffer); - int ok = 1; - FILE* in = fopen(fname, "r"); - if(!in) { - log_err("error opening file %s: %s", fname, strerror(errno)); - return 0; - } - memset(&pst, 0, sizeof(pst)); - pst.default_ttl = 3600; - pst.lineno = 1; - while(!feof(in)) { - len = sldns_buffer_capacity(buffer); - dname_len = 0; - status = sldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst); - if(len == 0) /* empty, $TTL, $ORIGIN */ - continue; - if(status != 0) { - log_err("parse error in %s:%d:%d : %s", fname, - pst.lineno, LDNS_WIREPARSE_OFFSET(status), - sldns_get_errorstr_parse(status)); - ok = 0; - break; - } - if(sldns_wirerr_get_type(rr, len, dname_len) != - LDNS_RR_TYPE_DS && sldns_wirerr_get_type(rr, len, - dname_len) != LDNS_RR_TYPE_DNSKEY) { - continue; - } - if(!(tanew=anchor_store_new_rr(anchors, rr, len, dname_len))) { - log_err("mem error at %s line %d", fname, pst.lineno); - ok = 0; - break; - } - if(onlyone && ta && ta != tanew) { - log_err("error at %s line %d: no multiple anchor " - "domains allowed (you can have multiple " - "keys, but they must have the same name).", - fname, pst.lineno); - ok = 0; - break; - } - ta = tanew; - } - fclose(in); - if(!ok) return NULL; - /* empty file is OK when multiple anchors are allowed */ - if(!onlyone && !ta) return (struct trust_anchor*)1; - return ta; -} - -/** skip file to end of line */ -static void -skip_to_eol(FILE* in) -{ - int c; - while((c = getc(in)) != EOF ) { - if(c == '\n') - return; - } -} - -/** true for special characters in bind configs */ -static int -is_bind_special(int c) -{ - switch(c) { - case '{': - case '}': - case '"': - case ';': - return 1; - } - return 0; -} - -/** - * Read a keyword skipping bind comments; spaces, specials, restkeywords. - * The file is split into the following tokens: - * * special characters, on their own, rdlen=1, { } doublequote ; - * * whitespace becomes a single ' ' or tab. Newlines become spaces. - * * other words ('keywords') - * * comments are skipped if desired - * / / C++ style comment to end of line - * # to end of line - * / * C style comment * / - * @param in: file to read from. - * @param buf: buffer, what is read is stored after current buffer position. - * Space is left in the buffer to write a terminating 0. - * @param line: line number is increased per line, for error reports. - * @param comments: if 0, comments are not possible and become text. - * if 1, comments are skipped entirely. - * In BIND files, this is when reading quoted strings, for example - * " base 64 text with / / in there " - * @return the number of character written to the buffer. - * 0 on end of file. - */ -static int -readkeyword_bindfile(FILE* in, sldns_buffer* buf, int* line, int comments) -{ - int c; - int numdone = 0; - while((c = getc(in)) != EOF ) { - if(comments && c == '#') { /* # blabla */ - skip_to_eol(in); - (*line)++; - continue; - } else if(comments && c=='/' && numdone>0 && /* /_/ bla*/ - sldns_buffer_read_u8_at(buf, - sldns_buffer_position(buf)-1) == '/') { - sldns_buffer_skip(buf, -1); - numdone--; - skip_to_eol(in); - (*line)++; - continue; - } else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */ - sldns_buffer_read_u8_at(buf, - sldns_buffer_position(buf)-1) == '/') { - sldns_buffer_skip(buf, -1); - numdone--; - /* skip to end of comment */ - while(c != EOF && (c=getc(in)) != EOF ) { - if(c == '*') { - if((c=getc(in)) == '/') - break; - } - if(c == '\n') - (*line)++; - } - continue; - } - /* not a comment, complete the keyword */ - if(numdone > 0) { - /* check same type */ - if(isspace((unsigned char)c)) { - ungetc(c, in); - return numdone; - } - if(is_bind_special(c)) { - ungetc(c, in); - return numdone; - } - } - if(c == '\n') { - c = ' '; - (*line)++; - } - /* space for 1 char + 0 string terminator */ - if(sldns_buffer_remaining(buf) < 2) { - fatal_exit("trusted-keys, %d, string too long", *line); - } - sldns_buffer_write_u8(buf, (uint8_t)c); - numdone++; - if(isspace((unsigned char)c)) { - /* collate whitespace into ' ' */ - while((c = getc(in)) != EOF ) { - if(c == '\n') - (*line)++; - if(!isspace((unsigned char)c)) { - ungetc(c, in); - break; - } - } - return numdone; - } - if(is_bind_special(c)) - return numdone; - } - return numdone; -} - -/** skip through file to { or ; */ -static int -skip_to_special(FILE* in, sldns_buffer* buf, int* line, int spec) -{ - int rdlen; - sldns_buffer_clear(buf); - while((rdlen=readkeyword_bindfile(in, buf, line, 1))) { - if(rdlen == 1 && isspace((unsigned char)*sldns_buffer_begin(buf))) { - sldns_buffer_clear(buf); - continue; - } - if(rdlen != 1 || *sldns_buffer_begin(buf) != (uint8_t)spec) { - sldns_buffer_write_u8(buf, 0); - log_err("trusted-keys, line %d, expected %c", - *line, spec); - return 0; - } - return 1; - } - log_err("trusted-keys, line %d, expected %c got EOF", *line, spec); - return 0; -} - -/** - * read contents of trusted-keys{ ... ; clauses and insert keys into storage. - * @param anchors: where to store keys - * @param buf: buffer to use - * @param line: line number in file - * @param in: file to read from. - * @return 0 on error. - */ -static int -process_bind_contents(struct val_anchors* anchors, sldns_buffer* buf, - int* line, FILE* in) -{ - /* loop over contents, collate strings before ; */ - /* contents is (numbered): 0 1 2 3 4 5 6 7 8 */ - /* name. 257 3 5 base64 base64 */ - /* quoted value: 0 "111" 0 0 0 0 0 0 0 */ - /* comments value: 1 "000" 1 1 1 "0 0 0 0" 1 */ - int contnum = 0; - int quoted = 0; - int comments = 1; - int rdlen; - char* str = 0; - sldns_buffer_clear(buf); - while((rdlen=readkeyword_bindfile(in, buf, line, comments))) { - if(rdlen == 1 && sldns_buffer_position(buf) == 1 - && isspace((unsigned char)*sldns_buffer_begin(buf))) { - /* starting whitespace is removed */ - sldns_buffer_clear(buf); - continue; - } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == '"') { - /* remove " from the string */ - if(contnum == 0) { - quoted = 1; - comments = 0; - } - sldns_buffer_skip(buf, -1); - if(contnum > 0 && quoted) { - if(sldns_buffer_remaining(buf) < 8+1) { - log_err("line %d, too long", *line); - return 0; - } - sldns_buffer_write(buf, " DNSKEY ", 8); - quoted = 0; - comments = 1; - } else if(contnum > 0) - comments = !comments; - continue; - } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == ';') { - - if(contnum < 5) { - sldns_buffer_write_u8(buf, 0); - log_err("line %d, bad key", *line); - return 0; - } - sldns_buffer_skip(buf, -1); - sldns_buffer_write_u8(buf, 0); - str = strdup((char*)sldns_buffer_begin(buf)); - if(!str) { - log_err("line %d, allocation failure", *line); - return 0; - } - if(!anchor_store_str(anchors, buf, str)) { - log_err("line %d, bad key", *line); - free(str); - return 0; - } - free(str); - sldns_buffer_clear(buf); - contnum = 0; - quoted = 0; - comments = 1; - continue; - } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == '}') { - if(contnum > 0) { - sldns_buffer_write_u8(buf, 0); - log_err("line %d, bad key before }", *line); - return 0; - } - return 1; - } else if(rdlen == 1 && - isspace((unsigned char)sldns_buffer_current(buf)[-1])) { - /* leave whitespace here */ - } else { - /* not space or whatnot, so actual content */ - contnum ++; - if(contnum == 1 && !quoted) { - if(sldns_buffer_remaining(buf) < 8+1) { - log_err("line %d, too long", *line); - return 0; - } - sldns_buffer_write(buf, " DNSKEY ", 8); - } - } - } - - log_err("line %d, EOF before }", *line); - return 0; -} - -/** - * Read a BIND9 like file with trust anchors in named.conf format. - * @param anchors: anchor storage. - * @param buffer: parsing buffer. - * @param fname: string. - * @return false on error. - */ -static int -anchor_read_bind_file(struct val_anchors* anchors, sldns_buffer* buffer, - const char* fname) -{ - int line_nr = 1; - FILE* in = fopen(fname, "r"); - int rdlen = 0; - if(!in) { - log_err("error opening file %s: %s", fname, strerror(errno)); - return 0; - } - verbose(VERB_QUERY, "reading in bind-compat-mode: '%s'", fname); - /* scan for trusted-keys keyword, ignore everything else */ - sldns_buffer_clear(buffer); - while((rdlen=readkeyword_bindfile(in, buffer, &line_nr, 1)) != 0) { - if(rdlen != 12 || strncmp((char*)sldns_buffer_begin(buffer), - "trusted-keys", 12) != 0) { - sldns_buffer_clear(buffer); - /* ignore everything but trusted-keys */ - continue; - } - if(!skip_to_special(in, buffer, &line_nr, '{')) { - log_err("error in trusted key: \"%s\"", fname); - fclose(in); - return 0; - } - /* process contents */ - if(!process_bind_contents(anchors, buffer, &line_nr, in)) { - log_err("error in trusted key: \"%s\"", fname); - fclose(in); - return 0; - } - if(!skip_to_special(in, buffer, &line_nr, ';')) { - log_err("error in trusted key: \"%s\"", fname); - fclose(in); - return 0; - } - sldns_buffer_clear(buffer); - } - fclose(in); - return 1; -} - -/** - * Read a BIND9 like files with trust anchors in named.conf format. - * Performs wildcard processing of name. - * @param anchors: anchor storage. - * @param buffer: parsing buffer. - * @param pat: pattern string. (can be wildcarded) - * @return false on error. - */ -static int -anchor_read_bind_file_wild(struct val_anchors* anchors, sldns_buffer* buffer, - const char* pat) -{ -#ifdef HAVE_GLOB - glob_t g; - size_t i; - int r, flags; - if(!strchr(pat, '*') && !strchr(pat, '?') && !strchr(pat, '[') && - !strchr(pat, '{') && !strchr(pat, '~')) { - return anchor_read_bind_file(anchors, buffer, pat); - } - verbose(VERB_QUERY, "wildcard found, processing %s", pat); - flags = 0 -#ifdef GLOB_ERR - | GLOB_ERR -#endif -#ifdef GLOB_NOSORT - | GLOB_NOSORT -#endif -#ifdef GLOB_BRACE - | GLOB_BRACE -#endif -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif - ; - memset(&g, 0, sizeof(g)); - r = glob(pat, flags, NULL, &g); - if(r) { - /* some error */ - if(r == GLOB_NOMATCH) { - verbose(VERB_QUERY, "trusted-keys-file: " - "no matches for %s", pat); - return 1; - } else if(r == GLOB_NOSPACE) { - log_err("wildcard trusted-keys-file %s: " - "pattern out of memory", pat); - } else if(r == GLOB_ABORTED) { - log_err("wildcard trusted-keys-file %s: expansion " - "aborted (%s)", pat, strerror(errno)); - } else { - log_err("wildcard trusted-keys-file %s: expansion " - "failed (%s)", pat, strerror(errno)); - } - /* ignore globs that yield no files */ - return 1; - } - /* process files found, if any */ - for(i=0; i<(size_t)g.gl_pathc; i++) { - if(!anchor_read_bind_file(anchors, buffer, g.gl_pathv[i])) { - log_err("error reading wildcard " - "trusted-keys-file: %s", g.gl_pathv[i]); - globfree(&g); - return 0; - } - } - globfree(&g); - return 1; -#else /* not HAVE_GLOB */ - return anchor_read_bind_file(anchors, buffer, pat); -#endif /* HAVE_GLOB */ -} - -/** - * Assemble an rrset structure for the type - * @param ta: trust anchor. - * @param num: number of items to fetch from list. - * @param type: fetch only items of this type. - * @return rrset or NULL on error. - */ -static struct ub_packed_rrset_key* -assemble_it(struct trust_anchor* ta, size_t num, uint16_t type) -{ - struct ub_packed_rrset_key* pkey = (struct ub_packed_rrset_key*) - malloc(sizeof(*pkey)); - struct packed_rrset_data* pd; - struct ta_key* tk; - size_t i; - if(!pkey) - return NULL; - memset(pkey, 0, sizeof(*pkey)); - pkey->rk.dname = memdup(ta->name, ta->namelen); - if(!pkey->rk.dname) { - free(pkey); - return NULL; - } - - pkey->rk.dname_len = ta->namelen; - pkey->rk.type = htons(type); - pkey->rk.rrset_class = htons(ta->dclass); - /* The rrset is build in an uncompressed way. This means it - * cannot be copied in the normal way. */ - pd = (struct packed_rrset_data*)malloc(sizeof(*pd)); - if(!pd) { - free(pkey->rk.dname); - free(pkey); - return NULL; - } - memset(pd, 0, sizeof(*pd)); - pd->count = num; - pd->trust = rrset_trust_ultimate; - pd->rr_len = (size_t*)reallocarray(NULL, num, sizeof(size_t)); - if(!pd->rr_len) { - free(pd); - free(pkey->rk.dname); - free(pkey); - return NULL; - } - pd->rr_ttl = (time_t*)reallocarray(NULL, num, sizeof(time_t)); - if(!pd->rr_ttl) { - free(pd->rr_len); - free(pd); - free(pkey->rk.dname); - free(pkey); - return NULL; - } - pd->rr_data = (uint8_t**)reallocarray(NULL, num, sizeof(uint8_t*)); - if(!pd->rr_data) { - free(pd->rr_ttl); - free(pd->rr_len); - free(pd); - free(pkey->rk.dname); - free(pkey); - return NULL; - } - /* fill in rrs */ - i=0; - for(tk = ta->keylist; tk; tk = tk->next) { - if(tk->type != type) - continue; - pd->rr_len[i] = tk->len; - /* reuse data ptr to allocation in talist */ - pd->rr_data[i] = tk->data; - pd->rr_ttl[i] = 0; - i++; - } - pkey->entry.data = (void*)pd; - return pkey; -} - -/** - * Assemble structures for the trust DS and DNSKEY rrsets. - * @param ta: trust anchor - * @return: false on error. - */ -static int -anchors_assemble(struct trust_anchor* ta) -{ - if(ta->numDS > 0) { - ta->ds_rrset = assemble_it(ta, ta->numDS, LDNS_RR_TYPE_DS); - if(!ta->ds_rrset) - return 0; - } - if(ta->numDNSKEY > 0) { - ta->dnskey_rrset = assemble_it(ta, ta->numDNSKEY, - LDNS_RR_TYPE_DNSKEY); - if(!ta->dnskey_rrset) - return 0; - } - return 1; -} - -/** - * Check DS algos for support, warn if not. - * @param ta: trust anchor - * @return number of DS anchors with unsupported algorithms. - */ -static size_t -anchors_ds_unsupported(struct trust_anchor* ta) -{ - size_t i, num = 0; - for(i=0; inumDS; i++) { - if(!ds_digest_algo_is_supported(ta->ds_rrset, i) || - !ds_key_algo_is_supported(ta->ds_rrset, i)) - num++; - } - return num; -} - -/** - * Check DNSKEY algos for support, warn if not. - * @param ta: trust anchor - * @return number of DNSKEY anchors with unsupported algorithms. - */ -static size_t -anchors_dnskey_unsupported(struct trust_anchor* ta) -{ - size_t i, num = 0; - for(i=0; inumDNSKEY; i++) { - if(!dnskey_algo_is_supported(ta->dnskey_rrset, i) || - !dnskey_size_is_supported(ta->dnskey_rrset, i)) - num++; - } - return num; -} - -/** - * Assemble the rrsets in the anchors, ready for use by validator. - * @param anchors: trust anchor storage. - * @return: false on error. - */ -static int -anchors_assemble_rrsets(struct val_anchors* anchors) -{ - struct trust_anchor* ta; - struct trust_anchor* next; - size_t nods, nokey; - lock_basic_lock(&anchors->lock); - ta=(struct trust_anchor*)rbtree_first(anchors->tree); - while((rbnode_type*)ta != RBTREE_NULL) { - next = (struct trust_anchor*)rbtree_next(&ta->node); - lock_basic_lock(&ta->lock); - if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) { - lock_basic_unlock(&ta->lock); - ta = next; /* skip */ - continue; - } - if(!anchors_assemble(ta)) { - log_err("out of memory"); - lock_basic_unlock(&ta->lock); - lock_basic_unlock(&anchors->lock); - return 0; - } - nods = anchors_ds_unsupported(ta); - nokey = anchors_dnskey_unsupported(ta); - if(nods) { - log_nametypeclass(NO_VERBOSE, "warning: unsupported " - "algorithm for trust anchor", - ta->name, LDNS_RR_TYPE_DS, ta->dclass); - } - if(nokey) { - log_nametypeclass(NO_VERBOSE, "warning: unsupported " - "algorithm for trust anchor", - ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); - } - if(nods == ta->numDS && nokey == ta->numDNSKEY) { - char b[257]; - dname_str(ta->name, b); - log_warn("trust anchor %s has no supported algorithms," - " the anchor is ignored (check if you need to" - " upgrade unbound and " -#ifdef HAVE_LIBRESSL - "libressl" -#else - "openssl" -#endif - ")", b); - (void)rbtree_delete(anchors->tree, &ta->node); - lock_basic_unlock(&ta->lock); - anchors_delfunc(&ta->node, NULL); - ta = next; - continue; - } - lock_basic_unlock(&ta->lock); - ta = next; - } - lock_basic_unlock(&anchors->lock); - return 1; -} - -int -anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg) -{ - struct config_strlist* f; - const char** zstr; - char* nm; - sldns_buffer* parsebuf = sldns_buffer_new(65535); - if(!parsebuf) { - log_err("malloc error in anchors_apply_cfg."); - return 0; - } - if(cfg->insecure_lan_zones) { - for(zstr = as112_zones; *zstr; zstr++) { - if(!anchor_insert_insecure(anchors, *zstr)) { - log_err("error in insecure-lan-zones: %s", *zstr); - sldns_buffer_free(parsebuf); - return 0; - } - } - } - for(f = cfg->domain_insecure; f; f = f->next) { - if(!f->str || f->str[0] == 0) /* empty "" */ - continue; - if(!anchor_insert_insecure(anchors, f->str)) { - log_err("error in domain-insecure: %s", f->str); - sldns_buffer_free(parsebuf); - return 0; - } - } - for(f = cfg->trust_anchor_file_list; f; f = f->next) { - if(!f->str || f->str[0] == 0) /* empty "" */ - continue; - nm = f->str; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - nm += strlen(cfg->chrootdir); - if(!anchor_read_file(anchors, parsebuf, nm, 0)) { - log_err("error reading trust-anchor-file: %s", f->str); - sldns_buffer_free(parsebuf); - return 0; - } - } - for(f = cfg->trusted_keys_file_list; f; f = f->next) { - if(!f->str || f->str[0] == 0) /* empty "" */ - continue; - nm = f->str; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - nm += strlen(cfg->chrootdir); - if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) { - log_err("error reading trusted-keys-file: %s", f->str); - sldns_buffer_free(parsebuf); - return 0; - } - } - for(f = cfg->trust_anchor_list; f; f = f->next) { - if(!f->str || f->str[0] == 0) /* empty "" */ - continue; - if(!anchor_store_str(anchors, parsebuf, f->str)) { - log_err("error in trust-anchor: \"%s\"", f->str); - sldns_buffer_free(parsebuf); - return 0; - } - } - /* do autr last, so that it sees what anchors are filled by other - * means can can print errors about double config for the name */ - for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) { - if(!f->str || f->str[0] == 0) /* empty "" */ - continue; - nm = f->str; - if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, - cfg->chrootdir, strlen(cfg->chrootdir)) == 0) - nm += strlen(cfg->chrootdir); - if(!autr_read_file(anchors, nm)) { - log_err("error reading auto-trust-anchor-file: %s", - f->str); - sldns_buffer_free(parsebuf); - return 0; - } - } - /* first assemble, since it may delete useless anchors */ - anchors_assemble_rrsets(anchors); - init_parents(anchors); - sldns_buffer_free(parsebuf); - if(verbosity >= VERB_ALGO) autr_debug_print(anchors); - return 1; -} - -struct trust_anchor* -anchors_lookup(struct val_anchors* anchors, - uint8_t* qname, size_t qname_len, uint16_t qclass) -{ - struct trust_anchor key; - struct trust_anchor* result; - rbnode_type* res = NULL; - key.node.key = &key; - key.name = qname; - key.namelabs = dname_count_labels(qname); - key.namelen = qname_len; - key.dclass = qclass; - lock_basic_lock(&anchors->lock); - if(rbtree_find_less_equal(anchors->tree, &key, &res)) { - /* exact */ - result = (struct trust_anchor*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct trust_anchor*)res; - if(!result || result->dclass != qclass) { - lock_basic_unlock(&anchors->lock); - return NULL; - } - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->namelabs, key.name, - key.namelabs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->namelabs <= m) - break; - result = result->parent; - } - } - if(result) { - lock_basic_lock(&result->lock); - } - lock_basic_unlock(&anchors->lock); - return result; -} - -size_t -anchors_get_mem(struct val_anchors* anchors) -{ - struct trust_anchor *ta; - size_t s = sizeof(*anchors); - if(!anchors) - return 0; - RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) { - s += sizeof(*ta) + ta->namelen; - /* keys and so on */ - } - return s; -} - -int -anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm) -{ - struct trust_anchor key; - key.node.key = &key; - key.name = nm; - key.namelabs = dname_count_size_labels(nm, &key.namelen); - key.dclass = c; - lock_basic_lock(&anchors->lock); - if(rbtree_search(anchors->tree, &key)) { - lock_basic_unlock(&anchors->lock); - /* nothing to do, already an anchor or insecure point */ - return 1; - } - if(!anchor_new_ta(anchors, nm, key.namelabs, key.namelen, c, 0)) { - log_err("out of memory"); - lock_basic_unlock(&anchors->lock); - return 0; - } - /* no other contents in new ta, because it is insecure point */ - anchors_init_parents_locked(anchors); - lock_basic_unlock(&anchors->lock); - return 1; -} - -void -anchors_delete_insecure(struct val_anchors* anchors, uint16_t c, - uint8_t* nm) -{ - struct trust_anchor key; - struct trust_anchor* ta; - key.node.key = &key; - key.name = nm; - key.namelabs = dname_count_size_labels(nm, &key.namelen); - key.dclass = c; - lock_basic_lock(&anchors->lock); - if(!(ta=(struct trust_anchor*)rbtree_search(anchors->tree, &key))) { - lock_basic_unlock(&anchors->lock); - /* nothing there */ - return; - } - /* lock it to drive away other threads that use it */ - lock_basic_lock(&ta->lock); - /* see if its really an insecure point */ - if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) { - lock_basic_unlock(&anchors->lock); - lock_basic_unlock(&ta->lock); - /* its not an insecure point, do not remove it */ - return; - } - - /* remove from tree */ - (void)rbtree_delete(anchors->tree, &ta->node); - anchors_init_parents_locked(anchors); - lock_basic_unlock(&anchors->lock); - - /* actual free of data */ - lock_basic_unlock(&ta->lock); - anchors_delfunc(&ta->node, NULL); -} - -/** compare two keytags, return -1, 0 or 1 */ -static int -keytag_compare(const void* x, const void* y) -{ - if(*(uint16_t*)x == *(uint16_t*)y) - return 0; - if(*(uint16_t*)x > *(uint16_t*)y) - return 1; - return -1; -} - -size_t -anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num) -{ - size_t i, ret = 0; - if(ta->numDS == 0 && ta->numDNSKEY == 0) - return 0; /* insecure point */ - if(ta->numDS != 0 && ta->ds_rrset) { - struct packed_rrset_data* d=(struct packed_rrset_data*) - ta->ds_rrset->entry.data; - for(i=0; icount; i++) { - if(ret == num) continue; - list[ret++] = ds_get_keytag(ta->ds_rrset, i); - } - } - if(ta->numDNSKEY != 0 && ta->dnskey_rrset) { - struct packed_rrset_data* d=(struct packed_rrset_data*) - ta->dnskey_rrset->entry.data; - for(i=0; icount; i++) { - if(ret == num) continue; - list[ret++] = dnskey_calc_keytag(ta->dnskey_rrset, i); - } - } - qsort(list, ret, sizeof(*list), keytag_compare); - return ret; -} - -int -anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, - size_t namelen, uint16_t dclass, uint16_t keytag) -{ - uint16_t* taglist; - uint16_t* tl; - size_t numtag, i; - struct trust_anchor* anchor = anchor_find(anchors, - name, namelabs, namelen, dclass); - if(!anchor) - return 0; - if(!anchor->numDS && !anchor->numDNSKEY) { - lock_basic_unlock(&anchor->lock); - return 0; - } - - taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist)); - if(!taglist) { - lock_basic_unlock(&anchor->lock); - return 0; - } - - numtag = anchor_list_keytags(anchor, taglist, - anchor->numDS+anchor->numDNSKEY); - lock_basic_unlock(&anchor->lock); - if(!numtag) { - free(taglist); - return 0; - } - tl = taglist; - for(i=0; ikey_cache_slabs; - start_size = HASH_DEFAULT_STARTARRAY; - maxmem = cfg->key_cache_size; - kcache->slab = slabhash_create(numtables, start_size, maxmem, - &key_entry_sizefunc, &key_entry_compfunc, - &key_entry_delkeyfunc, &key_entry_deldatafunc, NULL); - if(!kcache->slab) { - log_err("malloc failure"); - free(kcache); - return NULL; - } - return kcache; -} - -void -key_cache_delete(struct key_cache* kcache) -{ - if(!kcache) - return; - slabhash_delete(kcache->slab); - free(kcache); -} - -void -key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey, - int copy_reason) -{ - struct key_entry_key* k = key_entry_copy(kkey, copy_reason); - if(!k) - return; - key_entry_hash(k); - slabhash_insert(kcache->slab, k->entry.hash, &k->entry, - k->entry.data, NULL); -} - -/** - * Lookup exactly in the key cache. Returns pointer to locked entry. - * Caller must unlock it after use. - * @param kcache: the key cache. - * @param name: for what name to look; uncompressed wireformat - * @param namelen: length of the name. - * @param key_class: class of the key. - * @param wr: set true to get a writelock. - * @return key entry, locked, or NULL if not found. No TTL checking is - * performed. - */ -static struct key_entry_key* -key_cache_search(struct key_cache* kcache, uint8_t* name, size_t namelen, - uint16_t key_class, int wr) -{ - struct lruhash_entry* e; - struct key_entry_key lookfor; - lookfor.entry.key = &lookfor; - lookfor.name = name; - lookfor.namelen = namelen; - lookfor.key_class = key_class; - key_entry_hash(&lookfor); - e = slabhash_lookup(kcache->slab, lookfor.entry.hash, &lookfor, wr); - if(!e) - return NULL; - return (struct key_entry_key*)e->key; -} - -struct key_entry_key* -key_cache_obtain(struct key_cache* kcache, uint8_t* name, size_t namelen, - uint16_t key_class, struct regional* region, time_t now) -{ - /* keep looking until we find a nonexpired entry */ - while(1) { - struct key_entry_key* k = key_cache_search(kcache, name, - namelen, key_class, 0); - if(k) { - /* see if TTL is OK */ - struct key_entry_data* d = (struct key_entry_data*) - k->entry.data; - if(now <= d->ttl) { - /* copy and return it */ - struct key_entry_key* retkey = - key_entry_copy_toregion(k, region); - lock_rw_unlock(&k->entry.lock); - return retkey; - } - lock_rw_unlock(&k->entry.lock); - } - /* snip off first label to continue */ - if(dname_is_root(name)) - break; - dname_remove_label(&name, &namelen); - } - return NULL; -} - -size_t -key_cache_get_mem(struct key_cache* kcache) -{ - return sizeof(*kcache) + slabhash_get_mem(kcache->slab); -} - -void key_cache_remove(struct key_cache* kcache, - uint8_t* name, size_t namelen, uint16_t key_class) -{ - struct key_entry_key lookfor; - lookfor.entry.key = &lookfor; - lookfor.name = name; - lookfor.namelen = namelen; - lookfor.key_class = key_class; - key_entry_hash(&lookfor); - slabhash_remove(kcache->slab, lookfor.entry.hash, &lookfor); -} diff --git a/crates/libunbound-sys/unbound/validator/val_kcache.h b/crates/libunbound-sys/unbound/validator/val_kcache.h deleted file mode 100644 index df8de099..00000000 --- a/crates/libunbound-sys/unbound/validator/val_kcache.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * validator/val_kcache.h - validator key shared cache with validated keys - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for caching validated key entries. - */ - -#ifndef VALIDATOR_VAL_KCACHE_H -#define VALIDATOR_VAL_KCACHE_H -#include "util/storage/slabhash.h" -struct key_entry_key; -struct key_entry_data; -struct config_file; -struct regional; -struct module_qstate; - -/** - * Key cache - */ -struct key_cache { - /** uses slabhash for storage, type key_entry_key, key_entry_data */ - struct slabhash* slab; -}; - -/** - * Create the key cache - * @param cfg: config settings for the key cache. - * @return new key cache or NULL on malloc failure. - */ -struct key_cache* key_cache_create(struct config_file* cfg); - -/** - * Delete the key cache - * @param kcache: to delete - */ -void key_cache_delete(struct key_cache* kcache); - -/** - * Insert or update a key cache entry. Note that the insert may silently - * fail if there is not enough memory. - * - * @param kcache: the key cache. - * @param kkey: key entry key, assumed malloced in a region, is copied - * to perform update or insertion. Its data pointer is also copied. - * @param copy_reason: if the reason string needs to be copied (allocated). - */ -void key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey, - int copy_reason); - -/** - * Remove an entry from the key cache. - * @param kcache: the key cache. - * @param name: for what name to look; uncompressed wireformat - * @param namelen: length of the name. - * @param key_class: class of the key. - */ -void key_cache_remove(struct key_cache* kcache, - uint8_t* name, size_t namelen, uint16_t key_class); - -/** - * Lookup key entry in the cache. Looks up the closest key entry above the - * given name. - * @param kcache: the key cache. - * @param name: for what name to look; uncompressed wireformat - * @param namelen: length of the name. - * @param key_class: class of the key. - * @param region: a copy of the key_entry is allocated in this region. - * @param now: current time. - * @return pointer to a newly allocated key_entry copy in the region, if - * a key entry could be found, and allocation succeeded and TTL was OK. - * Otherwise, NULL is returned. - */ -struct key_entry_key* key_cache_obtain(struct key_cache* kcache, - uint8_t* name, size_t namelen, uint16_t key_class, - struct regional* region, time_t now); - -/** - * Get memory in use by the key cache. - * @param kcache: the key cache. - * @return memory in use in bytes. - */ -size_t key_cache_get_mem(struct key_cache* kcache); - -#endif /* VALIDATOR_VAL_KCACHE_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_kentry.c b/crates/libunbound-sys/unbound/validator/val_kentry.c deleted file mode 100644 index 85f02640..00000000 --- a/crates/libunbound-sys/unbound/validator/val_kentry.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * validator/val_kentry.c - validator key entry definition. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for dealing with validator key entries. - */ -#include "config.h" -#include "validator/val_kentry.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/storage/lookup3.h" -#include "util/regional.h" -#include "util/net_help.h" -#include "sldns/rrdef.h" -#include "sldns/keyraw.h" - -size_t -key_entry_sizefunc(void* key, void* data) -{ - struct key_entry_key* kk = (struct key_entry_key*)key; - struct key_entry_data* kd = (struct key_entry_data*)data; - size_t s = sizeof(*kk) + kk->namelen; - s += sizeof(*kd) + lock_get_mem(&kk->entry.lock); - if(kd->rrset_data) - s += packed_rrset_sizeof(kd->rrset_data); - if(kd->reason) - s += strlen(kd->reason)+1; - if(kd->algo) - s += strlen((char*)kd->algo)+1; - return s; -} - -int -key_entry_compfunc(void* k1, void* k2) -{ - struct key_entry_key* n1 = (struct key_entry_key*)k1; - struct key_entry_key* n2 = (struct key_entry_key*)k2; - if(n1->key_class != n2->key_class) { - if(n1->key_class < n2->key_class) - return -1; - return 1; - } - return query_dname_compare(n1->name, n2->name); -} - -void -key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) -{ - struct key_entry_key* kk = (struct key_entry_key*)key; - if(!key) - return; - lock_rw_destroy(&kk->entry.lock); - free(kk->name); - free(kk); -} - -void -key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg)) -{ - struct key_entry_data* kd = (struct key_entry_data*)data; - free(kd->reason); - free(kd->rrset_data); - free(kd->algo); - free(kd); -} - -void -key_entry_hash(struct key_entry_key* kk) -{ - kk->entry.hash = 0x654; - kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), - kk->entry.hash); - kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash); -} - -struct key_entry_key* -key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region) -{ - struct key_entry_key* newk; - newk = regional_alloc_init(region, kkey, sizeof(*kkey)); - if(!newk) - return NULL; - newk->name = regional_alloc_init(region, kkey->name, kkey->namelen); - if(!newk->name) - return NULL; - newk->entry.key = newk; - if(newk->entry.data) { - /* copy data element */ - struct key_entry_data *d = (struct key_entry_data*) - kkey->entry.data; - struct key_entry_data *newd; - newd = regional_alloc_init(region, d, sizeof(*d)); - if(!newd) - return NULL; - /* copy rrset */ - if(d->rrset_data) { - newd->rrset_data = regional_alloc_init(region, - d->rrset_data, - packed_rrset_sizeof(d->rrset_data)); - if(!newd->rrset_data) - return NULL; - packed_rrset_ptr_fixup(newd->rrset_data); - } - if(d->reason) { - newd->reason = regional_strdup(region, d->reason); - if(!newd->reason) - return NULL; - } - if(d->algo) { - newd->algo = (uint8_t*)regional_strdup(region, - (char*)d->algo); - if(!newd->algo) - return NULL; - } - newk->entry.data = newd; - } - return newk; -} - -struct key_entry_key* -key_entry_copy(struct key_entry_key* kkey, int copy_reason) -{ - struct key_entry_key* newk; - if(!kkey) - return NULL; - newk = memdup(kkey, sizeof(*kkey)); - if(!newk) - return NULL; - newk->name = memdup(kkey->name, kkey->namelen); - if(!newk->name) { - free(newk); - return NULL; - } - lock_rw_init(&newk->entry.lock); - newk->entry.key = newk; - if(newk->entry.data) { - /* copy data element */ - struct key_entry_data *d = (struct key_entry_data*) - kkey->entry.data; - struct key_entry_data *newd; - newd = memdup(d, sizeof(*d)); - if(!newd) { - free(newk->name); - free(newk); - return NULL; - } - /* copy rrset */ - if(d->rrset_data) { - newd->rrset_data = memdup(d->rrset_data, - packed_rrset_sizeof(d->rrset_data)); - if(!newd->rrset_data) { - free(newd); - free(newk->name); - free(newk); - return NULL; - } - packed_rrset_ptr_fixup(newd->rrset_data); - } - if(copy_reason && d->reason && *d->reason != 0) { - newd->reason = strdup(d->reason); - if(!newd->reason) { - free(newd->rrset_data); - free(newd); - free(newk->name); - free(newk); - return NULL; - } - } else { - newd->reason = NULL; - } - if(d->algo) { - newd->algo = (uint8_t*)strdup((char*)d->algo); - if(!newd->algo) { - free(newd->rrset_data); - free(newd->reason); - free(newd); - free(newk->name); - free(newk); - return NULL; - } - } - newk->entry.data = newd; - } - return newk; -} - -int -key_entry_isnull(struct key_entry_key* kkey) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - return (!d->isbad && d->rrset_data == NULL); -} - -int -key_entry_isgood(struct key_entry_key* kkey) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - return (!d->isbad && d->rrset_data != NULL); -} - -int -key_entry_isbad(struct key_entry_key* kkey) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - return (int)(d->isbad); -} - -char* -key_entry_get_reason(struct key_entry_key* kkey) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - return d->reason; -} - -sldns_ede_code -key_entry_get_reason_bogus(struct key_entry_key* kkey) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - return d->reason_bogus; - -} - -/** setup key entry in region */ -static int -key_entry_setup(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, - struct key_entry_key** k, struct key_entry_data** d) -{ - *k = regional_alloc(region, sizeof(**k)); - if(!*k) - return 0; - memset(*k, 0, sizeof(**k)); - (*k)->entry.key = *k; - (*k)->name = regional_alloc_init(region, name, namelen); - if(!(*k)->name) - return 0; - (*k)->namelen = namelen; - (*k)->key_class = dclass; - *d = regional_alloc(region, sizeof(**d)); - if(!*d) - return 0; - (*k)->entry.data = *d; - return 1; -} - -struct key_entry_key* -key_entry_create_null(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, - sldns_ede_code reason_bogus, const char* reason, - time_t now) -{ - struct key_entry_key* k; - struct key_entry_data* d; - if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) - return NULL; - d->ttl = now + ttl; - d->isbad = 0; - d->reason = (!reason || *reason == 0) - ?NULL :(char*)regional_strdup(region, reason); - /* On allocation error we don't store the reason string */ - d->reason_bogus = reason_bogus; - d->rrset_type = LDNS_RR_TYPE_DNSKEY; - d->rrset_data = NULL; - d->algo = NULL; - return k; -} - -struct key_entry_key* -key_entry_create_rrset(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, - struct ub_packed_rrset_key* rrset, uint8_t* sigalg, - sldns_ede_code reason_bogus, const char* reason, - time_t now) -{ - struct key_entry_key* k; - struct key_entry_data* d; - struct packed_rrset_data* rd = (struct packed_rrset_data*) - rrset->entry.data; - if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) - return NULL; - d->ttl = rd->ttl + now; - d->isbad = 0; - d->reason = (!reason || *reason == 0) - ?NULL :(char*)regional_strdup(region, reason); - /* On allocation error we don't store the reason string */ - d->reason_bogus = reason_bogus; - d->rrset_type = ntohs(rrset->rk.type); - d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, - rd, packed_rrset_sizeof(rd)); - if(!d->rrset_data) - return NULL; - if(sigalg) { - d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); - if(!d->algo) - return NULL; - } else d->algo = NULL; - packed_rrset_ptr_fixup(d->rrset_data); - return k; -} - -struct key_entry_key* -key_entry_create_bad(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, - sldns_ede_code reason_bogus, const char* reason, - time_t now) -{ - struct key_entry_key* k; - struct key_entry_data* d; - if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) - return NULL; - d->ttl = now + ttl; - d->isbad = 1; - d->reason = (!reason || *reason == 0) - ?NULL :(char*)regional_strdup(region, reason); - /* On allocation error we don't store the reason string */ - d->reason_bogus = reason_bogus; - d->rrset_type = LDNS_RR_TYPE_DNSKEY; - d->rrset_data = NULL; - d->algo = NULL; - return k; -} - -struct ub_packed_rrset_key* -key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) -{ - struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; - struct ub_packed_rrset_key* rrk; - struct packed_rrset_data* rrd; - if(!d || !d->rrset_data) - return NULL; - rrk = regional_alloc(region, sizeof(*rrk)); - if(!rrk) - return NULL; - memset(rrk, 0, sizeof(*rrk)); - rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); - if(!rrk->rk.dname) - return NULL; - rrk->rk.dname_len = kkey->namelen; - rrk->rk.type = htons(d->rrset_type); - rrk->rk.rrset_class = htons(kkey->key_class); - rrk->entry.key = rrk; - rrd = regional_alloc_init(region, d->rrset_data, - packed_rrset_sizeof(d->rrset_data)); - if(!rrd) - return NULL; - rrk->entry.data = rrd; - packed_rrset_ptr_fixup(rrd); - return rrk; -} - -/** Get size of key in keyset */ -static size_t -dnskey_get_keysize(struct packed_rrset_data* data, size_t idx) -{ - unsigned char* pk; - unsigned int pklen = 0; - int algo; - if(data->rr_len[idx] < 2+5) - return 0; - algo = (int)data->rr_data[idx][2+3]; - pk = (unsigned char*)data->rr_data[idx]+2+4; - pklen = (unsigned)data->rr_len[idx]-2-4; - return sldns_rr_dnskey_key_size_raw(pk, pklen, algo); -} - -/** get dnskey flags from data */ -static uint16_t -kd_get_flags(struct packed_rrset_data* data, size_t idx) -{ - uint16_t f; - if(data->rr_len[idx] < 2+2) - return 0; - memmove(&f, data->rr_data[idx]+2, 2); - f = ntohs(f); - return f; -} - -size_t -key_entry_keysize(struct key_entry_key* kkey) -{ - struct packed_rrset_data* d; - /* compute size of smallest ZSK key in the rrset */ - size_t i; - size_t bits = 0; - if(!key_entry_isgood(kkey)) - return 0; - d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; - for(i=0; icount; i++) { - if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) - continue; - if(i==0 || dnskey_get_keysize(d, i) < bits) - bits = dnskey_get_keysize(d, i); - } - return bits; -} diff --git a/crates/libunbound-sys/unbound/validator/val_kentry.h b/crates/libunbound-sys/unbound/validator/val_kentry.h deleted file mode 100644 index ca9f0dab..00000000 --- a/crates/libunbound-sys/unbound/validator/val_kentry.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * validator/val_kentry.h - validator key entry definition. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains functions for dealing with validator key entries. - */ - -#ifndef VALIDATOR_VAL_KENTRY_H -#define VALIDATOR_VAL_KENTRY_H -struct packed_rrset_data; -struct regional; -struct ub_packed_rrset_key; -#include "util/storage/lruhash.h" -#include "sldns/rrdef.h" - -/** - * A key entry for the validator. - * This may or may not be a trusted key. - * This is what is stored in the key cache. - * This is the key part for the cache; the key entry key. - */ -struct key_entry_key { - /** lru hash entry */ - struct lruhash_entry entry; - /** name of the key */ - uint8_t* name; - /** length of name */ - size_t namelen; - /** class of the key, host byteorder */ - uint16_t key_class; -}; - -/** - * Key entry for the validator. - * Contains key status. - * This is the data part for the cache, the key entry data. - * - * Can be in three basic states: - * isbad=0: good key - * isbad=1: bad key - * isbad=0 && rrset=0: insecure space. - */ -struct key_entry_data { - /** the TTL of this entry (absolute time) */ - time_t ttl; - /** the key rrdata. can be NULL to signal keyless name. */ - struct packed_rrset_data* rrset_data; - /** not NULL sometimes to give reason why bogus */ - char* reason; - /** not NULL to give reason why bogus */ - sldns_ede_code reason_bogus; - /** list of algorithms signalled, ends with 0, or NULL */ - uint8_t* algo; - /** DNS RR type of the rrset data (host order) */ - uint16_t rrset_type; - /** if the key is bad: Bogus or malformed */ - uint8_t isbad; -}; - -/** function for lruhash operation */ -size_t key_entry_sizefunc(void* key, void* data); - -/** function for lruhash operation */ -int key_entry_compfunc(void* k1, void* k2); - -/** function for lruhash operation */ -void key_entry_delkeyfunc(void* key, void* userarg); - -/** function for lruhash operation */ -void key_entry_deldatafunc(void* data, void* userarg); - -/** calculate hash for key entry - * @param kk: key entry. The lruhash entry.hash value is filled in. - */ -void key_entry_hash(struct key_entry_key* kk); - -/** - * Copy a key entry, to be region-allocated. - * @param kkey: the key entry key (and data pointer) to copy. - * @param region: where to allocate it - * @return newly region-allocated entry or NULL on a failure to allocate. - */ -struct key_entry_key* key_entry_copy_toregion(struct key_entry_key* kkey, - struct regional* region); - -/** - * Copy a key entry, malloced. - * @param kkey: the key entry key (and data pointer) to copy. - * @param copy_reason: if the reason string needs to be copied (allocated). - * @return newly allocated entry or NULL on a failure to allocate memory. - */ -struct key_entry_key* key_entry_copy(struct key_entry_key* kkey, - int copy_reason); - -/** - * See if this is a null entry. Does not do locking. - * @param kkey: must have data pointer set correctly - * @return true if it is a NULL rrset entry. - */ -int key_entry_isnull(struct key_entry_key* kkey); - -/** - * See if this entry is good. Does not do locking. - * @param kkey: must have data pointer set correctly - * @return true if it is good. - */ -int key_entry_isgood(struct key_entry_key* kkey); - -/** - * See if this entry is bad. Does not do locking. - * @param kkey: must have data pointer set correctly - * @return true if it is bad. - */ -int key_entry_isbad(struct key_entry_key* kkey); - -/** - * Get reason why a key is bad. - * @param kkey: bad key - * @return pointer to string. - * String is part of key entry and is deleted with it. - */ -char* key_entry_get_reason(struct key_entry_key* kkey); - -/** - * Get the EDE (RFC8914) code why a key is bad. Can return LDNS_EDE_NONE. - * @param kkey: bad key - * @return the ede code. - */ -sldns_ede_code key_entry_get_reason_bogus(struct key_entry_key* kkey); - -/** - * Create a null entry, in the given region. - * @param region: where to allocate - * @param name: the key name - * @param namelen: length of name - * @param dclass: class of key entry. (host order); - * @param ttl: what ttl should the key have. relative. - * @param reason_bogus: accompanying EDE code. - * @param reason: accompanying NULL-terminated EDE string (or NULL). - * @param now: current time (added to ttl). - * @return new key entry or NULL on alloc failure - */ -struct key_entry_key* key_entry_create_null(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, - sldns_ede_code reason_bogus, const char* reason, - time_t now); - -/** - * Create a key entry from an rrset, in the given region. - * @param region: where to allocate. - * @param name: the key name - * @param namelen: length of name - * @param dclass: class of key entry. (host order); - * @param rrset: data for key entry. This is copied to the region. - * @param sigalg: signalled algorithm list (or NULL). - * @param reason_bogus: accompanying EDE code (usually LDNS_EDE_NONE). - * @param reason: accompanying NULL-terminated EDE string (or NULL). - * @param now: current time (added to ttl of rrset) - * @return new key entry or NULL on alloc failure - */ -struct key_entry_key* key_entry_create_rrset(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, - struct ub_packed_rrset_key* rrset, uint8_t* sigalg, - sldns_ede_code reason_bogus, const char* reason, - time_t now); - -/** - * Create a bad entry, in the given region. - * @param region: where to allocate - * @param name: the key name - * @param namelen: length of name - * @param dclass: class of key entry. (host order); - * @param ttl: what ttl should the key have. relative. - * @param reason_bogus: accompanying EDE code. - * @param reason: accompanying NULL-terminated EDE string (or NULL). - * @param now: current time (added to ttl). - * @return new key entry or NULL on alloc failure - */ -struct key_entry_key* key_entry_create_bad(struct regional* region, - uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, - sldns_ede_code reason_bogus, const char* reason, - time_t now); - -/** - * Obtain rrset from a key entry, allocated in region. - * @param kkey: key entry to convert to a rrset. - * @param region: where to allocate rrset - * @return rrset copy; if no rrset or alloc error returns NULL. - */ -struct ub_packed_rrset_key* key_entry_get_rrset(struct key_entry_key* kkey, - struct regional* region); - -/** - * Get keysize of the keyentry. - * @param kkey: key, must be a good key, with contents. - * @return size in bits of the key. - */ -size_t key_entry_keysize(struct key_entry_key* kkey); - -#endif /* VALIDATOR_VAL_KENTRY_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_neg.c b/crates/libunbound-sys/unbound/validator/val_neg.c deleted file mode 100644 index 52bc6838..00000000 --- a/crates/libunbound-sys/unbound/validator/val_neg.c +++ /dev/null @@ -1,1554 +0,0 @@ -/* - * validator/val_neg.c - validator aggressive negative caching functions. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with aggressive negative caching. - * This creates new denials of existence, and proofs for absence of types - * from cached NSEC records. - */ -#include "config.h" -#ifdef HAVE_OPENSSL_SSL_H -#include -#define NSEC3_SHA_LEN SHA_DIGEST_LENGTH -#else -#define NSEC3_SHA_LEN 20 -#endif -#include "validator/val_neg.h" -#include "validator/val_nsec.h" -#include "validator/val_nsec3.h" -#include "validator/val_utils.h" -#include "util/data/dname.h" -#include "util/data/msgreply.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/config_file.h" -#include "services/cache/rrset.h" -#include "services/cache/dns.h" -#include "sldns/rrdef.h" -#include "sldns/sbuffer.h" - -int val_neg_data_compare(const void* a, const void* b) -{ - struct val_neg_data* x = (struct val_neg_data*)a; - struct val_neg_data* y = (struct val_neg_data*)b; - int m; - return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); -} - -int val_neg_zone_compare(const void* a, const void* b) -{ - struct val_neg_zone* x = (struct val_neg_zone*)a; - struct val_neg_zone* y = (struct val_neg_zone*)b; - int m; - if(x->dclass != y->dclass) { - if(x->dclass < y->dclass) - return -1; - return 1; - } - return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); -} - -struct val_neg_cache* val_neg_create(struct config_file* cfg, size_t maxiter) -{ - struct val_neg_cache* neg = (struct val_neg_cache*)calloc(1, - sizeof(*neg)); - if(!neg) { - log_err("Could not create neg cache: out of memory"); - return NULL; - } - neg->nsec3_max_iter = maxiter; - neg->max = 1024*1024; /* 1 M is thousands of entries */ - if(cfg) neg->max = cfg->neg_cache_size; - rbtree_init(&neg->tree, &val_neg_zone_compare); - lock_basic_init(&neg->lock); - lock_protect(&neg->lock, neg, sizeof(*neg)); - return neg; -} - -size_t val_neg_get_mem(struct val_neg_cache* neg) -{ - size_t result; - lock_basic_lock(&neg->lock); - result = sizeof(*neg) + neg->use; - lock_basic_unlock(&neg->lock); - return result; -} - -/** clear datas on cache deletion */ -static void -neg_clear_datas(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct val_neg_data* d = (struct val_neg_data*)n; - free(d->name); - free(d); -} - -/** clear zones on cache deletion */ -static void -neg_clear_zones(rbnode_type* n, void* ATTR_UNUSED(arg)) -{ - struct val_neg_zone* z = (struct val_neg_zone*)n; - /* delete all the rrset entries in the tree */ - traverse_postorder(&z->tree, &neg_clear_datas, NULL); - free(z->nsec3_salt); - free(z->name); - free(z); -} - -void neg_cache_delete(struct val_neg_cache* neg) -{ - if(!neg) return; - lock_basic_destroy(&neg->lock); - /* delete all the zones in the tree */ - traverse_postorder(&neg->tree, &neg_clear_zones, NULL); - free(neg); -} - -/** - * Put data element at the front of the LRU list. - * @param neg: negative cache with LRU start and end. - * @param data: this data is fronted. - */ -static void neg_lru_front(struct val_neg_cache* neg, - struct val_neg_data* data) -{ - data->prev = NULL; - data->next = neg->first; - if(!neg->first) - neg->last = data; - else neg->first->prev = data; - neg->first = data; -} - -/** - * Remove data element from LRU list. - * @param neg: negative cache with LRU start and end. - * @param data: this data is removed from the list. - */ -static void neg_lru_remove(struct val_neg_cache* neg, - struct val_neg_data* data) -{ - if(data->prev) - data->prev->next = data->next; - else neg->first = data->next; - if(data->next) - data->next->prev = data->prev; - else neg->last = data->prev; -} - -/** - * Touch LRU for data element, put it at the start of the LRU list. - * @param neg: negative cache with LRU start and end. - * @param data: this data is used. - */ -static void neg_lru_touch(struct val_neg_cache* neg, - struct val_neg_data* data) -{ - if(data == neg->first) - return; /* nothing to do */ - /* remove from current lru position */ - neg_lru_remove(neg, data); - /* add at front */ - neg_lru_front(neg, data); -} - -/** - * Delete a zone element from the negative cache. - * May delete other zone elements to keep tree coherent, or - * only mark the element as 'not in use'. - * @param neg: negative cache. - * @param z: zone element to delete. - */ -static void neg_delete_zone(struct val_neg_cache* neg, struct val_neg_zone* z) -{ - struct val_neg_zone* p, *np; - if(!z) return; - log_assert(z->in_use); - log_assert(z->count > 0); - z->in_use = 0; - - /* go up the tree and reduce counts */ - p = z; - while(p) { - log_assert(p->count > 0); - p->count --; - p = p->parent; - } - - /* remove zones with zero count */ - p = z; - while(p && p->count == 0) { - np = p->parent; - (void)rbtree_delete(&neg->tree, &p->node); - neg->use -= p->len + sizeof(*p); - free(p->nsec3_salt); - free(p->name); - free(p); - p = np; - } -} - -void neg_delete_data(struct val_neg_cache* neg, struct val_neg_data* el) -{ - struct val_neg_zone* z; - struct val_neg_data* p, *np; - if(!el) return; - z = el->zone; - log_assert(el->in_use); - log_assert(el->count > 0); - el->in_use = 0; - - /* remove it from the lru list */ - neg_lru_remove(neg, el); - log_assert(neg->first != el && neg->last != el); - - /* go up the tree and reduce counts */ - p = el; - while(p) { - log_assert(p->count > 0); - p->count --; - p = p->parent; - } - - /* delete 0 count items from tree */ - p = el; - while(p && p->count == 0) { - np = p->parent; - (void)rbtree_delete(&z->tree, &p->node); - neg->use -= p->len + sizeof(*p); - free(p->name); - free(p); - p = np; - } - - /* check if the zone is now unused */ - if(z->tree.count == 0) { - neg_delete_zone(neg, z); - } -} - -/** - * Create more space in negative cache - * The oldest elements are deleted until enough space is present. - * Empty zones are deleted. - * @param neg: negative cache. - * @param need: how many bytes are needed. - */ -static void neg_make_space(struct val_neg_cache* neg, size_t need) -{ - /* delete elements until enough space or its empty */ - while(neg->last && neg->max < neg->use + need) { - neg_delete_data(neg, neg->last); - } -} - -struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg, - uint8_t* nm, size_t len, uint16_t dclass) -{ - struct val_neg_zone lookfor; - struct val_neg_zone* result; - lookfor.node.key = &lookfor; - lookfor.name = nm; - lookfor.len = len; - lookfor.labs = dname_count_labels(lookfor.name); - lookfor.dclass = dclass; - - result = (struct val_neg_zone*) - rbtree_search(&neg->tree, lookfor.node.key); - return result; -} - -/** - * Find the given data - * @param zone: negative zone - * @param nm: what to look for. - * @param len: length of nm - * @param labs: labels in nm - * @return data or NULL if not found. - */ -static struct val_neg_data* neg_find_data(struct val_neg_zone* zone, - uint8_t* nm, size_t len, int labs) -{ - struct val_neg_data lookfor; - struct val_neg_data* result; - lookfor.node.key = &lookfor; - lookfor.name = nm; - lookfor.len = len; - lookfor.labs = labs; - - result = (struct val_neg_data*) - rbtree_search(&zone->tree, lookfor.node.key); - return result; -} - -/** - * Calculate space needed for the data and all its parents - * @param rep: NSEC entries. - * @return size. - */ -static size_t calc_data_need(struct reply_info* rep) -{ - uint8_t* d; - size_t i, len, res = 0; - - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC) { - d = rep->rrsets[i]->rk.dname; - len = rep->rrsets[i]->rk.dname_len; - res = sizeof(struct val_neg_data) + len; - while(!dname_is_root(d)) { - log_assert(len > 1); /* not root label */ - dname_remove_label(&d, &len); - res += sizeof(struct val_neg_data) + len; - } - } - } - return res; -} - -/** - * Calculate space needed for zone and all its parents - * @param d: name of zone - * @param len: length of name - * @return size. - */ -static size_t calc_zone_need(uint8_t* d, size_t len) -{ - size_t res = sizeof(struct val_neg_zone) + len; - while(!dname_is_root(d)) { - log_assert(len > 1); /* not root label */ - dname_remove_label(&d, &len); - res += sizeof(struct val_neg_zone) + len; - } - return res; -} - -/** - * Find closest existing parent zone of the given name. - * @param neg: negative cache. - * @param nm: name to look for - * @param nm_len: length of nm - * @param labs: labelcount of nm. - * @param qclass: class. - * @return the zone or NULL if none found. - */ -static struct val_neg_zone* neg_closest_zone_parent(struct val_neg_cache* neg, - uint8_t* nm, size_t nm_len, int labs, uint16_t qclass) -{ - struct val_neg_zone key; - struct val_neg_zone* result; - rbnode_type* res = NULL; - key.node.key = &key; - key.name = nm; - key.len = nm_len; - key.labs = labs; - key.dclass = qclass; - if(rbtree_find_less_equal(&neg->tree, &key, &res)) { - /* exact match */ - result = (struct val_neg_zone*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct val_neg_zone*)res; - if(!result || result->dclass != qclass) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->labs, key.name, - key.labs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->labs <= m) - break; - result = result->parent; - } - } - return result; -} - -/** - * Find closest existing parent data for the given name. - * @param zone: to look in. - * @param nm: name to look for - * @param nm_len: length of nm - * @param labs: labelcount of nm. - * @return the data or NULL if none found. - */ -static struct val_neg_data* neg_closest_data_parent( - struct val_neg_zone* zone, uint8_t* nm, size_t nm_len, int labs) -{ - struct val_neg_data key; - struct val_neg_data* result; - rbnode_type* res = NULL; - key.node.key = &key; - key.name = nm; - key.len = nm_len; - key.labs = labs; - if(rbtree_find_less_equal(&zone->tree, &key, &res)) { - /* exact match */ - result = (struct val_neg_data*)res; - } else { - /* smaller element (or no element) */ - int m; - result = (struct val_neg_data*)res; - if(!result) - return NULL; - /* count number of labels matched */ - (void)dname_lab_cmp(result->name, result->labs, key.name, - key.labs, &m); - while(result) { /* go up until qname is subdomain of stub */ - if(result->labs <= m) - break; - result = result->parent; - } - } - return result; -} - -/** - * Create a single zone node - * @param nm: name for zone (copied) - * @param nm_len: length of name - * @param labs: labels in name. - * @param dclass: class of zone, host order. - * @return new zone or NULL on failure - */ -static struct val_neg_zone* neg_setup_zone_node( - uint8_t* nm, size_t nm_len, int labs, uint16_t dclass) -{ - struct val_neg_zone* zone = - (struct val_neg_zone*)calloc(1, sizeof(*zone)); - if(!zone) { - return NULL; - } - zone->node.key = zone; - zone->name = memdup(nm, nm_len); - if(!zone->name) { - free(zone); - return NULL; - } - zone->len = nm_len; - zone->labs = labs; - zone->dclass = dclass; - - rbtree_init(&zone->tree, &val_neg_data_compare); - return zone; -} - -/** - * Create a linked list of parent zones, starting at longname ending on - * the parent (can be NULL, creates to the root). - * @param nm: name for lowest in chain - * @param nm_len: length of name - * @param labs: labels in name. - * @param dclass: class of zone. - * @param parent: NULL for to root, else so it fits under here. - * @return zone; a chain of zones and their parents up to the parent. - * or NULL on malloc failure - */ -static struct val_neg_zone* neg_zone_chain( - uint8_t* nm, size_t nm_len, int labs, uint16_t dclass, - struct val_neg_zone* parent) -{ - int i; - int tolabs = parent?parent->labs:0; - struct val_neg_zone* zone, *prev = NULL, *first = NULL; - - /* create the new subtree, i is labelcount of current creation */ - /* this creates a 'first' to z->parent=NULL list of zones */ - for(i=labs; i!=tolabs; i--) { - /* create new item */ - zone = neg_setup_zone_node(nm, nm_len, i, dclass); - if(!zone) { - /* need to delete other allocations in this routine!*/ - struct val_neg_zone* p=first, *np; - while(p) { - np = p->parent; - free(p->name); - free(p); - p = np; - } - return NULL; - } - if(i == labs) { - first = zone; - } else { - prev->parent = zone; - } - /* prepare for next name */ - prev = zone; - dname_remove_label(&nm, &nm_len); - } - return first; -} - -void val_neg_zone_take_inuse(struct val_neg_zone* zone) -{ - if(!zone->in_use) { - struct val_neg_zone* p; - zone->in_use = 1; - /* increase usage count of all parents */ - for(p=zone; p; p = p->parent) { - p->count++; - } - } -} - -struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg, - uint8_t* nm, size_t nm_len, uint16_t dclass) -{ - struct val_neg_zone* zone; - struct val_neg_zone* parent; - struct val_neg_zone* p, *np; - int labs = dname_count_labels(nm); - - /* find closest enclosing parent zone that (still) exists */ - parent = neg_closest_zone_parent(neg, nm, nm_len, labs, dclass); - if(parent && query_dname_compare(parent->name, nm) == 0) - return parent; /* already exists, weird */ - /* if parent exists, it is in use */ - log_assert(!parent || parent->count > 0); - zone = neg_zone_chain(nm, nm_len, labs, dclass, parent); - if(!zone) { - return NULL; - } - - /* insert the list of zones into the tree */ - p = zone; - while(p) { - np = p->parent; - /* mem use */ - neg->use += sizeof(struct val_neg_zone) + p->len; - /* insert in tree */ - (void)rbtree_insert(&neg->tree, &p->node); - /* last one needs proper parent pointer */ - if(np == NULL) - p->parent = parent; - p = np; - } - return zone; -} - -/** find zone name of message, returns the SOA record */ -static struct ub_packed_rrset_key* reply_find_soa(struct reply_info* rep) -{ - size_t i; - for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA) - return rep->rrsets[i]; - } - return NULL; -} - -/** see if the reply has NSEC records worthy of caching */ -static int reply_has_nsec(struct reply_info* rep) -{ - size_t i; - struct packed_rrset_data* d; - if(rep->security != sec_status_secure) - return 0; - for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC) { - d = (struct packed_rrset_data*)rep->rrsets[i]-> - entry.data; - if(d->security == sec_status_secure) - return 1; - } - } - return 0; -} - - -/** - * Create single node of data element. - * @param nm: name (copied) - * @param nm_len: length of name - * @param labs: labels in name. - * @return element with name nm, or NULL malloc failure. - */ -static struct val_neg_data* neg_setup_data_node( - uint8_t* nm, size_t nm_len, int labs) -{ - struct val_neg_data* el; - el = (struct val_neg_data*)calloc(1, sizeof(*el)); - if(!el) { - return NULL; - } - el->node.key = el; - el->name = memdup(nm, nm_len); - if(!el->name) { - free(el); - return NULL; - } - el->len = nm_len; - el->labs = labs; - return el; -} - -/** - * Create chain of data element and parents - * @param nm: name - * @param nm_len: length of name - * @param labs: labels in name. - * @param parent: up to where to make, if NULL up to root label. - * @return lowest element with name nm, or NULL malloc failure. - */ -static struct val_neg_data* neg_data_chain( - uint8_t* nm, size_t nm_len, int labs, struct val_neg_data* parent) -{ - int i; - int tolabs = parent?parent->labs:0; - struct val_neg_data* el, *first = NULL, *prev = NULL; - - /* create the new subtree, i is labelcount of current creation */ - /* this creates a 'first' to z->parent=NULL list of zones */ - for(i=labs; i!=tolabs; i--) { - /* create new item */ - el = neg_setup_data_node(nm, nm_len, i); - if(!el) { - /* need to delete other allocations in this routine!*/ - struct val_neg_data* p = first, *np; - while(p) { - np = p->parent; - free(p->name); - free(p); - p = np; - } - return NULL; - } - if(i == labs) { - first = el; - } else { - prev->parent = el; - } - - /* prepare for next name */ - prev = el; - dname_remove_label(&nm, &nm_len); - } - return first; -} - -/** - * Remove NSEC records between start and end points. - * By walking the tree, the tree is sorted canonically. - * @param neg: negative cache. - * @param zone: the zone - * @param el: element to start walking at. - * @param nsec: the nsec record with the end point - */ -static void wipeout(struct val_neg_cache* neg, struct val_neg_zone* zone, - struct val_neg_data* el, struct ub_packed_rrset_key* nsec) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> - entry.data; - uint8_t* end; - size_t end_len; - int end_labs, m; - rbnode_type* walk, *next; - struct val_neg_data* cur; - uint8_t buf[257]; - /* get endpoint */ - if(!d || d->count == 0 || d->rr_len[0] < 2+1) - return; - if(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC) { - end = d->rr_data[0]+2; - end_len = dname_valid(end, d->rr_len[0]-2); - end_labs = dname_count_labels(end); - } else { - /* NSEC3 */ - if(!nsec3_get_nextowner_b32(nsec, 0, buf, sizeof(buf))) - return; - end = buf; - end_labs = dname_count_size_labels(end, &end_len); - } - - /* sanity check, both owner and end must be below the zone apex */ - if(!dname_subdomain_c(el->name, zone->name) || - !dname_subdomain_c(end, zone->name)) - return; - - /* detect end of zone NSEC ; wipe until the end of zone */ - if(query_dname_compare(end, zone->name) == 0) { - end = NULL; - } - - walk = rbtree_next(&el->node); - while(walk && walk != RBTREE_NULL) { - cur = (struct val_neg_data*)walk; - /* sanity check: must be larger than start */ - if(dname_canon_lab_cmp(cur->name, cur->labs, - el->name, el->labs, &m) <= 0) { - /* r == 0 skip original record. */ - /* r < 0 too small! */ - walk = rbtree_next(walk); - continue; - } - /* stop at endpoint, also data at empty nonterminals must be - * removed (no NSECs there) so everything between - * start and end */ - if(end && dname_canon_lab_cmp(cur->name, cur->labs, - end, end_labs, &m) >= 0) { - break; - } - /* this element has to be deleted, but we cannot do it - * now, because we are walking the tree still ... */ - /* get the next element: */ - next = rbtree_next(walk); - /* now delete the original element, this may trigger - * rbtree rebalances, but really, the next element is - * the one we need. - * But it may trigger delete of other data and the - * entire zone. However, if that happens, this is done - * by deleting the *parents* of the element for deletion, - * and maybe also the entire zone if it is empty. - * But parents are smaller in canonical compare, thus, - * if a larger element exists, then it is not a parent, - * it cannot get deleted, the zone cannot get empty. - * If the next==NULL, then zone can be empty. */ - if(cur->in_use) - neg_delete_data(neg, cur); - walk = next; - } -} - -void neg_insert_data(struct val_neg_cache* neg, - struct val_neg_zone* zone, struct ub_packed_rrset_key* nsec) -{ - struct packed_rrset_data* d; - struct val_neg_data* parent; - struct val_neg_data* el; - uint8_t* nm = nsec->rk.dname; - size_t nm_len = nsec->rk.dname_len; - int labs = dname_count_labels(nsec->rk.dname); - - d = (struct packed_rrset_data*)nsec->entry.data; - if( !(d->security == sec_status_secure || - (d->security == sec_status_unchecked && d->rrsig_count > 0))) - return; - log_nametypeclass(VERB_ALGO, "negcache rr", - nsec->rk.dname, ntohs(nsec->rk.type), - ntohs(nsec->rk.rrset_class)); - - /* find closest enclosing parent data that (still) exists */ - parent = neg_closest_data_parent(zone, nm, nm_len, labs); - if(parent && query_dname_compare(parent->name, nm) == 0) { - /* perfect match already exists */ - log_assert(parent->count > 0); - el = parent; - } else { - struct val_neg_data* p, *np; - - /* create subtree for perfect match */ - /* if parent exists, it is in use */ - log_assert(!parent || parent->count > 0); - - el = neg_data_chain(nm, nm_len, labs, parent); - if(!el) { - log_err("out of memory inserting NSEC negative cache"); - return; - } - el->in_use = 0; /* set on below */ - - /* insert the list of zones into the tree */ - p = el; - while(p) { - np = p->parent; - /* mem use */ - neg->use += sizeof(struct val_neg_data) + p->len; - /* insert in tree */ - p->zone = zone; - (void)rbtree_insert(&zone->tree, &p->node); - /* last one needs proper parent pointer */ - if(np == NULL) - p->parent = parent; - p = np; - } - } - - if(!el->in_use) { - struct val_neg_data* p; - - el->in_use = 1; - /* increase usage count of all parents */ - for(p=el; p; p = p->parent) { - p->count++; - } - - neg_lru_front(neg, el); - } else { - /* in use, bring to front, lru */ - neg_lru_touch(neg, el); - } - - /* if nsec3 store last used parameters */ - if(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC3) { - int h; - uint8_t* s; - size_t slen, it; - if(nsec3_get_params(nsec, 0, &h, &it, &s, &slen) && - it <= neg->nsec3_max_iter && - (h != zone->nsec3_hash || it != zone->nsec3_iter || - slen != zone->nsec3_saltlen || - memcmp(zone->nsec3_salt, s, slen) != 0)) { - - if(slen > 0) { - uint8_t* sa = memdup(s, slen); - if(sa) { - free(zone->nsec3_salt); - zone->nsec3_salt = sa; - zone->nsec3_saltlen = slen; - zone->nsec3_iter = it; - zone->nsec3_hash = h; - } - } else { - free(zone->nsec3_salt); - zone->nsec3_salt = NULL; - zone->nsec3_saltlen = 0; - zone->nsec3_iter = it; - zone->nsec3_hash = h; - } - } - } - - /* wipe out the cache items between NSEC start and end */ - wipeout(neg, zone, el, nsec); -} - -/** see if the reply has signed NSEC records and return the signer */ -static uint8_t* reply_nsec_signer(struct reply_info* rep, size_t* signer_len, - uint16_t* dclass) -{ - size_t i; - struct packed_rrset_data* d; - uint8_t* s; - for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC || - ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC3) { - d = (struct packed_rrset_data*)rep->rrsets[i]-> - entry.data; - /* return first signer name of first NSEC */ - if(d->rrsig_count != 0) { - val_find_rrset_signer(rep->rrsets[i], - &s, signer_len); - if(s && *signer_len) { - *dclass = ntohs(rep->rrsets[i]-> - rk.rrset_class); - return s; - } - } - } - } - return 0; -} - -void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep) -{ - size_t i, need; - struct ub_packed_rrset_key* soa; - uint8_t* dname = NULL; - size_t dname_len; - uint16_t rrset_class; - struct val_neg_zone* zone; - /* see if secure nsecs inside */ - if(!reply_has_nsec(rep)) - return; - /* find the zone name in message */ - if((soa = reply_find_soa(rep))) { - dname = soa->rk.dname; - dname_len = soa->rk.dname_len; - rrset_class = ntohs(soa->rk.rrset_class); - } - else { - /* No SOA in positive (wildcard) answer. Use signer from the - * validated answer RRsets' signature. */ - if(!(dname = reply_nsec_signer(rep, &dname_len, &rrset_class))) - return; - } - - log_nametypeclass(VERB_ALGO, "negcache insert for zone", - dname, LDNS_RR_TYPE_SOA, rrset_class); - - /* ask for enough space to store all of it */ - need = calc_data_need(rep) + - calc_zone_need(dname, dname_len); - lock_basic_lock(&neg->lock); - neg_make_space(neg, need); - - /* find or create the zone entry */ - zone = neg_find_zone(neg, dname, dname_len, rrset_class); - if(!zone) { - if(!(zone = neg_create_zone(neg, dname, dname_len, - rrset_class))) { - lock_basic_unlock(&neg->lock); - log_err("out of memory adding negative zone"); - return; - } - } - val_neg_zone_take_inuse(zone); - - /* insert the NSECs */ - for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC) - continue; - if(!dname_subdomain_c(rep->rrsets[i]->rk.dname, - zone->name)) continue; - /* insert NSEC into this zone's tree */ - neg_insert_data(neg, zone, rep->rrsets[i]); - } - if(zone->tree.count == 0) { - /* remove empty zone if inserts failed */ - neg_delete_zone(neg, zone); - } - lock_basic_unlock(&neg->lock); -} - -/** - * Lookup closest data record. For NSEC denial. - * @param zone: zone to look in - * @param qname: name to look for. - * @param len: length of name - * @param labs: labels in name - * @param data: data element, exact or smaller or NULL - * @return true if exact match. - */ -static int neg_closest_data(struct val_neg_zone* zone, - uint8_t* qname, size_t len, int labs, struct val_neg_data** data) -{ - struct val_neg_data key; - rbnode_type* r; - key.node.key = &key; - key.name = qname; - key.len = len; - key.labs = labs; - if(rbtree_find_less_equal(&zone->tree, &key, &r)) { - /* exact match */ - *data = (struct val_neg_data*)r; - return 1; - } else { - /* smaller match */ - *data = (struct val_neg_data*)r; - return 0; - } -} - -void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep, - uint8_t* zone_name) -{ - size_t i, need; - uint8_t* signer; - size_t signer_len; - uint16_t dclass; - struct val_neg_zone* zone; - /* no SOA in this message, find RRSIG over NSEC's signer name. - * note the NSEC records are maybe not validated yet */ - signer = reply_nsec_signer(rep, &signer_len, &dclass); - if(!signer) - return; - if(!dname_subdomain_c(signer, zone_name)) { - /* the signer is not in the bailiwick, throw it out */ - return; - } - - log_nametypeclass(VERB_ALGO, "negcache insert referral ", - signer, LDNS_RR_TYPE_NS, dclass); - - /* ask for enough space to store all of it */ - need = calc_data_need(rep) + calc_zone_need(signer, signer_len); - lock_basic_lock(&neg->lock); - neg_make_space(neg, need); - - /* find or create the zone entry */ - zone = neg_find_zone(neg, signer, signer_len, dclass); - if(!zone) { - if(!(zone = neg_create_zone(neg, signer, signer_len, - dclass))) { - lock_basic_unlock(&neg->lock); - log_err("out of memory adding negative zone"); - return; - } - } - val_neg_zone_take_inuse(zone); - - /* insert the NSECs */ - for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ - if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC && - ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC3) - continue; - if(!dname_subdomain_c(rep->rrsets[i]->rk.dname, - zone->name)) continue; - /* insert NSEC into this zone's tree */ - neg_insert_data(neg, zone, rep->rrsets[i]); - } - if(zone->tree.count == 0) { - /* remove empty zone if inserts failed */ - neg_delete_zone(neg, zone); - } - lock_basic_unlock(&neg->lock); -} - -/** - * Check that an NSEC3 rrset does not have a type set. - * None of the nsec3s in a hash-collision are allowed to have the type. - * (since we do not know which one is the nsec3 looked at, flags, ..., we - * ignore the cached item and let it bypass negative caching). - * @param k: the nsec3 rrset to check. - * @param t: type to check - * @return true if no RRs have the type. - */ -static int nsec3_no_type(struct ub_packed_rrset_key* k, uint16_t t) -{ - int count = (int)((struct packed_rrset_data*)k->entry.data)->count; - int i; - for(i=0; ientry.data; - if(d->ttl < now) { - lock_rw_unlock(&k->entry.lock); - return NULL; - } - /* only secure or unchecked records that have signatures. */ - if( ! ( d->security == sec_status_secure || - (d->security == sec_status_unchecked && - d->rrsig_count > 0) ) ) { - lock_rw_unlock(&k->entry.lock); - return NULL; - } - /* check if checktype is absent */ - if(checkbit && ( - (qtype == LDNS_RR_TYPE_NSEC && nsec_has_type(k, checktype)) || - (qtype == LDNS_RR_TYPE_NSEC3 && !nsec3_no_type(k, checktype)) - )) { - lock_rw_unlock(&k->entry.lock); - return NULL; - } - /* looks OK! copy to region and return it */ - r = packed_rrset_copy_region(k, region, now); - /* if it failed, we return the NULL */ - lock_rw_unlock(&k->entry.lock); - return r; -} - -/** - * Get best NSEC record for qname. Might be matching, covering or totally - * useless. - * @param neg_cache: neg cache - * @param qname: to lookup rrset name - * @param qname_len: length of qname. - * @param qclass: class of rrset to lookup, host order - * @param rrset_cache: rrset cache - * @param now: to check ttl against - * @param region: where to alloc result - * @return rrset or NULL - */ -static struct ub_packed_rrset_key* -neg_find_nsec(struct val_neg_cache* neg_cache, uint8_t* qname, size_t qname_len, - uint16_t qclass, struct rrset_cache* rrset_cache, time_t now, - struct regional* region) -{ - int labs; - uint32_t flags; - struct val_neg_zone* zone; - struct val_neg_data* data; - struct ub_packed_rrset_key* nsec; - - labs = dname_count_labels(qname); - lock_basic_lock(&neg_cache->lock); - zone = neg_closest_zone_parent(neg_cache, qname, qname_len, labs, - qclass); - while(zone && !zone->in_use) - zone = zone->parent; - if(!zone) { - lock_basic_unlock(&neg_cache->lock); - return NULL; - } - - /* NSEC only for now */ - if(zone->nsec3_hash) { - lock_basic_unlock(&neg_cache->lock); - return NULL; - } - - /* ignore return value, don't care if it is an exact or smaller match */ - (void)neg_closest_data(zone, qname, qname_len, labs, &data); - if(!data) { - lock_basic_unlock(&neg_cache->lock); - return NULL; - } - - /* ENT nodes are not in use, try the previous node. If the previous node - * is not in use, we don't have an useful NSEC and give up. */ - if(!data->in_use) { - data = (struct val_neg_data*)rbtree_previous((rbnode_type*)data); - if((rbnode_type*)data == RBTREE_NULL || !data->in_use) { - lock_basic_unlock(&neg_cache->lock); - return NULL; - } - } - - flags = 0; - if(query_dname_compare(data->name, zone->name) == 0) - flags = PACKED_RRSET_NSEC_AT_APEX; - - nsec = grab_nsec(rrset_cache, data->name, data->len, LDNS_RR_TYPE_NSEC, - zone->dclass, flags, region, 0, 0, now); - lock_basic_unlock(&neg_cache->lock); - return nsec; -} - -/** find nsec3 closest encloser in neg cache */ -static struct val_neg_data* -neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, - int qlabs, sldns_buffer* buf, uint8_t* hashnc, size_t* nclen) -{ - struct val_neg_data* data; - uint8_t hashce[NSEC3_SHA_LEN]; - uint8_t b32[257]; - size_t celen, b32len; - - *nclen = 0; - while(qlabs > 0) { - /* hash */ - if(!(celen=nsec3_get_hashed(buf, qname, qname_len, - zone->nsec3_hash, zone->nsec3_iter, zone->nsec3_salt, - zone->nsec3_saltlen, hashce, sizeof(hashce)))) - return NULL; - if(!(b32len=nsec3_hash_to_b32(hashce, celen, zone->name, - zone->len, b32, sizeof(b32)))) - return NULL; - - /* lookup (exact match only) */ - data = neg_find_data(zone, b32, b32len, zone->labs+1); - if(data && data->in_use) { - /* found ce match! */ - return data; - } - - *nclen = celen; - memmove(hashnc, hashce, celen); - dname_remove_label(&qname, &qname_len); - qlabs --; - } - return NULL; -} - -/** check nsec3 parameters on nsec3 rrset with current zone values */ -static int -neg_params_ok(struct val_neg_zone* zone, struct ub_packed_rrset_key* rrset) -{ - int h; - uint8_t* s; - size_t slen, it; - if(!nsec3_get_params(rrset, 0, &h, &it, &s, &slen)) - return 0; - return (h == zone->nsec3_hash && it == zone->nsec3_iter && - slen == zone->nsec3_saltlen && - memcmp(zone->nsec3_salt, s, slen) == 0); -} - -/** get next closer for nsec3 proof */ -static struct ub_packed_rrset_key* -neg_nsec3_getnc(struct val_neg_zone* zone, uint8_t* hashnc, size_t nclen, - struct rrset_cache* rrset_cache, struct regional* region, - time_t now, uint8_t* b32, size_t maxb32) -{ - struct ub_packed_rrset_key* nc_rrset; - struct val_neg_data* data; - size_t b32len; - - if(!(b32len=nsec3_hash_to_b32(hashnc, nclen, zone->name, - zone->len, b32, maxb32))) - return NULL; - (void)neg_closest_data(zone, b32, b32len, zone->labs+1, &data); - if(!data && zone->tree.count != 0) { - /* could be before the first entry ; return the last - * entry (possibly the rollover nsec3 at end) */ - data = (struct val_neg_data*)rbtree_last(&zone->tree); - } - while(data && !data->in_use) - data = data->parent; - if(!data) - return NULL; - /* got a data element in tree, grab it */ - nc_rrset = grab_nsec(rrset_cache, data->name, data->len, - LDNS_RR_TYPE_NSEC3, zone->dclass, 0, region, 0, 0, now); - if(!nc_rrset) - return NULL; - if(!neg_params_ok(zone, nc_rrset)) - return NULL; - return nc_rrset; -} - -/** neg cache nsec3 proof procedure*/ -static struct dns_msg* -neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, - int qlabs, sldns_buffer* buf, struct rrset_cache* rrset_cache, - struct regional* region, time_t now, uint8_t* topname) -{ - struct dns_msg* msg; - struct val_neg_data* data; - uint8_t hashnc[NSEC3_SHA_LEN]; - size_t nclen; - struct ub_packed_rrset_key* ce_rrset, *nc_rrset; - struct nsec3_cached_hash c; - uint8_t nc_b32[257]; - - /* for NSEC3 ; determine the closest encloser for which we - * can find an exact match. Remember the hashed lower name, - * since that is the one we need a closest match for. - * If we find a match straight away, then it becomes NODATA. - * Otherwise, NXDOMAIN or if OPTOUT, an insecure delegation. - * Also check that parameters are the same on closest encloser - * and on closest match. - */ - if(!zone->nsec3_hash) - return NULL; /* not nsec3 zone */ - - if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf, - hashnc, &nclen))) { - return NULL; - } - - /* grab the ce rrset */ - ce_rrset = grab_nsec(rrset_cache, data->name, data->len, - LDNS_RR_TYPE_NSEC3, zone->dclass, 0, region, 1, - LDNS_RR_TYPE_DS, now); - if(!ce_rrset) - return NULL; - if(!neg_params_ok(zone, ce_rrset)) - return NULL; - - if(nclen == 0) { - /* exact match, just check the type bits */ - /* need: -SOA, -DS, +NS */ - if(nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_SOA) || - nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_DS) || - !nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_NS)) - return NULL; - if(!(msg = dns_msg_create(qname, qname_len, - LDNS_RR_TYPE_DS, zone->dclass, region, 1))) - return NULL; - /* TTL reduced in grab_nsec */ - if(!dns_msg_authadd(msg, region, ce_rrset, 0)) - return NULL; - return msg; - } - - /* optout is not allowed without knowing the trust-anchor in use, - * otherwise the optout could spoof away that anchor */ - if(!topname) - return NULL; - - /* if there is no exact match, it must be in an optout span - * (an existing DS implies an NSEC3 must exist) */ - nc_rrset = neg_nsec3_getnc(zone, hashnc, nclen, rrset_cache, - region, now, nc_b32, sizeof(nc_b32)); - if(!nc_rrset) - return NULL; - if(!neg_params_ok(zone, nc_rrset)) - return NULL; - if(!nsec3_has_optout(nc_rrset, 0)) - return NULL; - c.hash = hashnc; - c.hash_len = nclen; - c.b32 = nc_b32+1; - c.b32_len = (size_t)nc_b32[0]; - if(nsec3_covers(zone->name, &c, nc_rrset, 0, buf)) { - /* nc_rrset covers the next closer name. - * ce_rrset equals a closer encloser. - * nc_rrset is optout. - * No need to check wildcard for type DS */ - /* capacity=3: ce + nc + soa(if needed) */ - if(!(msg = dns_msg_create(qname, qname_len, - LDNS_RR_TYPE_DS, zone->dclass, region, 3))) - return NULL; - /* now=0 because TTL was reduced in grab_nsec */ - if(!dns_msg_authadd(msg, region, ce_rrset, 0)) - return NULL; - if(!dns_msg_authadd(msg, region, nc_rrset, 0)) - return NULL; - return msg; - } - return NULL; -} - -/** - * Add SOA record for external responses. - * @param rrset_cache: to look into. - * @param now: current time. - * @param region: where to perform the allocation - * @param msg: current msg with NSEC. - * @param zone: val_neg_zone if we have one. - * @return false on lookup or alloc failure. - */ -static int add_soa(struct rrset_cache* rrset_cache, time_t now, - struct regional* region, struct dns_msg* msg, struct val_neg_zone* zone) -{ - struct ub_packed_rrset_key* soa; - uint8_t* nm; - size_t nmlen; - uint16_t dclass; - if(zone) { - nm = zone->name; - nmlen = zone->len; - dclass = zone->dclass; - } else { - /* Assumes the signer is the zone SOA to add */ - nm = reply_nsec_signer(msg->rep, &nmlen, &dclass); - if(!nm) - return 0; - } - soa = rrset_cache_lookup(rrset_cache, nm, nmlen, LDNS_RR_TYPE_SOA, - dclass, PACKED_RRSET_SOA_NEG, now, 0); - if(!soa) - return 0; - if(!dns_msg_authadd(msg, region, soa, now)) { - lock_rw_unlock(&soa->entry.lock); - return 0; - } - lock_rw_unlock(&soa->entry.lock); - return 1; -} - -struct dns_msg* -val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo, - struct regional* region, struct rrset_cache* rrset_cache, - sldns_buffer* buf, time_t now, int addsoa, uint8_t* topname, - struct config_file* cfg) -{ - struct dns_msg* msg; - struct ub_packed_rrset_key* nsec; /* qname matching/covering nsec */ - struct ub_packed_rrset_key* wcrr; /* wildcard record or nsec */ - uint8_t* nodata_wc = NULL; - uint8_t* ce = NULL; - size_t ce_len; - uint8_t wc_ce[LDNS_MAX_DOMAINLEN+3]; - struct query_info wc_qinfo; - struct ub_packed_rrset_key* cache_wc; - struct packed_rrset_data* wcrr_data; - int rcode = LDNS_RCODE_NOERROR; - uint8_t* zname; - size_t zname_len; - int zname_labs; - struct val_neg_zone* zone; - - /* only for DS queries when aggressive use of NSEC is disabled */ - if(qinfo->qtype != LDNS_RR_TYPE_DS && !cfg->aggressive_nsec) - return NULL; - log_assert(!topname || dname_subdomain_c(qinfo->qname, topname)); - - /* Get best available NSEC for qname */ - nsec = neg_find_nsec(neg, qinfo->qname, qinfo->qname_len, qinfo->qclass, - rrset_cache, now, region); - - /* Matching NSEC, use to generate No Data answer. Not creating answers - * yet for No Data proven using wildcard. */ - if(nsec && nsec_proves_nodata(nsec, qinfo, &nodata_wc) && !nodata_wc) { - /* do not create nodata answers for qtype ANY, it is a query - * type, not an rrtype to disprove. Nameerrors are useful for - * qtype ANY, in the else branch. */ - if(qinfo->qtype == LDNS_RR_TYPE_ANY) - return NULL; - if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, - qinfo->qtype, qinfo->qclass, region, 2))) - return NULL; - if(!dns_msg_authadd(msg, region, nsec, 0)) - return NULL; - if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL)) - return NULL; - - lock_basic_lock(&neg->lock); - neg->num_neg_cache_noerror++; - lock_basic_unlock(&neg->lock); - return msg; - } else if(nsec && val_nsec_proves_name_error(nsec, qinfo->qname)) { - if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, - qinfo->qtype, qinfo->qclass, region, 3))) - return NULL; - if(!(ce = nsec_closest_encloser(qinfo->qname, nsec))) - return NULL; - dname_count_size_labels(ce, &ce_len); - - /* No extra extra NSEC required if both nameerror qname and - * nodata *.ce. are proven already. */ - if(!nodata_wc || query_dname_compare(nodata_wc, ce) != 0) { - /* Qname proven non existing, get wildcard record for - * QTYPE or NSEC covering or matching wildcard. */ - - /* Num labels in ce is always smaller than in qname, - * therefore adding the wildcard label cannot overflow - * buffer. */ - wc_ce[0] = 1; - wc_ce[1] = (uint8_t)'*'; - memmove(wc_ce+2, ce, ce_len); - wc_qinfo.qname = wc_ce; - wc_qinfo.qname_len = ce_len + 2; - wc_qinfo.qtype = qinfo->qtype; - - - if((cache_wc = rrset_cache_lookup(rrset_cache, wc_qinfo.qname, - wc_qinfo.qname_len, wc_qinfo.qtype, - qinfo->qclass, 0/*flags*/, now, 0/*read only*/))) { - /* Synthesize wildcard answer */ - wcrr_data = (struct packed_rrset_data*)cache_wc->entry.data; - if(!(wcrr_data->security == sec_status_secure || - (wcrr_data->security == sec_status_unchecked && - wcrr_data->rrsig_count > 0))) { - lock_rw_unlock(&cache_wc->entry.lock); - return NULL; - } - if(!(wcrr = packed_rrset_copy_region(cache_wc, - region, now))) { - lock_rw_unlock(&cache_wc->entry.lock); - return NULL; - }; - lock_rw_unlock(&cache_wc->entry.lock); - wcrr->rk.dname = qinfo->qname; - wcrr->rk.dname_len = qinfo->qname_len; - if(!dns_msg_ansadd(msg, region, wcrr, 0)) - return NULL; - /* No SOA needed for wildcard synthesised - * answer. */ - addsoa = 0; - } else { - /* Get wildcard NSEC for possible non existence - * proof */ - if(!(wcrr = neg_find_nsec(neg, wc_qinfo.qname, - wc_qinfo.qname_len, qinfo->qclass, - rrset_cache, now, region))) - return NULL; - - nodata_wc = NULL; - if(val_nsec_proves_name_error(wcrr, wc_ce)) - rcode = LDNS_RCODE_NXDOMAIN; - else if(!nsec_proves_nodata(wcrr, &wc_qinfo, - &nodata_wc) || nodata_wc) - /* &nodata_wc shouldn't be set, wc_qinfo - * already contains wildcard domain. */ - /* NSEC doesn't prove anything for - * wildcard. */ - return NULL; - if(query_dname_compare(wcrr->rk.dname, - nsec->rk.dname) != 0) - if(!dns_msg_authadd(msg, region, wcrr, 0)) - return NULL; - } - } - - if(!dns_msg_authadd(msg, region, nsec, 0)) - return NULL; - if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL)) - return NULL; - - /* Increment statistic counters */ - lock_basic_lock(&neg->lock); - if(rcode == LDNS_RCODE_NOERROR) - neg->num_neg_cache_noerror++; - else if(rcode == LDNS_RCODE_NXDOMAIN) - neg->num_neg_cache_nxdomain++; - lock_basic_unlock(&neg->lock); - - FLAGS_SET_RCODE(msg->rep->flags, rcode); - return msg; - } - - /* No aggressive use of NSEC3 for now, only proceed for DS types. */ - if(qinfo->qtype != LDNS_RR_TYPE_DS){ - return NULL; - } - /* check NSEC3 neg cache for type DS */ - /* need to look one zone higher for DS type */ - zname = qinfo->qname; - zname_len = qinfo->qname_len; - dname_remove_label(&zname, &zname_len); - zname_labs = dname_count_labels(zname); - - /* lookup closest zone */ - lock_basic_lock(&neg->lock); - zone = neg_closest_zone_parent(neg, zname, zname_len, zname_labs, - qinfo->qclass); - while(zone && !zone->in_use) - zone = zone->parent; - /* check that the zone is not too high up so that we do not pick data - * out of a zone that is above the last-seen key (or trust-anchor). */ - if(zone && topname) { - if(!dname_subdomain_c(zone->name, topname)) - zone = NULL; - } - if(!zone) { - lock_basic_unlock(&neg->lock); - return NULL; - } - - msg = neg_nsec3_proof_ds(zone, qinfo->qname, qinfo->qname_len, - zname_labs+1, buf, rrset_cache, region, now, topname); - if(msg && addsoa && !add_soa(rrset_cache, now, region, msg, zone)) { - lock_basic_unlock(&neg->lock); - return NULL; - } - lock_basic_unlock(&neg->lock); - return msg; -} diff --git a/crates/libunbound-sys/unbound/validator/val_neg.h b/crates/libunbound-sys/unbound/validator/val_neg.h deleted file mode 100644 index 5643ca33..00000000 --- a/crates/libunbound-sys/unbound/validator/val_neg.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * validator/val_neg.h - validator aggressive negative caching functions. - * - * Copyright (c) 2008, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with aggressive negative caching. - * This creates new denials of existence, and proofs for absence of types - * from cached NSEC records. - */ - -#ifndef VALIDATOR_VAL_NEG_H -#define VALIDATOR_VAL_NEG_H -#include "util/locks.h" -#include "util/rbtree.h" -struct sldns_buffer; -struct val_neg_data; -struct config_file; -struct reply_info; -struct rrset_cache; -struct regional; -struct query_info; -struct dns_msg; -struct ub_packed_rrset_key; - -/** - * The negative cache. It is shared between the threads, so locked. - * Kept as validator-environ-state. It refers back to the rrset cache for - * data elements. It can be out of date and contain conflicting data - * from zone content changes. - * It contains a tree of zones, every zone has a tree of data elements. - * The data elements are part of one big LRU list, with one memory counter. - */ -struct val_neg_cache { - /** the big lock on the negative cache. Because we use a rbtree - * for the data (quick lookup), we need a big lock */ - lock_basic_type lock; - /** The zone rbtree. contents sorted canonical, type val_neg_zone */ - rbtree_type tree; - /** the first in linked list of LRU of val_neg_data */ - struct val_neg_data* first; - /** last in lru (least recently used element) */ - struct val_neg_data* last; - /** current memory in use (bytes) */ - size_t use; - /** max memory to use (bytes) */ - size_t max; - /** max nsec3 iterations allowed */ - size_t nsec3_max_iter; - /** number of times neg cache records were used to generate NOERROR - * responses. */ - size_t num_neg_cache_noerror; - /** number of times neg cache records were used to generate NXDOMAIN - * responses. */ - size_t num_neg_cache_nxdomain; -}; - -/** - * Per Zone aggressive negative caching data. - */ -struct val_neg_zone { - /** rbtree node element, key is this struct: the name, class */ - rbnode_type node; - /** name; the key */ - uint8_t* name; - /** length of name */ - size_t len; - /** labels in name */ - int labs; - - /** pointer to parent zone in the negative cache */ - struct val_neg_zone* parent; - - /** the number of elements, including this one and the ones whose - * parents (-parents) include this one, that are in_use - * No elements have a count of zero, those are removed. */ - int count; - - /** if 0: NSEC zone, else NSEC3 hash algorithm in use */ - int nsec3_hash; - /** nsec3 iteration count in use */ - size_t nsec3_iter; - /** nsec3 salt in use */ - uint8_t* nsec3_salt; - /** length of salt in bytes */ - size_t nsec3_saltlen; - - /** tree of NSEC data for this zone, sorted canonical - * by NSEC owner name */ - rbtree_type tree; - - /** class of node; host order */ - uint16_t dclass; - /** if this element is in use, boolean */ - uint8_t in_use; -}; - -/** - * Data element for aggressive negative caching. - * The tree of these elements acts as an index onto the rrset cache. - * It shows the NSEC records that (may) exist and are (possibly) secure. - * The rbtree allows for logN search for a covering NSEC record. - * To make tree insertion and deletion logN too, all the parent (one label - * less than the name) data elements are also in the rbtree, with a usage - * count for every data element. - * There is no actual data stored in this data element, if it is in_use, - * then the data can (possibly) be found in the rrset cache. - */ -struct val_neg_data { - /** rbtree node element, key is this struct: the name */ - rbnode_type node; - /** name; the key */ - uint8_t* name; - /** length of name */ - size_t len; - /** labels in name */ - int labs; - - /** pointer to parent node in the negative cache */ - struct val_neg_data* parent; - - /** the number of elements, including this one and the ones whose - * parents (-parents) include this one, that are in use - * No elements have a count of zero, those are removed. */ - int count; - - /** the zone that this denial is part of */ - struct val_neg_zone* zone; - - /** previous in LRU */ - struct val_neg_data* prev; - /** next in LRU (next element was less recently used) */ - struct val_neg_data* next; - - /** if this element is in use, boolean */ - uint8_t in_use; -}; - -/** - * Create negative cache - * @param cfg: config options. - * @param maxiter: max nsec3 iterations allowed. - * @return neg cache, empty or NULL on failure. - */ -struct val_neg_cache* val_neg_create(struct config_file* cfg, size_t maxiter); - -/** - * see how much memory is in use by the negative cache. - * @param neg: negative cache - * @return number of bytes in use. - */ -size_t val_neg_get_mem(struct val_neg_cache* neg); - -/** - * Destroy negative cache. There must no longer be any other threads. - * @param neg: negative cache. - */ -void neg_cache_delete(struct val_neg_cache* neg); - -/** - * Comparison function for rbtree val neg data elements - */ -int val_neg_data_compare(const void* a, const void* b); - -/** - * Comparison function for rbtree val neg zone elements - */ -int val_neg_zone_compare(const void* a, const void* b); - -/** - * Insert NSECs from this message into the negative cache for reference. - * @param neg: negative cache - * @param rep: reply with NSECs. - * Errors are ignored, means that storage is omitted. - */ -void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep); - -/** - * Insert NSECs from this referral into the negative cache for reference. - * @param neg: negative cache - * @param rep: referral reply with NS, NSECs. - * @param zone: bailiwick for the referral. - * Errors are ignored, means that storage is omitted. - */ -void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep, - uint8_t* zone); - -/** - * For the given query, try to get a reply out of the negative cache. - * The reply still needs to be validated. - * @param neg: negative cache. - * @param qinfo: query - * @param region: where to allocate reply. - * @param rrset_cache: rrset cache. - * @param buf: temporary buffer. - * @param now: to check TTLs against. - * @param addsoa: if true, produce result for external consumption. - * if false, do not add SOA - for unbound-internal consumption. - * @param topname: do not look higher than this name, - * so that the result cannot be taken from a zone above the current - * trust anchor. Which could happen with multiple islands of trust. - * if NULL, then no trust anchor is used, but also the algorithm becomes - * more conservative, especially for opt-out zones, since the receiver - * may have a trust-anchor below the optout and thus the optout cannot - * be used to create a proof from the negative cache. - * @param cfg: config options. - * @return a reply message if something was found. - * This reply may still need validation. - * NULL if nothing found (or out of memory). - */ -struct dns_msg* val_neg_getmsg(struct val_neg_cache* neg, - struct query_info* qinfo, struct regional* region, - struct rrset_cache* rrset_cache, struct sldns_buffer* buf, time_t now, - int addsoa, uint8_t* topname, struct config_file* cfg); - - -/**** functions exposed for unit test ****/ -/** - * Insert data into the data tree of a zone - * Does not do locking. - * @param neg: negative cache - * @param zone: zone to insert into - * @param nsec: record to insert. - */ -void neg_insert_data(struct val_neg_cache* neg, - struct val_neg_zone* zone, struct ub_packed_rrset_key* nsec); - -/** - * Delete a data element from the negative cache. - * May delete other data elements to keep tree coherent, or - * only mark the element as 'not in use'. - * Does not do locking. - * @param neg: negative cache. - * @param el: data element to delete. - */ -void neg_delete_data(struct val_neg_cache* neg, struct val_neg_data* el); - -/** - * Find the given zone, from the SOA owner name and class - * Does not do locking. - * @param neg: negative cache - * @param nm: what to look for. - * @param len: length of nm - * @param dclass: class to look for. - * @return zone or NULL if not found. - */ -struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg, - uint8_t* nm, size_t len, uint16_t dclass); - -/** - * Create a new zone. - * Does not do locking. - * @param neg: negative cache - * @param nm: what to look for. - * @param nm_len: length of name. - * @param dclass: class of zone, host order. - * @return zone or NULL if out of memory. - */ -struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg, - uint8_t* nm, size_t nm_len, uint16_t dclass); - -/** - * take a zone into use. increases counts of parents. - * Does not do locking. - * @param zone: zone to take into use. - */ -void val_neg_zone_take_inuse(struct val_neg_zone* zone); - -#endif /* VALIDATOR_VAL_NEG_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_nsec.c b/crates/libunbound-sys/unbound/validator/val_nsec.c deleted file mode 100644 index 17c90d83..00000000 --- a/crates/libunbound-sys/unbound/validator/val_nsec.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * validator/val_nsec.c - validator NSEC denial of existence functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with NSEC checking, the different NSEC proofs - * for denial of existence, and proofs for presence of types. - */ -#include "config.h" -#include "validator/val_nsec.h" -#include "validator/val_utils.h" -#include "util/data/msgreply.h" -#include "util/data/dname.h" -#include "util/net_help.h" -#include "util/module.h" -#include "services/cache/rrset.h" - -/** get ttl of rrset */ -static uint32_t -rrset_get_ttl(struct ub_packed_rrset_key* k) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - return d->ttl; -} - -int -nsecbitmap_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type) -{ - /* Check type present in NSEC typemap with bitmap arg */ - /* bitmasks for determining type-lowerbits presence */ - uint8_t masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; - uint8_t type_window = type>>8; - uint8_t type_low = type&0xff; - uint8_t win, winlen; - /* read each of the type bitmap windows and see if the searched - * type is amongst it */ - while(len > 0) { - if(len < 3) /* bad window, at least window# winlen bitmap */ - return 0; - win = *bitmap++; - winlen = *bitmap++; - len -= 2; - if(len < winlen || winlen < 1 || winlen > 32) - return 0; /* bad window length */ - if(win == type_window) { - /* search window bitmap for the correct byte */ - /* mybyte is 0 if we need the first byte */ - size_t mybyte = type_low>>3; - if(winlen <= mybyte) - return 0; /* window too short */ - return (int)(bitmap[mybyte] & masks[type_low&0x7]); - } else { - /* not the window we are looking for */ - bitmap += winlen; - len -= winlen; - } - } - /* end of bitmap reached, no type found */ - return 0; -} - -int -nsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> - entry.data; - size_t len; - if(!d || d->count == 0 || d->rr_len[0] < 2+1) - return 0; - len = dname_valid(d->rr_data[0]+2, d->rr_len[0]-2); - if(!len) - return 0; - return nsecbitmap_has_type_rdata(d->rr_data[0]+2+len, - d->rr_len[0]-2-len, type); -} - -/** - * Get next owner name from nsec record - * @param nsec: the nsec RRset. - * If there are multiple RRs, then this will only return one of them. - * @param nm: the next name is returned. - * @param ln: length of nm is returned. - * @return false on a bad NSEC RR (too short, malformed dname). - */ -static int -nsec_get_next(struct ub_packed_rrset_key* nsec, uint8_t** nm, size_t* ln) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> - entry.data; - if(!d || d->count == 0 || d->rr_len[0] < 2+1) { - *nm = 0; - *ln = 0; - return 0; - } - *nm = d->rr_data[0]+2; - *ln = dname_valid(*nm, d->rr_len[0]-2); - if(!*ln) { - *nm = 0; - *ln = 0; - return 0; - } - return 1; -} - -/** - * For an NSEC that matches the DS queried for, check absence of DS type. - * - * @param nsec: NSEC for proof, must be trusted. - * @param qinfo: what is queried for. - * @return if secure the nsec proves that no DS is present, or - * insecure if it proves it is not a delegation point. - * or bogus if something was wrong. - */ -static enum sec_status -val_nsec_proves_no_ds(struct ub_packed_rrset_key* nsec, - struct query_info* qinfo) -{ - log_assert(qinfo->qtype == LDNS_RR_TYPE_DS); - log_assert(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC); - - if(nsec_has_type(nsec, LDNS_RR_TYPE_SOA) && qinfo->qname_len != 1) { - /* SOA present means that this is the NSEC from the child, - * not the parent (so it is the wrong one). */ - return sec_status_bogus; - } - if(nsec_has_type(nsec, LDNS_RR_TYPE_DS)) { - /* DS present means that there should have been a positive - * response to the DS query, so there is something wrong. */ - return sec_status_bogus; - } - - if(!nsec_has_type(nsec, LDNS_RR_TYPE_NS)) { - /* If there is no NS at this point at all, then this - * doesn't prove anything one way or the other. */ - return sec_status_insecure; - } - /* Otherwise, this proves no DS. */ - return sec_status_secure; -} - -/** check security status from cache or verify rrset, returns true if secure */ -static int -nsec_verify_rrset(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey, - char** reason, sldns_ede_code* reason_bogus, - struct module_qstate* qstate) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - nsec->entry.data; - if(!d) return 0; - if(d->security == sec_status_secure) - return 1; - rrset_check_sec_status(env->rrset_cache, nsec, *env->now); - if(d->security == sec_status_secure) - return 1; - d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason, - reason_bogus, LDNS_SECTION_AUTHORITY, qstate); - if(d->security == sec_status_secure) { - rrset_update_sec_status(env->rrset_cache, nsec, *env->now); - return 1; - } - return 0; -} - -enum sec_status -val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve, - struct query_info* qinfo, struct reply_info* rep, - struct key_entry_key* kkey, time_t* proof_ttl, char** reason, - sldns_ede_code* reason_bogus, struct module_qstate* qstate) -{ - struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns( - rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC, - qinfo->qclass); - enum sec_status sec; - size_t i; - uint8_t* wc = NULL, *ce = NULL; - int valid_nsec = 0; - struct ub_packed_rrset_key* wc_nsec = NULL; - - /* If we have a NSEC at the same name, it must prove one - * of two things - * -- - * 1) this is a delegation point and there is no DS - * 2) this is not a delegation point */ - if(nsec) { - if(!nsec_verify_rrset(env, ve, nsec, kkey, reason, - reason_bogus, qstate)) { - verbose(VERB_ALGO, "NSEC RRset for the " - "referral did not verify."); - return sec_status_bogus; - } - sec = val_nsec_proves_no_ds(nsec, qinfo); - if(sec == sec_status_bogus) { - /* something was wrong. */ - *reason = "NSEC does not prove absence of DS"; - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec; - } else if(sec == sec_status_insecure) { - /* this wasn't a delegation point. */ - return sec; - } else if(sec == sec_status_secure) { - /* this proved no DS. */ - *proof_ttl = ub_packed_rrset_ttl(nsec); - return sec; - } - /* if unchecked, fall through to next proof */ - } - - /* Otherwise, there is no NSEC at qname. This could be an ENT. - * (ENT=empty non terminal). If not, this is broken. */ - - /* verify NSEC rrsets in auth section */ - for(i=rep->an_numrrsets; i < rep->an_numrrsets+rep->ns_numrrsets; - i++) { - if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC)) - continue; - if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason, - reason_bogus, qstate)) { - verbose(VERB_ALGO, "NSEC for empty non-terminal " - "did not verify."); - *reason = "NSEC for empty non-terminal " - "did not verify."; - return sec_status_bogus; - } - if(nsec_proves_nodata(rep->rrsets[i], qinfo, &wc)) { - verbose(VERB_ALGO, "NSEC for empty non-terminal " - "proved no DS."); - *proof_ttl = rrset_get_ttl(rep->rrsets[i]); - if(wc && dname_is_wild(rep->rrsets[i]->rk.dname)) - wc_nsec = rep->rrsets[i]; - valid_nsec = 1; - } - if(val_nsec_proves_name_error(rep->rrsets[i], qinfo->qname)) { - ce = nsec_closest_encloser(qinfo->qname, - rep->rrsets[i]); - } - } - if(wc && !ce) - valid_nsec = 0; - else if(wc && ce) { - /* ce and wc must match */ - if(query_dname_compare(wc, ce) != 0) - valid_nsec = 0; - else if(!wc_nsec) - valid_nsec = 0; - } - if(valid_nsec) { - if(wc) { - /* check if this is a delegation */ - *reason = "NSEC for wildcard does not prove absence of DS"; - return val_nsec_proves_no_ds(wc_nsec, qinfo); - } - /* valid nsec proves empty nonterminal */ - return sec_status_insecure; - } - - /* NSEC proof did not conclusively point to DS or no DS */ - return sec_status_unchecked; -} - -int nsec_proves_nodata(struct ub_packed_rrset_key* nsec, - struct query_info* qinfo, uint8_t** wc) -{ - log_assert(wc); - if(query_dname_compare(nsec->rk.dname, qinfo->qname) != 0) { - uint8_t* nm; - size_t ln; - - /* empty-non-terminal checking. - * Done before wildcard, because this is an exact match, - * and would prevent a wildcard from matching. */ - - /* If the nsec is proving that qname is an ENT, the nsec owner - * will be less than qname, and the next name will be a child - * domain of the qname. */ - if(!nsec_get_next(nsec, &nm, &ln)) - return 0; /* bad nsec */ - if(dname_strict_subdomain_c(nm, qinfo->qname) && - dname_canonical_compare(nsec->rk.dname, - qinfo->qname) < 0) { - return 1; /* proves ENT */ - } - - /* wildcard checking. */ - - /* If this is a wildcard NSEC, make sure that a) it was - * possible to have generated qname from the wildcard and - * b) the type map does not contain qtype. Note that this - * does NOT prove that this wildcard was the applicable - * wildcard. */ - if(dname_is_wild(nsec->rk.dname)) { - /* the purported closest encloser. */ - uint8_t* ce = nsec->rk.dname; - size_t ce_len = nsec->rk.dname_len; - dname_remove_label(&ce, &ce_len); - - /* The qname must be a strict subdomain of the - * closest encloser, for the wildcard to apply - */ - if(dname_strict_subdomain_c(qinfo->qname, ce)) { - /* here we have a matching NSEC for the qname, - * perform matching NSEC checks */ - if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) { - /* should have gotten the wildcard CNAME */ - return 0; - } - if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) && - !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { - /* wrong parentside (wildcard) NSEC used */ - return 0; - } - if(nsec_has_type(nsec, qinfo->qtype)) { - return 0; - } - *wc = ce; - return 1; - } - } else { - /* See if the next owner name covers a wildcard - * empty non-terminal. */ - while (dname_canonical_compare(nsec->rk.dname, nm) < 0) { - /* wildcard does not apply if qname below - * the name that exists under the '*' */ - if (dname_subdomain_c(qinfo->qname, nm)) - break; - /* but if it is a wildcard and qname is below - * it, then the wildcard applies. The wildcard - * is an empty nonterminal. nodata proven. */ - if (dname_is_wild(nm)) { - size_t ce_len = ln; - uint8_t* ce = nm; - dname_remove_label(&ce, &ce_len); - if(dname_strict_subdomain_c(qinfo->qname, ce)) { - *wc = ce; - return 1; - } - } - dname_remove_label(&nm, &ln); - } - } - - /* Otherwise, this NSEC does not prove ENT and is not a - * wildcard, so it does not prove NODATA. */ - return 0; - } - - /* If the qtype exists, then we should have gotten it. */ - if(nsec_has_type(nsec, qinfo->qtype)) { - return 0; - } - - /* if the name is a CNAME node, then we should have gotten the CNAME*/ - if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) { - return 0; - } - - /* If an NS set exists at this name, and NOT a SOA (so this is a - * zone cut, not a zone apex), then we should have gotten a - * referral (or we just got the wrong NSEC). - * The reverse of this check is used when qtype is DS, since that - * must use the NSEC from above the zone cut. */ - if(qinfo->qtype != LDNS_RR_TYPE_DS && - nsec_has_type(nsec, LDNS_RR_TYPE_NS) && - !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { - return 0; - } else if(qinfo->qtype == LDNS_RR_TYPE_DS && - nsec_has_type(nsec, LDNS_RR_TYPE_SOA) && - !dname_is_root(qinfo->qname)) { - return 0; - } - - return 1; -} - -int -val_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, uint8_t* qname) -{ - uint8_t* owner = nsec->rk.dname; - uint8_t* next; - size_t nlen; - if(!nsec_get_next(nsec, &next, &nlen)) - return 0; - - /* If NSEC owner == qname, then this NSEC proves that qname exists. */ - if(query_dname_compare(qname, owner) == 0) { - return 0; - } - - /* If NSEC is a parent of qname, we need to check the type map - * If the parent name has a DNAME or is a delegation point, then - * this NSEC is being misused. */ - if(dname_subdomain_c(qname, owner) && - (nsec_has_type(nsec, LDNS_RR_TYPE_DNAME) || - (nsec_has_type(nsec, LDNS_RR_TYPE_NS) - && !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) - )) { - return 0; - } - - if(query_dname_compare(owner, next) == 0) { - /* this nsec is the only nsec */ - /* zone.name NSEC zone.name, disproves everything else */ - /* but only for subdomains of that zone */ - if(dname_strict_subdomain_c(qname, next)) - return 1; - } - else if(dname_canonical_compare(owner, next) > 0) { - /* this is the last nsec, ....(bigger) NSEC zonename(smaller) */ - /* the names after the last (owner) name do not exist - * there are no names before the zone name in the zone - * but the qname must be a subdomain of the zone name(next). */ - if(dname_canonical_compare(owner, qname) < 0 && - dname_strict_subdomain_c(qname, next)) - return 1; - } else { - /* regular NSEC, (smaller) NSEC (larger) */ - if(dname_canonical_compare(owner, qname) < 0 && - dname_canonical_compare(qname, next) < 0) { - return 1; - } - } - return 0; -} - -int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec, - struct query_info* qinfo) -{ - if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) && - !nsec_has_type(nsec, LDNS_RR_TYPE_DS) && - !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { - /* see if nsec signals an insecure delegation */ - if(qinfo->qtype == LDNS_RR_TYPE_DS) { - /* if type is DS and qname is equal to nsec, then it - * is an exact match nsec, result not insecure */ - if(dname_strict_subdomain_c(qinfo->qname, - nsec->rk.dname)) - return 1; - } else { - if(dname_subdomain_c(qinfo->qname, nsec->rk.dname)) - return 1; - } - } - return 0; -} - -uint8_t* -nsec_closest_encloser(uint8_t* qname, struct ub_packed_rrset_key* nsec) -{ - uint8_t* next; - size_t nlen; - uint8_t* common1, *common2; - if(!nsec_get_next(nsec, &next, &nlen)) - return NULL; - /* longest common with owner or next name */ - common1 = dname_get_shared_topdomain(nsec->rk.dname, qname); - common2 = dname_get_shared_topdomain(next, qname); - if(dname_count_labels(common1) > dname_count_labels(common2)) - return common1; - return common2; -} - -int val_nsec_proves_positive_wildcard(struct ub_packed_rrset_key* nsec, - struct query_info* qinf, uint8_t* wc) -{ - uint8_t* ce; - /* 1) prove that qname doesn't exist and - * 2) that the correct wildcard was used - * nsec has been verified already. */ - if(!val_nsec_proves_name_error(nsec, qinf->qname)) - return 0; - /* check wildcard name */ - ce = nsec_closest_encloser(qinf->qname, nsec); - if(!ce) - return 0; - if(query_dname_compare(wc, ce) != 0) { - return 0; - } - return 1; -} - -int -val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, - size_t qnamelen) -{ - /* Determine if a NSEC record proves the non-existence of a - * wildcard that could have produced qname. */ - int labs; - uint8_t* ce = nsec_closest_encloser(qname, nsec); - uint8_t* strip; - size_t striplen; - uint8_t buf[LDNS_MAX_DOMAINLEN+3]; - if(!ce) - return 0; - /* we can subtract the closest encloser count - since that is the - * largest shared topdomain with owner and next NSEC name, - * because the NSEC is no proof for names shorter than the owner - * and next names. */ - labs = dname_count_labels(qname) - dname_count_labels(ce); - - if(labs > 0) { - /* i is number of labels to strip off qname, prepend * wild */ - strip = qname; - striplen = qnamelen; - dname_remove_labels(&strip, &striplen, labs); - if(striplen > LDNS_MAX_DOMAINLEN-2) - return 0; /* too long to prepend wildcard */ - buf[0] = 1; - buf[1] = (uint8_t)'*'; - memmove(buf+2, strip, striplen); - if(val_nsec_proves_name_error(nsec, buf)) { - return 1; - } - } - return 0; -} diff --git a/crates/libunbound-sys/unbound/validator/val_nsec.h b/crates/libunbound-sys/unbound/validator/val_nsec.h deleted file mode 100644 index 81844c90..00000000 --- a/crates/libunbound-sys/unbound/validator/val_nsec.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * validator/val_nsec.h - validator NSEC denial of existence functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with NSEC checking, the different NSEC proofs - * for denial of existence, and proofs for presence of types. - */ - -#ifndef VALIDATOR_VAL_NSEC_H -#define VALIDATOR_VAL_NSEC_H -#include "util/data/packed_rrset.h" -#include "sldns/rrdef.h" -struct val_env; -struct module_env; -struct module_qstate; -struct ub_packed_rrset_key; -struct reply_info; -struct query_info; -struct key_entry_key; - -/** - * Check DS absence. - * There is a NODATA reply to a DS that needs checking. - * NSECs can prove this is not a delegation point, or successfully prove - * that there is no DS. Or this fails. - * - * @param env: module env for rrsig verification routines. - * @param ve: validator env for rrsig verification routines. - * @param qinfo: the DS queried for. - * @param rep: reply received. - * @param kkey: key entry to use for verification of signatures. - * @param proof_ttl: if secure, the TTL of how long this proof lasts. - * @param reason: string explaining why bogus. - * @param reason_bogus: relevant EDE code for validation failure. - * @param qstate: qstate with region. - * @return security status. - * SECURE: proved absence of DS. - * INSECURE: proved that this was not a delegation point. - * BOGUS: crypto bad, or no absence of DS proven. - * UNCHECKED: there was no way to prove anything (no NSECs, unknown algo). - */ -enum sec_status val_nsec_prove_nodata_dsreply(struct module_env* env, - struct val_env* ve, struct query_info* qinfo, - struct reply_info* rep, struct key_entry_key* kkey, - time_t* proof_ttl, char** reason, sldns_ede_code* reason_bogus, - struct module_qstate* qstate); - -/** - * nsec typemap check, takes an NSEC-type bitmap as argument, checks for type. - * @param bitmap: pointer to the bitmap part of wireformat rdata. - * @param len: length of the bitmap, in bytes. - * @param type: the type (in host order) to check for. - * @return true if the type bit was set in the bitmap. false if not, or - * if the bitmap was malformed in some way. - */ -int nsecbitmap_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type); - -/** - * Check if type is present in the NSEC typemap - * @param nsec: the nsec RRset. - * If there are multiple RRs, then each must have the same typemap, - * since the typemap represents the types at this domain node. - * @param type: type to check for, host order. - * @return true if present - */ -int nsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type); - -/** - * Determine if a NSEC proves the NOERROR/NODATA conditions. This will also - * handle the empty non-terminal (ENT) case and partially handle the - * wildcard case. If the ownername of 'nsec' is a wildcard, the validator - * must still be provided proof that qname did not directly exist and that - * the wildcard is, in fact, *.closest_encloser. - * - * @param nsec: the nsec record to check against. - * @param qinfo: the query info. - * @param wc: if the nodata is proven for a wildcard match, the wildcard - * closest encloser is returned, else NULL (wc is unchanged). - * This closest encloser must then match the nameerror given for the - * nextcloser of qname. - * @return true if NSEC proves this. - */ -int nsec_proves_nodata(struct ub_packed_rrset_key* nsec, - struct query_info* qinfo, uint8_t** wc); - -/** - * Determine if the given NSEC proves a NameError (NXDOMAIN) for a given - * qname. - * - * @param nsec: the nsec to check - * @param qname: what was queried. - * @return true if proven. - */ -int val_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, - uint8_t* qname); - -/** - * Determine if the given NSEC proves a positive wildcard response. - * @param nsec: the nsec to check - * @param qinf: what was queried. - * @param wc: wildcard (without *. label) - * @return true if proven. - */ -int val_nsec_proves_positive_wildcard(struct ub_packed_rrset_key* nsec, - struct query_info* qinf, uint8_t* wc); - -/** - * Determine closest encloser of a query name and the NSEC that covers it - * (and thus disproved it). - * A name error must have been proven already, otherwise this will be invalid. - * @param qname: the name queried for. - * @param nsec: the nsec RRset. - * @return closest encloser dname or NULL on error (bad nsec RRset). - */ -uint8_t* nsec_closest_encloser(uint8_t* qname, - struct ub_packed_rrset_key* nsec); - -/** - * Determine if the given NSEC proves that a wildcard match does not exist. - * - * @param nsec: the nsec RRset. - * @param qname: the name queried for. - * @param qnamelen: length of qname. - * @return true if proven. - */ -int val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, - size_t qnamelen); - -/** - * Determine if an nsec proves an insecure delegation towards the qname. - * @param nsec: nsec rrset. - * @param qinfo: what was queries for. - * @return 0 if not, 1 if an NSEC that signals an insecure delegation to - * the qname. - */ -int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec, - struct query_info* qinfo); - -#endif /* VALIDATOR_VAL_NSEC_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_nsec3.c b/crates/libunbound-sys/unbound/validator/val_nsec3.c deleted file mode 100644 index a2b3794f..00000000 --- a/crates/libunbound-sys/unbound/validator/val_nsec3.c +++ /dev/null @@ -1,1442 +0,0 @@ -/* - * validator/val_nsec3.c - validator NSEC3 denial of existence functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with NSEC3 checking, the different NSEC3 proofs - * for denial of existence, and proofs for presence of types. - */ -#include "config.h" -#include -#include "validator/val_nsec3.h" -#include "validator/val_secalgo.h" -#include "validator/validator.h" -#include "validator/val_kentry.h" -#include "services/cache/rrset.h" -#include "util/regional.h" -#include "util/rbtree.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/data/msgreply.h" -/* we include nsec.h for the bitmap_has_type function */ -#include "validator/val_nsec.h" -#include "sldns/sbuffer.h" - -/** - * This function we get from ldns-compat or from base system - * it returns the number of data bytes stored at the target, or <0 on error. - */ -int sldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, - char *target, size_t targsize); -/** - * This function we get from ldns-compat or from base system - * it returns the number of data bytes stored at the target, or <0 on error. - */ -int sldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, - uint8_t *target, size_t targsize); - -/** - * Closest encloser (ce) proof results - * Contains the ce and the next-closer (nc) proof. - */ -struct ce_response { - /** the closest encloser name */ - uint8_t* ce; - /** length of ce */ - size_t ce_len; - /** NSEC3 record that proved ce. rrset */ - struct ub_packed_rrset_key* ce_rrset; - /** NSEC3 record that proved ce. rr number */ - int ce_rr; - /** NSEC3 record that proved nc. rrset */ - struct ub_packed_rrset_key* nc_rrset; - /** NSEC3 record that proved nc. rr*/ - int nc_rr; -}; - -/** - * Filter conditions for NSEC3 proof - * Used to iterate over the applicable NSEC3 RRs. - */ -struct nsec3_filter { - /** Zone name, only NSEC3 records for this zone are considered */ - uint8_t* zone; - /** length of the zonename */ - size_t zone_len; - /** the list of NSEC3s to filter; array */ - struct ub_packed_rrset_key** list; - /** number of rrsets in list */ - size_t num; - /** class of records for the NSEC3, only this class applies */ - uint16_t fclass; -}; - -/** return number of rrs in an rrset */ -static size_t -rrset_get_count(struct ub_packed_rrset_key* rrset) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - if(!d) return 0; - return d->count; -} - -/** return if nsec3 RR has unknown flags */ -static int -nsec3_unknown_flags(struct ub_packed_rrset_key* rrset, int r) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+2) - return 0; /* malformed */ - return (int)(d->rr_data[r][2+1] & NSEC3_UNKNOWN_FLAGS); -} - -int -nsec3_has_optout(struct ub_packed_rrset_key* rrset, int r) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+2) - return 0; /* malformed */ - return (int)(d->rr_data[r][2+1] & NSEC3_OPTOUT); -} - -/** return nsec3 RR algorithm */ -static int -nsec3_get_algo(struct ub_packed_rrset_key* rrset, int r) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+1) - return 0; /* malformed */ - return (int)(d->rr_data[r][2+0]); -} - -/** return if nsec3 RR has known algorithm */ -static int -nsec3_known_algo(struct ub_packed_rrset_key* rrset, int r) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+1) - return 0; /* malformed */ - switch(d->rr_data[r][2+0]) { - case NSEC3_HASH_SHA1: - return 1; - } - return 0; -} - -/** return nsec3 RR iteration count */ -static size_t -nsec3_get_iter(struct ub_packed_rrset_key* rrset, int r) -{ - uint16_t i; - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+4) - return 0; /* malformed */ - memmove(&i, d->rr_data[r]+2+2, sizeof(i)); - i = ntohs(i); - return (size_t)i; -} - -/** return nsec3 RR salt */ -static int -nsec3_get_salt(struct ub_packed_rrset_key* rrset, int r, - uint8_t** salt, size_t* saltlen) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+5) { - *salt = 0; - *saltlen = 0; - return 0; /* malformed */ - } - *saltlen = (size_t)d->rr_data[r][2+4]; - if(d->rr_len[r] < 2+5+(size_t)*saltlen) { - *salt = 0; - *saltlen = 0; - return 0; /* malformed */ - } - *salt = d->rr_data[r]+2+5; - return 1; -} - -int nsec3_get_params(struct ub_packed_rrset_key* rrset, int r, - int* algo, size_t* iter, uint8_t** salt, size_t* saltlen) -{ - if(!nsec3_known_algo(rrset, r) || nsec3_unknown_flags(rrset, r)) - return 0; - if(!nsec3_get_salt(rrset, r, salt, saltlen)) - return 0; - *algo = nsec3_get_algo(rrset, r); - *iter = nsec3_get_iter(rrset, r); - return 1; -} - -int -nsec3_get_nextowner(struct ub_packed_rrset_key* rrset, int r, - uint8_t** next, size_t* nextlen) -{ - size_t saltlen; - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - if(d->rr_len[r] < 2+5) { - *next = 0; - *nextlen = 0; - return 0; /* malformed */ - } - saltlen = (size_t)d->rr_data[r][2+4]; - if(d->rr_len[r] < 2+5+saltlen+1) { - *next = 0; - *nextlen = 0; - return 0; /* malformed */ - } - *nextlen = (size_t)d->rr_data[r][2+5+saltlen]; - if(d->rr_len[r] < 2+5+saltlen+1+*nextlen) { - *next = 0; - *nextlen = 0; - return 0; /* malformed */ - } - *next = d->rr_data[r]+2+5+saltlen+1; - return 1; -} - -size_t nsec3_hash_to_b32(uint8_t* hash, size_t hashlen, uint8_t* zone, - size_t zonelen, uint8_t* buf, size_t max) -{ - /* write b32 of name, leave one for length */ - int ret; - if(max < hashlen*2+1) /* quick approx of b32, as if hexb16 */ - return 0; - ret = sldns_b32_ntop_extended_hex(hash, hashlen, (char*)buf+1, max-1); - if(ret < 1) - return 0; - buf[0] = (uint8_t)ret; /* length of b32 label */ - ret++; - if(max - ret < zonelen) - return 0; - memmove(buf+ret, zone, zonelen); - return zonelen+(size_t)ret; -} - -size_t nsec3_get_nextowner_b32(struct ub_packed_rrset_key* rrset, int r, - uint8_t* buf, size_t max) -{ - uint8_t* nm, *zone; - size_t nmlen, zonelen; - if(!nsec3_get_nextowner(rrset, r, &nm, &nmlen)) - return 0; - /* append zone name; the owner name must be .zone */ - zone = rrset->rk.dname; - zonelen = rrset->rk.dname_len; - dname_remove_label(&zone, &zonelen); - return nsec3_hash_to_b32(nm, nmlen, zone, zonelen, buf, max); -} - -int -nsec3_has_type(struct ub_packed_rrset_key* rrset, int r, uint16_t type) -{ - uint8_t* bitmap; - size_t bitlen, skiplen; - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - log_assert(d && r < (int)d->count); - skiplen = 2+4; - /* skip salt */ - if(d->rr_len[r] < skiplen+1) - return 0; /* malformed, too short */ - skiplen += 1+(size_t)d->rr_data[r][skiplen]; - /* skip next hashed owner */ - if(d->rr_len[r] < skiplen+1) - return 0; /* malformed, too short */ - skiplen += 1+(size_t)d->rr_data[r][skiplen]; - if(d->rr_len[r] < skiplen) - return 0; /* malformed, too short */ - bitlen = d->rr_len[r] - skiplen; - bitmap = d->rr_data[r]+skiplen; - return nsecbitmap_has_type_rdata(bitmap, bitlen, type); -} - -/** - * Iterate through NSEC3 list, per RR - * This routine gives the next RR in the list (or sets rrset null). - * Usage: - * - * size_t rrsetnum; - * int rrnum; - * struct ub_packed_rrset_key* rrset; - * for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; - * rrset=filter_next(filter, &rrsetnum, &rrnum)) - * do_stuff; - * - * Also filters out - * o unknown flag NSEC3s - * o unknown algorithm NSEC3s. - * @param filter: nsec3 filter structure. - * @param rrsetnum: in/out rrset number to look at. - * @param rrnum: in/out rr number in rrset to look at. - * @returns ptr to the next rrset (or NULL at end). - */ -static struct ub_packed_rrset_key* -filter_next(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum) -{ - size_t i; - int r; - uint8_t* nm; - size_t nmlen; - if(!filter->zone) /* empty list */ - return NULL; - for(i=*rrsetnum; inum; i++) { - /* see if RRset qualifies */ - if(ntohs(filter->list[i]->rk.type) != LDNS_RR_TYPE_NSEC3 || - ntohs(filter->list[i]->rk.rrset_class) != - filter->fclass) - continue; - /* check RRset zone */ - nm = filter->list[i]->rk.dname; - nmlen = filter->list[i]->rk.dname_len; - dname_remove_label(&nm, &nmlen); - if(query_dname_compare(nm, filter->zone) != 0) - continue; - if(i == *rrsetnum) - r = (*rrnum) + 1; /* continue at next RR */ - else r = 0; /* new RRset start at first RR */ - for(; r < (int)rrset_get_count(filter->list[i]); r++) { - /* skip unknown flags, algo */ - if(nsec3_unknown_flags(filter->list[i], r) || - !nsec3_known_algo(filter->list[i], r)) - continue; - /* this one is a good target */ - *rrsetnum = i; - *rrnum = r; - return filter->list[i]; - } - } - return NULL; -} - -/** - * Start iterating over NSEC3 records. - * @param filter: the filter structure, must have been filter_init-ed. - * @param rrsetnum: can be undefined on call, initialised. - * @param rrnum: can be undefined on call, initialised. - * @return first rrset of an NSEC3, together with rrnum this points to - * the first RR to examine. Is NULL on empty list. - */ -static struct ub_packed_rrset_key* -filter_first(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum) -{ - *rrsetnum = 0; - *rrnum = -1; - return filter_next(filter, rrsetnum, rrnum); -} - -/** see if at least one RR is known (flags, algo) */ -static int -nsec3_rrset_has_known(struct ub_packed_rrset_key* s) -{ - int r; - for(r=0; r < (int)rrset_get_count(s); r++) { - if(!nsec3_unknown_flags(s, r) && nsec3_known_algo(s, r)) - return 1; - } - return 0; -} - -/** - * Initialize the filter structure. - * Finds the zone by looking at available NSEC3 records and best match. - * (skips the unknown flag and unknown algo NSEC3s). - * - * @param filter: nsec3 filter structure. - * @param list: list of rrsets, an array of them. - * @param num: number of rrsets in list. - * @param qinfo: - * query name to match a zone for. - * query type (if DS a higher zone must be chosen) - * qclass, to filter NSEC3s with. - */ -static void -filter_init(struct nsec3_filter* filter, struct ub_packed_rrset_key** list, - size_t num, struct query_info* qinfo) -{ - size_t i; - uint8_t* nm; - size_t nmlen; - filter->zone = NULL; - filter->zone_len = 0; - filter->list = list; - filter->num = num; - filter->fclass = qinfo->qclass; - for(i=0; irk.type) != LDNS_RR_TYPE_NSEC3 || - ntohs(list[i]->rk.rrset_class) != qinfo->qclass) - continue; - /* skip unknown flags, algo */ - if(!nsec3_rrset_has_known(list[i])) - continue; - - /* since NSEC3s are base32.zonename, we can find the zone - * name by stripping off the first label of the record */ - nm = list[i]->rk.dname; - nmlen = list[i]->rk.dname_len; - dname_remove_label(&nm, &nmlen); - /* if we find a domain that can prove about the qname, - * and if this domain is closer to the qname */ - if(dname_subdomain_c(qinfo->qname, nm) && (!filter->zone || - dname_subdomain_c(nm, filter->zone))) { - /* for a type DS do not accept a zone equal to qname*/ - if(qinfo->qtype == LDNS_RR_TYPE_DS && - query_dname_compare(qinfo->qname, nm) == 0 && - !dname_is_root(qinfo->qname)) - continue; - filter->zone = nm; - filter->zone_len = nmlen; - } - } -} - -/** - * Find max iteration count using config settings and key size - * @param ve: validator environment with iteration count config settings. - * @param bits: key size - * @return max iteration count - */ -static size_t -get_max_iter(struct val_env* ve, size_t bits) -{ - int i; - log_assert(ve->nsec3_keyiter_count > 0); - /* round up to nearest config keysize, linear search, keep it small */ - for(i=0; insec3_keyiter_count; i++) { - if(bits <= ve->nsec3_keysize[i]) - return ve->nsec3_maxiter[i]; - } - /* else, use value for biggest key */ - return ve->nsec3_maxiter[ve->nsec3_keyiter_count-1]; -} - -/** - * Determine if any of the NSEC3 rrs iteration count is too high, from key. - * @param ve: validator environment with iteration count config settings. - * @param filter: what NSEC3s to loop over. - * @param kkey: key entry used for verification; used for iteration counts. - * @return 1 if some nsec3s are above the max iteration count. - */ -static int -nsec3_iteration_count_high(struct val_env* ve, struct nsec3_filter* filter, - struct key_entry_key* kkey) -{ - size_t rrsetnum; - int rrnum; - struct ub_packed_rrset_key* rrset; - /* first determine the max number of iterations */ - size_t bits = key_entry_keysize(kkey); - size_t max_iter = get_max_iter(ve, bits); - verbose(VERB_ALGO, "nsec3: keysize %d bits, max iterations %d", - (int)bits, (int)max_iter); - - for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; - rrset=filter_next(filter, &rrsetnum, &rrnum)) { - if(nsec3_get_iter(rrset, rrnum) > max_iter) - return 1; - } - return 0; -} - -/* nsec3_cache_compare for rbtree */ -int -nsec3_hash_cmp(const void* c1, const void* c2) -{ - struct nsec3_cached_hash* h1 = (struct nsec3_cached_hash*)c1; - struct nsec3_cached_hash* h2 = (struct nsec3_cached_hash*)c2; - uint8_t* s1, *s2; - size_t s1len, s2len; - int c = query_dname_compare(h1->dname, h2->dname); - if(c != 0) - return c; - /* compare parameters */ - /* if both malformed, its equal, robustness */ - if(nsec3_get_algo(h1->nsec3, h1->rr) != - nsec3_get_algo(h2->nsec3, h2->rr)) { - if(nsec3_get_algo(h1->nsec3, h1->rr) < - nsec3_get_algo(h2->nsec3, h2->rr)) - return -1; - return 1; - } - if(nsec3_get_iter(h1->nsec3, h1->rr) != - nsec3_get_iter(h2->nsec3, h2->rr)) { - if(nsec3_get_iter(h1->nsec3, h1->rr) < - nsec3_get_iter(h2->nsec3, h2->rr)) - return -1; - return 1; - } - (void)nsec3_get_salt(h1->nsec3, h1->rr, &s1, &s1len); - (void)nsec3_get_salt(h2->nsec3, h2->rr, &s2, &s2len); - if(s1len == 0 && s2len == 0) - return 0; - if(!s1) return -1; - if(!s2) return 1; - if(s1len != s2len) { - if(s1len < s2len) - return -1; - return 1; - } - return memcmp(s1, s2, s1len); -} - -size_t -nsec3_get_hashed(sldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo, - size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max) -{ - size_t i, hash_len; - /* prepare buffer for first iteration */ - sldns_buffer_clear(buf); - sldns_buffer_write(buf, nm, nmlen); - query_dname_tolower(sldns_buffer_begin(buf)); - sldns_buffer_write(buf, salt, saltlen); - sldns_buffer_flip(buf); - hash_len = nsec3_hash_algo_size_supported(algo); - if(hash_len == 0) { - log_err("nsec3 hash of unknown algo %d", algo); - return 0; - } - if(hash_len > max) - return 0; - if(!secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf), - sldns_buffer_limit(buf), (unsigned char*)res)) - return 0; - for(i=0; insec3, c->rr); - size_t iter = nsec3_get_iter(c->nsec3, c->rr); - uint8_t* salt; - size_t saltlen, i; - if(!nsec3_get_salt(c->nsec3, c->rr, &salt, &saltlen)) - return -1; - /* prepare buffer for first iteration */ - sldns_buffer_clear(buf); - sldns_buffer_write(buf, c->dname, c->dname_len); - query_dname_tolower(sldns_buffer_begin(buf)); - sldns_buffer_write(buf, salt, saltlen); - sldns_buffer_flip(buf); - c->hash_len = nsec3_hash_algo_size_supported(algo); - if(c->hash_len == 0) { - log_err("nsec3 hash of unknown algo %d", algo); - return -1; - } - c->hash = (uint8_t*)regional_alloc(region, c->hash_len); - if(!c->hash) - return 0; - (void)secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf), - sldns_buffer_limit(buf), (unsigned char*)c->hash); - for(i=0; ihash, c->hash_len); - sldns_buffer_write(buf, salt, saltlen); - sldns_buffer_flip(buf); - (void)secalgo_nsec3_hash(algo, - (unsigned char*)sldns_buffer_begin(buf), - sldns_buffer_limit(buf), (unsigned char*)c->hash); - } - return 1; -} - -/** perform b32 encoding of hash */ -static int -nsec3_calc_b32(struct regional* region, sldns_buffer* buf, - struct nsec3_cached_hash* c) -{ - int r; - sldns_buffer_clear(buf); - r = sldns_b32_ntop_extended_hex(c->hash, c->hash_len, - (char*)sldns_buffer_begin(buf), sldns_buffer_limit(buf)); - if(r < 1) { - log_err("b32_ntop_extended_hex: error in encoding: %d", r); - return 0; - } - c->b32_len = (size_t)r; - c->b32 = regional_alloc_init(region, sldns_buffer_begin(buf), - c->b32_len); - if(!c->b32) - return 0; - return 1; -} - -int -nsec3_hash_name(rbtree_type* table, struct regional* region, sldns_buffer* buf, - struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname, - size_t dname_len, struct nsec3_cached_hash** hash) -{ - struct nsec3_cached_hash* c; - struct nsec3_cached_hash looki; -#ifdef UNBOUND_DEBUG - rbnode_type* n; -#endif - int r; - looki.node.key = &looki; - looki.nsec3 = nsec3; - looki.rr = rr; - looki.dname = dname; - looki.dname_len = dname_len; - /* lookup first in cache */ - c = (struct nsec3_cached_hash*)rbtree_search(table, &looki); - if(c) { - *hash = c; - return 1; - } - /* create a new entry */ - c = (struct nsec3_cached_hash*)regional_alloc(region, sizeof(*c)); - if(!c) return 0; - c->node.key = c; - c->nsec3 = nsec3; - c->rr = rr; - c->dname = dname; - c->dname_len = dname_len; - r = nsec3_calc_hash(region, buf, c); - if(r != 1) - return r; - r = nsec3_calc_b32(region, buf, c); - if(r != 1) - return r; -#ifdef UNBOUND_DEBUG - n = -#else - (void) -#endif - rbtree_insert(table, &c->node); - log_assert(n); /* cannot be duplicate, just did lookup */ - *hash = c; - return 1; -} - -/** - * compare a label lowercased - */ -static int -label_compare_lower(uint8_t* lab1, uint8_t* lab2, size_t lablen) -{ - size_t i; - for(i=0; irk.dname; - /* compare, does hash of name based on params in this NSEC3 - * match the owner name of this NSEC3? - * name must be: base32 . zone name - * so; first label must not be root label (not zero length), - * and match the b32 encoded hash length, - * and the label content match the b32 encoded hash - * and the rest must be the zone name. - */ - if(hash->b32_len != 0 && (size_t)nm[0] == hash->b32_len && - label_compare_lower(nm+1, hash->b32, hash->b32_len) == 0 && - query_dname_compare(nm+(size_t)nm[0]+1, flt->zone) == 0) { - return 1; - } - return 0; -} - -/** - * Find matching NSEC3 - * Find the NSEC3Record that matches a hash of a name. - * @param env: module environment with temporary region and buffer. - * @param flt: the NSEC3 RR filter, contains zone name and RRs. - * @param ct: cached hashes table. - * @param nm: name to look for. - * @param nmlen: length of name. - * @param rrset: nsec3 that matches is returned here. - * @param rr: rr number in nsec3 rrset that matches. - * @return true if a matching NSEC3 is found, false if not. - */ -static int -find_matching_nsec3(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, uint8_t* nm, size_t nmlen, - struct ub_packed_rrset_key** rrset, int* rr) -{ - size_t i_rs; - int i_rr; - struct ub_packed_rrset_key* s; - struct nsec3_cached_hash* hash = NULL; - int r; - - /* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */ - for(s=filter_first(flt, &i_rs, &i_rr); s; - s=filter_next(flt, &i_rs, &i_rr)) { - /* get name hashed for this NSEC3 RR */ - r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer, - s, i_rr, nm, nmlen, &hash); - if(r == 0) { - log_err("nsec3: malloc failure"); - break; /* alloc failure */ - } else if(r != 1) - continue; /* malformed NSEC3 */ - else if(nsec3_hash_matches_owner(flt, hash, s)) { - *rrset = s; /* rrset with this name */ - *rr = i_rr; /* matches hash with these parameters */ - return 1; - } - } - *rrset = NULL; - *rr = 0; - return 0; -} - -int -nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash, - struct ub_packed_rrset_key* rrset, int rr, sldns_buffer* buf) -{ - uint8_t* next, *owner; - size_t nextlen; - int len; - if(!nsec3_get_nextowner(rrset, rr, &next, &nextlen)) - return 0; /* malformed RR proves nothing */ - - /* check the owner name is a hashed value . apex - * base32 encoded values must have equal length. - * hash_value and next hash value must have equal length. */ - if(nextlen != hash->hash_len || hash->hash_len==0||hash->b32_len==0|| - (size_t)*rrset->rk.dname != hash->b32_len || - query_dname_compare(rrset->rk.dname+1+ - (size_t)*rrset->rk.dname, zone) != 0) - return 0; /* bad lengths or owner name */ - - /* This is the "normal case: owner < next and owner < hash < next */ - if(label_compare_lower(rrset->rk.dname+1, hash->b32, - hash->b32_len) < 0 && - memcmp(hash->hash, next, nextlen) < 0) - return 1; - - /* convert owner name from text to binary */ - sldns_buffer_clear(buf); - owner = sldns_buffer_begin(buf); - len = sldns_b32_pton_extended_hex((char*)rrset->rk.dname+1, - hash->b32_len, owner, sldns_buffer_limit(buf)); - if(len<1) - return 0; /* bad owner name in some way */ - if((size_t)len != hash->hash_len || (size_t)len != nextlen) - return 0; /* wrong length */ - - /* this is the end of zone case: next <= owner && - * (hash > owner || hash < next) - * this also covers the only-apex case of next==owner. - */ - if(memcmp(next, owner, nextlen) <= 0 && - ( memcmp(hash->hash, owner, nextlen) > 0 || - memcmp(hash->hash, next, nextlen) < 0)) { - return 1; - } - return 0; -} - -/** - * findCoveringNSEC3 - * Given a name, find a covering NSEC3 from among a list of NSEC3s. - * - * @param env: module environment with temporary region and buffer. - * @param flt: the NSEC3 RR filter, contains zone name and RRs. - * @param ct: cached hashes table. - * @param nm: name to check if covered. - * @param nmlen: length of name. - * @param rrset: covering NSEC3 rrset is returned here. - * @param rr: rr of cover is returned here. - * @return true if a covering NSEC3 is found, false if not. - */ -static int -find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, uint8_t* nm, size_t nmlen, - struct ub_packed_rrset_key** rrset, int* rr) -{ - size_t i_rs; - int i_rr; - struct ub_packed_rrset_key* s; - struct nsec3_cached_hash* hash = NULL; - int r; - - /* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */ - for(s=filter_first(flt, &i_rs, &i_rr); s; - s=filter_next(flt, &i_rs, &i_rr)) { - /* get name hashed for this NSEC3 RR */ - r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer, - s, i_rr, nm, nmlen, &hash); - if(r == 0) { - log_err("nsec3: malloc failure"); - break; /* alloc failure */ - } else if(r != 1) - continue; /* malformed NSEC3 */ - else if(nsec3_covers(flt->zone, hash, s, i_rr, - env->scratch_buffer)) { - *rrset = s; /* rrset with this name */ - *rr = i_rr; /* covers hash with these parameters */ - return 1; - } - } - *rrset = NULL; - *rr = 0; - return 0; -} - -/** - * findClosestEncloser - * Given a name and a list of NSEC3s, find the candidate closest encloser. - * This will be the first ancestor of 'name' (including itself) to have a - * matching NSEC3 RR. - * @param env: module environment with temporary region and buffer. - * @param flt: the NSEC3 RR filter, contains zone name and RRs. - * @param ct: cached hashes table. - * @param qinfo: query that is verified for. - * @param ce: closest encloser information is returned in here. - * @return true if a closest encloser candidate is found, false if not. - */ -static int -nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, struct query_info* qinfo, struct ce_response* ce) -{ - uint8_t* nm = qinfo->qname; - size_t nmlen = qinfo->qname_len; - - /* This scans from longest name to shortest, so the first match - * we find is the only viable candidate. */ - - /* (David:) FIXME: modify so that the NSEC3 matching the zone apex need - * not be present. (Mark Andrews idea). - * (Wouter:) But make sure you check for DNAME bit in zone apex, - * if the NSEC3 you find is the only NSEC3 in the zone, then this - * may be the case. */ - - while(dname_subdomain_c(nm, flt->zone)) { - if(find_matching_nsec3(env, flt, ct, nm, nmlen, - &ce->ce_rrset, &ce->ce_rr)) { - ce->ce = nm; - ce->ce_len = nmlen; - return 1; - } - dname_remove_label(&nm, &nmlen); - } - return 0; -} - -/** - * Given a qname and its proven closest encloser, calculate the "next - * closest" name. Basically, this is the name that is one label longer than - * the closest encloser that is still a subdomain of qname. - * - * @param qname: query name. - * @param qnamelen: length of qname. - * @param ce: closest encloser - * @param nm: result name. - * @param nmlen: length of nm. - */ -static void -next_closer(uint8_t* qname, size_t qnamelen, uint8_t* ce, - uint8_t** nm, size_t* nmlen) -{ - int strip = dname_count_labels(qname) - dname_count_labels(ce) -1; - *nm = qname; - *nmlen = qnamelen; - if(strip>0) - dname_remove_labels(nm, nmlen, strip); -} - -/** - * proveClosestEncloser - * Given a List of nsec3 RRs, find and prove the closest encloser to qname. - * @param env: module environment with temporary region and buffer. - * @param flt: the NSEC3 RR filter, contains zone name and RRs. - * @param ct: cached hashes table. - * @param qinfo: query that is verified for. - * @param prove_does_not_exist: If true, then if the closest encloser - * turns out to be qname, then null is returned. - * If set true, and the return value is true, then you can be - * certain that the ce.nc_rrset and ce.nc_rr are set properly. - * @param ce: closest encloser information is returned in here. - * @return bogus if no closest encloser could be proven. - * secure if a closest encloser could be proven, ce is set. - * insecure if the closest-encloser candidate turns out to prove - * that an insecure delegation exists above the qname. - */ -static enum sec_status -nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, struct query_info* qinfo, int prove_does_not_exist, - struct ce_response* ce) -{ - uint8_t* nc; - size_t nc_len; - /* robust: clean out ce, in case it gets abused later */ - memset(ce, 0, sizeof(*ce)); - - if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) { - verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could " - "not find a candidate for the closest encloser."); - return sec_status_bogus; - } - log_nametypeclass(VERB_ALGO, "ce candidate", ce->ce, 0, 0); - - if(query_dname_compare(ce->ce, qinfo->qname) == 0) { - if(prove_does_not_exist) { - verbose(VERB_ALGO, "nsec3 proveClosestEncloser: " - "proved that qname existed, bad"); - return sec_status_bogus; - } - /* otherwise, we need to nothing else to prove that qname - * is its own closest encloser. */ - return sec_status_secure; - } - - /* If the closest encloser is actually a delegation, then the - * response should have been a referral. If it is a DNAME, then - * it should have been a DNAME response. */ - if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_NS) && - !nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_SOA)) { - if(!nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DS)) { - verbose(VERB_ALGO, "nsec3 proveClosestEncloser: " - "closest encloser is insecure delegation"); - return sec_status_insecure; - } - verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest " - "encloser was a delegation, bad"); - return sec_status_bogus; - } - if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DNAME)) { - verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest " - "encloser was a DNAME, bad"); - return sec_status_bogus; - } - - /* Otherwise, we need to show that the next closer name is covered. */ - next_closer(qinfo->qname, qinfo->qname_len, ce->ce, &nc, &nc_len); - if(!find_covering_nsec3(env, flt, ct, nc, nc_len, - &ce->nc_rrset, &ce->nc_rr)) { - verbose(VERB_ALGO, "nsec3: Could not find proof that the " - "candidate encloser was the closest encloser"); - return sec_status_bogus; - } - return sec_status_secure; -} - -/** allocate a wildcard for the closest encloser */ -static uint8_t* -nsec3_ce_wildcard(struct regional* region, uint8_t* ce, size_t celen, - size_t* len) -{ - uint8_t* nm; - if(celen > LDNS_MAX_DOMAINLEN - 2) - return 0; /* too long */ - nm = (uint8_t*)regional_alloc(region, celen+2); - if(!nm) { - log_err("nsec3 wildcard: out of memory"); - return 0; /* alloc failure */ - } - nm[0] = 1; - nm[1] = (uint8_t)'*'; /* wildcard label */ - memmove(nm+2, ce, celen); - *len = celen+2; - return nm; -} - -/** Do the name error proof */ -static enum sec_status -nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, struct query_info* qinfo) -{ - struct ce_response ce; - uint8_t* wc; - size_t wclen; - struct ub_packed_rrset_key* wc_rrset; - int wc_rr; - enum sec_status sec; - - /* First locate and prove the closest encloser to qname. We will - * use the variant that fails if the closest encloser turns out - * to be qname. */ - sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce); - if(sec != sec_status_secure) { - if(sec == sec_status_bogus) - verbose(VERB_ALGO, "nsec3 nameerror proof: failed " - "to prove a closest encloser"); - else verbose(VERB_ALGO, "nsec3 nameerror proof: closest " - "nsec3 is an insecure delegation"); - return sec; - } - log_nametypeclass(VERB_ALGO, "nsec3 nameerror: proven ce=", ce.ce,0,0); - - /* At this point, we know that qname does not exist. Now we need - * to prove that the wildcard does not exist. */ - log_assert(ce.ce); - wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen); - if(!wc || !find_covering_nsec3(env, flt, ct, wc, wclen, - &wc_rrset, &wc_rr)) { - verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove " - "that the applicable wildcard did not exist."); - return sec_status_bogus; - } - - if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { - verbose(VERB_ALGO, "nsec3 nameerror proof: nc has optout"); - return sec_status_insecure; - } - return sec_status_secure; -} - -enum sec_status -nsec3_prove_nameerror(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey) -{ - rbtree_type ct; - struct nsec3_filter flt; - - if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) - return sec_status_bogus; /* no valid NSEC3s, bogus */ - rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ - filter_init(&flt, list, num, qinfo); /* init RR iterator */ - if(!flt.zone) - return sec_status_bogus; /* no RRs */ - if(nsec3_iteration_count_high(ve, &flt, kkey)) - return sec_status_insecure; /* iteration count too high */ - log_nametypeclass(VERB_ALGO, "start nsec3 nameerror proof, zone", - flt.zone, 0, 0); - return nsec3_do_prove_nameerror(env, &flt, &ct, qinfo); -} - -/* - * No code to handle qtype=NSEC3 specially. - * This existed in early drafts, but was later (-05) removed. - */ - -/** Do the nodata proof */ -static enum sec_status -nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt, - rbtree_type* ct, struct query_info* qinfo) -{ - struct ce_response ce; - uint8_t* wc; - size_t wclen; - struct ub_packed_rrset_key* rrset; - int rr; - enum sec_status sec; - - if(find_matching_nsec3(env, flt, ct, qinfo->qname, qinfo->qname_len, - &rrset, &rr)) { - /* cases 1 and 2 */ - if(nsec3_has_type(rrset, rr, qinfo->qtype)) { - verbose(VERB_ALGO, "proveNodata: Matching NSEC3 " - "proved that type existed, bogus"); - return sec_status_bogus; - } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_CNAME)) { - verbose(VERB_ALGO, "proveNodata: Matching NSEC3 " - "proved that a CNAME existed, bogus"); - return sec_status_bogus; - } - - /* - * If type DS: filter_init zone find already found a parent - * zone, so this nsec3 is from a parent zone. - * o can be not a delegation (unusual query for normal name, - * no DS anyway, but we can verify that). - * o can be a delegation (which is the usual DS check). - * o may not have the SOA bit set (only the top of the - * zone, which must have been above the name, has that). - * Except for the root; which is checked by itself. - * - * If not type DS: matching nsec3 must not be a delegation. - */ - if(qinfo->qtype == LDNS_RR_TYPE_DS && qinfo->qname_len != 1 - && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA) && - !dname_is_root(qinfo->qname)) { - verbose(VERB_ALGO, "proveNodata: apex NSEC3 " - "abused for no DS proof, bogus"); - return sec_status_bogus; - } else if(qinfo->qtype != LDNS_RR_TYPE_DS && - nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) && - !nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { - if(!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_DS)) { - verbose(VERB_ALGO, "proveNodata: matching " - "NSEC3 is insecure delegation"); - return sec_status_insecure; - } - verbose(VERB_ALGO, "proveNodata: matching " - "NSEC3 is a delegation, bogus"); - return sec_status_bogus; - } - return sec_status_secure; - } - - /* For cases 3 - 5, we need the proven closest encloser, and it - * can't match qname. Although, at this point, we know that it - * won't since we just checked that. */ - sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce); - if(sec == sec_status_bogus) { - verbose(VERB_ALGO, "proveNodata: did not match qname, " - "nor found a proven closest encloser."); - return sec_status_bogus; - } else if(sec==sec_status_insecure && qinfo->qtype!=LDNS_RR_TYPE_DS){ - verbose(VERB_ALGO, "proveNodata: closest nsec3 is insecure " - "delegation."); - return sec_status_insecure; - } - - /* Case 3: removed */ - - /* Case 4: */ - log_assert(ce.ce); - wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen); - if(wc && find_matching_nsec3(env, flt, ct, wc, wclen, &rrset, &rr)) { - /* found wildcard */ - if(nsec3_has_type(rrset, rr, qinfo->qtype)) { - verbose(VERB_ALGO, "nsec3 nodata proof: matching " - "wildcard had qtype, bogus"); - return sec_status_bogus; - } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_CNAME)) { - verbose(VERB_ALGO, "nsec3 nodata proof: matching " - "wildcard had a CNAME, bogus"); - return sec_status_bogus; - } - if(qinfo->qtype == LDNS_RR_TYPE_DS && qinfo->qname_len != 1 - && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { - verbose(VERB_ALGO, "nsec3 nodata proof: matching " - "wildcard for no DS proof has a SOA, bogus"); - return sec_status_bogus; - } else if(qinfo->qtype != LDNS_RR_TYPE_DS && - nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) && - !nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { - verbose(VERB_ALGO, "nsec3 nodata proof: matching " - "wildcard is a delegation, bogus"); - return sec_status_bogus; - } - /* everything is peachy keen, except for optout spans */ - if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { - verbose(VERB_ALGO, "nsec3 nodata proof: matching " - "wildcard is in optout range, insecure"); - return sec_status_insecure; - } - return sec_status_secure; - } - - /* Case 5: */ - /* Due to forwarders, cnames, and other collating effects, we - * can see the ordinary unsigned data from a zone beneath an - * insecure delegation under an optout here */ - if(!ce.nc_rrset) { - verbose(VERB_ALGO, "nsec3 nodata proof: no next closer nsec3"); - return sec_status_bogus; - } - - /* We need to make sure that the covering NSEC3 is opt-out. */ - log_assert(ce.nc_rrset); - if(!nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { - if(qinfo->qtype == LDNS_RR_TYPE_DS) - verbose(VERB_ALGO, "proveNodata: covering NSEC3 was not " - "opt-out in an opt-out DS NOERROR/NODATA case."); - else verbose(VERB_ALGO, "proveNodata: could not find matching " - "NSEC3, nor matching wildcard, nor optout NSEC3 " - "-- no more options, bogus."); - return sec_status_bogus; - } - /* RFC5155 section 9.2: if nc has optout then no AD flag set */ - return sec_status_insecure; -} - -enum sec_status -nsec3_prove_nodata(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey) -{ - rbtree_type ct; - struct nsec3_filter flt; - - if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) - return sec_status_bogus; /* no valid NSEC3s, bogus */ - rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ - filter_init(&flt, list, num, qinfo); /* init RR iterator */ - if(!flt.zone) - return sec_status_bogus; /* no RRs */ - if(nsec3_iteration_count_high(ve, &flt, kkey)) - return sec_status_insecure; /* iteration count too high */ - return nsec3_do_prove_nodata(env, &flt, &ct, qinfo); -} - -enum sec_status -nsec3_prove_wildcard(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc) -{ - rbtree_type ct; - struct nsec3_filter flt; - struct ce_response ce; - uint8_t* nc; - size_t nc_len; - size_t wclen; - (void)dname_count_size_labels(wc, &wclen); - - if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) - return sec_status_bogus; /* no valid NSEC3s, bogus */ - rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ - filter_init(&flt, list, num, qinfo); /* init RR iterator */ - if(!flt.zone) - return sec_status_bogus; /* no RRs */ - if(nsec3_iteration_count_high(ve, &flt, kkey)) - return sec_status_insecure; /* iteration count too high */ - - /* We know what the (purported) closest encloser is by just - * looking at the supposed generating wildcard. - * The *. has already been removed from the wc name. - */ - memset(&ce, 0, sizeof(ce)); - ce.ce = wc; - ce.ce_len = wclen; - - /* Now we still need to prove that the original data did not exist. - * Otherwise, we need to show that the next closer name is covered. */ - next_closer(qinfo->qname, qinfo->qname_len, ce.ce, &nc, &nc_len); - if(!find_covering_nsec3(env, &flt, &ct, nc, nc_len, - &ce.nc_rrset, &ce.nc_rr)) { - verbose(VERB_ALGO, "proveWildcard: did not find a covering " - "NSEC3 that covered the next closer name."); - return sec_status_bogus; - } - if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { - verbose(VERB_ALGO, "proveWildcard: NSEC3 optout"); - return sec_status_insecure; - } - return sec_status_secure; -} - -/** test if list is all secure */ -static int -list_is_secure(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus, - struct module_qstate* qstate) -{ - struct packed_rrset_data* d; - size_t i; - for(i=0; ientry.data; - if(list[i]->rk.type != htons(LDNS_RR_TYPE_NSEC3)) - continue; - if(d->security == sec_status_secure) - continue; - rrset_check_sec_status(env->rrset_cache, list[i], *env->now); - if(d->security == sec_status_secure) - continue; - d->security = val_verify_rrset_entry(env, ve, list[i], kkey, - reason, reason_bogus, LDNS_SECTION_AUTHORITY, qstate); - if(d->security != sec_status_secure) { - verbose(VERB_ALGO, "NSEC3 did not verify"); - return 0; - } - rrset_update_sec_status(env->rrset_cache, list[i], *env->now); - } - return 1; -} - -enum sec_status -nsec3_prove_nods(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, char** reason, - sldns_ede_code* reason_bogus, struct module_qstate* qstate) -{ - rbtree_type ct; - struct nsec3_filter flt; - struct ce_response ce; - struct ub_packed_rrset_key* rrset; - int rr; - log_assert(qinfo->qtype == LDNS_RR_TYPE_DS); - - if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) { - *reason = "no valid NSEC3s"; - return sec_status_bogus; /* no valid NSEC3s, bogus */ - } - if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus, qstate)) { - *reason = "not all NSEC3 records secure"; - return sec_status_bogus; /* not all NSEC3 records secure */ - } - rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ - filter_init(&flt, list, num, qinfo); /* init RR iterator */ - if(!flt.zone) { - *reason = "no NSEC3 records"; - return sec_status_bogus; /* no RRs */ - } - if(nsec3_iteration_count_high(ve, &flt, kkey)) - return sec_status_insecure; /* iteration count too high */ - - /* Look for a matching NSEC3 to qname -- this is the normal - * NODATA case. */ - if(find_matching_nsec3(env, &flt, &ct, qinfo->qname, qinfo->qname_len, - &rrset, &rr)) { - /* If the matching NSEC3 has the SOA bit set, it is from - * the wrong zone (the child instead of the parent). If - * it has the DS bit set, then we were lied to. */ - if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA) && - qinfo->qname_len != 1) { - verbose(VERB_ALGO, "nsec3 provenods: NSEC3 is from" - " child zone, bogus"); - *reason = "NSEC3 from child zone"; - return sec_status_bogus; - } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_DS)) { - verbose(VERB_ALGO, "nsec3 provenods: NSEC3 has qtype" - " DS, bogus"); - *reason = "NSEC3 has DS in bitmap"; - return sec_status_bogus; - } - /* If the NSEC3 RR doesn't have the NS bit set, then - * this wasn't a delegation point. */ - if(!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS)) - return sec_status_indeterminate; - /* Otherwise, this proves no DS. */ - return sec_status_secure; - } - - /* Otherwise, we are probably in the opt-out case. */ - if(nsec3_prove_closest_encloser(env, &flt, &ct, qinfo, 1, &ce) - != sec_status_secure) { - /* an insecure delegation *above* the qname does not prove - * anything about this qname exactly, and bogus is bogus */ - verbose(VERB_ALGO, "nsec3 provenods: did not match qname, " - "nor found a proven closest encloser."); - *reason = "no NSEC3 closest encloser"; - return sec_status_bogus; - } - - /* robust extra check */ - if(!ce.nc_rrset) { - verbose(VERB_ALGO, "nsec3 nods proof: no next closer nsec3"); - *reason = "no NSEC3 next closer"; - return sec_status_bogus; - } - - /* we had the closest encloser proof, then we need to check that the - * covering NSEC3 was opt-out -- the proveClosestEncloser step already - * checked to see if the closest encloser was a delegation or DNAME. - */ - log_assert(ce.nc_rrset); - if(!nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { - verbose(VERB_ALGO, "nsec3 provenods: covering NSEC3 was not " - "opt-out in an opt-out DS NOERROR/NODATA case."); - *reason = "covering NSEC3 was not opt-out in an opt-out " - "DS NOERROR/NODATA case"; - return sec_status_bogus; - } - /* RFC5155 section 9.2: if nc has optout then no AD flag set */ - return sec_status_insecure; -} - -enum sec_status -nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, int* nodata) -{ - enum sec_status sec, secnx; - rbtree_type ct; - struct nsec3_filter flt; - *nodata = 0; - - if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) - return sec_status_bogus; /* no valid NSEC3s, bogus */ - rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ - filter_init(&flt, list, num, qinfo); /* init RR iterator */ - if(!flt.zone) - return sec_status_bogus; /* no RRs */ - if(nsec3_iteration_count_high(ve, &flt, kkey)) - return sec_status_insecure; /* iteration count too high */ - - /* try nxdomain and nodata after another, while keeping the - * hash cache intact */ - - secnx = nsec3_do_prove_nameerror(env, &flt, &ct, qinfo); - if(secnx==sec_status_secure) - return sec_status_secure; - sec = nsec3_do_prove_nodata(env, &flt, &ct, qinfo); - if(sec==sec_status_secure) { - *nodata = 1; - } else if(sec == sec_status_insecure) { - *nodata = 1; - } else if(secnx == sec_status_insecure) { - sec = sec_status_insecure; - } - return sec; -} diff --git a/crates/libunbound-sys/unbound/validator/val_nsec3.h b/crates/libunbound-sys/unbound/validator/val_nsec3.h deleted file mode 100644 index 7676fc8b..00000000 --- a/crates/libunbound-sys/unbound/validator/val_nsec3.h +++ /dev/null @@ -1,385 +0,0 @@ -/* - * validator/val_nsec3.h - validator NSEC3 denial of existence functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with NSEC3 checking, the different NSEC3 proofs - * for denial of existence, and proofs for presence of types. - * - * NSEC3 - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hash Alg. | Flags | Iterations | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Salt Length | Salt / - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hash Length | Next Hashed Owner Name / - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * / Type Bit Maps / - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * NSEC3PARAM - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Hash Alg. | Flags | Iterations | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Salt Length | Salt / - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - */ - -#ifndef VALIDATOR_VAL_NSEC3_H -#define VALIDATOR_VAL_NSEC3_H -#include "util/rbtree.h" -#include "util/data/packed_rrset.h" -#include "sldns/rrdef.h" -struct val_env; -struct regional; -struct module_env; -struct module_qstate; -struct ub_packed_rrset_key; -struct reply_info; -struct query_info; -struct key_entry_key; -struct sldns_buffer; - -/** - * 0 1 2 3 4 5 6 7 - * +-+-+-+-+-+-+-+-+ - * | |O| - * +-+-+-+-+-+-+-+-+ - * The OPT-OUT bit in the NSEC3 flags field. - * If enabled, there can be zero or more unsigned delegations in the span. - * If disabled, there are zero unsigned delegations in the span. - */ -#define NSEC3_OPTOUT 0x01 -/** - * The unknown flags in the NSEC3 flags field. - * They must be zero, or the NSEC3 is ignored. - */ -#define NSEC3_UNKNOWN_FLAGS 0xFE - -/** The SHA1 hash algorithm for NSEC3 */ -#define NSEC3_HASH_SHA1 0x01 - -/** - * Determine if the set of NSEC3 records provided with a response prove NAME - * ERROR. This means that the NSEC3s prove a) the closest encloser exists, - * b) the direct child of the closest encloser towards qname doesn't exist, - * and c) *.closest encloser does not exist. - * - * @param env: module environment with temporary region and buffer. - * @param ve: validator environment, with iteration count settings. - * @param list: array of RRsets, some of which are NSEC3s. - * @param num: number of RRsets in the array to examine. - * @param qinfo: query that is verified for. - * @param kkey: key entry that signed the NSEC3s. - * @return: - * sec_status SECURE of the Name Error is proven by the NSEC3 RRs, - * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. - */ -enum sec_status -nsec3_prove_nameerror(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey); - -/** - * Determine if the NSEC3s provided in a response prove the NOERROR/NODATA - * status. There are a number of different variants to this: - * - * 1) Normal NODATA -- qname is matched to an NSEC3 record, type is not - * present. - * - * 2) ENT NODATA -- because there must be NSEC3 record for - * empty-non-terminals, this is the same as #1. - * - * 3) NSEC3 ownername NODATA -- qname matched an existing, lone NSEC3 - * ownername, but qtype was not NSEC3. NOTE: as of nsec-05, this case no - * longer exists. - * - * 4) Wildcard NODATA -- A wildcard matched the name, but not the type. - * - * 5) Opt-In DS NODATA -- the qname is covered by an opt-in span and qtype == - * DS. (or maybe some future record with the same parent-side-only property) - * - * @param env: module environment with temporary region and buffer. - * @param ve: validator environment, with iteration count settings. - * @param list: array of RRsets, some of which are NSEC3s. - * @param num: number of RRsets in the array to examine. - * @param qinfo: query that is verified for. - * @param kkey: key entry that signed the NSEC3s. - * @return: - * sec_status SECURE of the proposition is proven by the NSEC3 RRs, - * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. - */ -enum sec_status -nsec3_prove_nodata(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey); - - -/** - * Prove that a positive wildcard match was appropriate (no direct match - * RRset). - * - * @param env: module environment with temporary region and buffer. - * @param ve: validator environment, with iteration count settings. - * @param list: array of RRsets, some of which are NSEC3s. - * @param num: number of RRsets in the array to examine. - * @param qinfo: query that is verified for. - * @param kkey: key entry that signed the NSEC3s. - * @param wc: The purported wildcard that matched. This is the wildcard name - * as *.wildcard.name., with the *. label already removed. - * @return: - * sec_status SECURE of the proposition is proven by the NSEC3 RRs, - * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. - */ -enum sec_status -nsec3_prove_wildcard(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc); - -/** - * Prove that a DS response either had no DS, or wasn't a delegation point. - * - * Fundamentally there are two cases here: normal NODATA and Opt-In NODATA. - * - * @param env: module environment with temporary region and buffer. - * @param ve: validator environment, with iteration count settings. - * @param list: array of RRsets, some of which are NSEC3s. - * @param num: number of RRsets in the array to examine. - * @param qinfo: query that is verified for. - * @param kkey: key entry that signed the NSEC3s. - * @param reason: string for bogus result. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param qstate: qstate with region. - * @return: - * sec_status SECURE of the proposition is proven by the NSEC3 RRs, - * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. - * or if there was no DS in an insecure (i.e., opt-in) way, - * INDETERMINATE if it was clear that this wasn't a delegation point. - */ -enum sec_status -nsec3_prove_nods(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, char** reason, - sldns_ede_code* reason_bogus, struct module_qstate* qstate); - -/** - * Prove NXDOMAIN or NODATA. - * - * @param env: module environment with temporary region and buffer. - * @param ve: validator environment, with iteration count settings. - * @param list: array of RRsets, some of which are NSEC3s. - * @param num: number of RRsets in the array to examine. - * @param qinfo: query that is verified for. - * @param kkey: key entry that signed the NSEC3s. - * @param nodata: if return value is secure, this indicates if nodata or - * nxdomain was proven. - * @return: - * sec_status SECURE of the proposition is proven by the NSEC3 RRs, - * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. - */ -enum sec_status -nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key** list, size_t num, - struct query_info* qinfo, struct key_entry_key* kkey, int* nodata); - -/** - * The NSEC3 hash result storage. - * Consists of an rbtree, with these nodes in it. - * The nodes detail how a set of parameters (from nsec3 rr) plus - * a dname result in a hash. - */ -struct nsec3_cached_hash { - /** rbtree node, key is this structure */ - rbnode_type node; - /** where are the parameters for conversion, in this rrset data */ - struct ub_packed_rrset_key* nsec3; - /** where are the parameters for conversion, this RR number in data */ - int rr; - /** the name to convert */ - uint8_t* dname; - /** length of the dname */ - size_t dname_len; - /** the hash result (not base32 encoded) */ - uint8_t* hash; - /** length of hash in bytes */ - size_t hash_len; - /** the hash result in base32 encoding */ - uint8_t* b32; - /** length of base32 encoding (as a label) */ - size_t b32_len; -}; - -/** - * Rbtree for hash cache comparison function. - * @param c1: key 1. - * @param c2: key 2. - * @return: comparison code, -1, 0, 1, of the keys. - */ -int nsec3_hash_cmp(const void* c1, const void* c2); - -/** - * Obtain the hash of an owner name. - * Used internally by the nsec3 proof functions in this file. - * published to enable unit testing of hash algorithms and cache. - * - * @param table: the cache table. Must be initialised at start. - * @param region: scratch region to use for allocation. - * This region holds the tree, if you wipe the region, reinit the tree. - * @param buf: temporary buffer. - * @param nsec3: the rrset with parameters - * @param rr: rr number from d that has the NSEC3 parameters to hash to. - * @param dname: name to hash - * This pointer is used inside the tree, assumed region-alloced. - * @param dname_len: the length of the name. - * @param hash: the hash node is returned on success. - * @return: - * 1 on success, either from cache or newly hashed hash is returned. - * 0 on a malloc failure. - * -1 if the NSEC3 rr was badly formatted (i.e. formerr). - */ -int nsec3_hash_name(rbtree_type* table, struct regional* region, - struct sldns_buffer* buf, struct ub_packed_rrset_key* nsec3, int rr, - uint8_t* dname, size_t dname_len, struct nsec3_cached_hash** hash); - -/** - * Get next owner name, converted to base32 encoding and with the - * zone name (taken from the nsec3 owner name) appended. - * @param rrset: the NSEC3 rrset. - * @param r: the rr num of the nsec3 in the rrset. - * @param buf: buffer to store name in - * @param max: size of buffer. - * @return length of name on success. 0 on failure (buffer too short or - * bad format nsec3 record). - */ -size_t nsec3_get_nextowner_b32(struct ub_packed_rrset_key* rrset, int r, - uint8_t* buf, size_t max); - -/** - * Convert hash into base32 encoding and with the - * zone name appended. - * @param hash: hashed buffer - * @param hashlen: length of hash - * @param zone: name of zone - * @param zonelen: length of zonename. - * @param buf: buffer to store name in - * @param max: size of buffer. - * @return length of name on success. 0 on failure (buffer too short or - * bad format nsec3 record). - */ -size_t nsec3_hash_to_b32(uint8_t* hash, size_t hashlen, uint8_t* zone, - size_t zonelen, uint8_t* buf, size_t max); - -/** - * Get NSEC3 parameters out of rr. - * @param rrset: the NSEC3 rrset. - * @param r: the rr num of the nsec3 in the rrset. - * @param algo: nsec3 hash algo. - * @param iter: iteration count. - * @param salt: ptr to salt inside rdata. - * @param saltlen: length of salt. - * @return 0 if bad formatted, unknown nsec3 hash algo, or unknown flags set. - */ -int nsec3_get_params(struct ub_packed_rrset_key* rrset, int r, - int* algo, size_t* iter, uint8_t** salt, size_t* saltlen); - -/** - * Get NSEC3 hashed in a buffer - * @param buf: buffer for temp use. - * @param nm: name to hash - * @param nmlen: length of nm. - * @param algo: algo to use, must be known. - * @param iter: iterations - * @param salt: salt for nsec3 - * @param saltlen: length of salt. - * @param res: result of hash stored here. - * @param max: maximum space for result. - * @return 0 on failure, otherwise bytelength stored. - */ -size_t nsec3_get_hashed(struct sldns_buffer* buf, uint8_t* nm, size_t nmlen, - int algo, size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, - size_t max); - -/** - * see if NSEC3 RR contains given type - * @param rrset: NSEC3 rrset - * @param r: RR in rrset - * @param type: in host order to check bit for. - * @return true if bit set, false if not or error. - */ -int nsec3_has_type(struct ub_packed_rrset_key* rrset, int r, uint16_t type); - -/** - * return if nsec3 RR has the optout flag - * @param rrset: NSEC3 rrset - * @param r: RR in rrset - * @return true if optout, false on error or not optout - */ -int nsec3_has_optout(struct ub_packed_rrset_key* rrset, int r); - -/** - * Return nsec3 RR next hashed owner name - * @param rrset: NSEC3 rrset - * @param r: RR in rrset - * @param next: ptr into rdata to next owner hash - * @param nextlen: length of hash. - * @return false on malformed - */ -int nsec3_get_nextowner(struct ub_packed_rrset_key* rrset, int r, - uint8_t** next, size_t* nextlen); - -/** - * nsec3Covers - * Given a hash and a candidate NSEC3Record, determine if that NSEC3Record - * covers the hash. Covers specifically means that the hash is in between - * the owner and next hashes and does not equal either. - * - * @param zone: the zone name. - * @param hash: the hash of the name - * @param rrset: the rrset of the NSEC3. - * @param rr: which rr in the rrset. - * @param buf: temporary buffer. - * @return true if covers, false if not. - */ -int nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash, - struct ub_packed_rrset_key* rrset, int rr, struct sldns_buffer* buf); - -#endif /* VALIDATOR_VAL_NSEC3_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_secalgo.c b/crates/libunbound-sys/unbound/validator/val_secalgo.c deleted file mode 100644 index 78651674..00000000 --- a/crates/libunbound-sys/unbound/validator/val_secalgo.c +++ /dev/null @@ -1,2107 +0,0 @@ -/* - * validator/val_secalgo.c - validator security algorithm functions. - * - * Copyright (c) 2012, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * These functions take raw data buffers, formatted for crypto verification, - * and do the library calls (for the crypto library in use). - */ -#include "config.h" -/* packed_rrset on top to define enum types (forced by c99 standard) */ -#include "util/data/packed_rrset.h" -#include "validator/val_secalgo.h" -#include "validator/val_nsec3.h" -#include "util/log.h" -#include "sldns/rrdef.h" -#include "sldns/keyraw.h" -#include "sldns/sbuffer.h" - -#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE) -#error "Need crypto library to do digital signature cryptography" -#endif - -/** fake DSA support for unit tests */ -int fake_dsa = 0; -/** fake SHA1 support for unit tests */ -int fake_sha1 = 0; - -/* OpenSSL implementation */ -#ifdef HAVE_SSL -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif - -#if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA) -#include -#endif - -/** - * Output a libcrypto openssl error to the logfile. - * @param str: string to add to it. - * @param e: the error to output, error number from ERR_get_error(). - */ -static void -log_crypto_error(const char* str, unsigned long e) -{ - char buf[128]; - /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ - ERR_error_string_n(e, buf, sizeof(buf)); - /* buf now contains */ - /* error:[error code]:[library name]:[function name]:[reason string] */ - log_err("%s crypto %s", str, buf); -} - -/** - * Output a libcrypto openssl error to the logfile as a debug message. - * @param level: debug level to use in verbose() call - * @param str: string to add to it. - * @param e: the error to output, error number from ERR_get_error(). - */ -static void -log_crypto_verbose(enum verbosity_value level, const char* str, unsigned long e) -{ - char buf[128]; - /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ - ERR_error_string_n(e, buf, sizeof(buf)); - /* buf now contains */ - /* error:[error code]:[library name]:[function name]:[reason string] */ - verbose(level, "%s crypto %s", str, buf); -} - -/* return size of digest if supported, or 0 otherwise */ -size_t -nsec3_hash_algo_size_supported(int id) -{ - switch(id) { - case NSEC3_HASH_SHA1: - return SHA_DIGEST_LENGTH; - default: - return 0; - } -} - -/* perform nsec3 hash. return false on failure */ -int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - switch(algo) { - case NSEC3_HASH_SHA1: -#ifdef OPENSSL_FIPS - if(!sldns_digest_evp(buf, len, res, EVP_sha1())) - log_crypto_error("could not digest with EVP_sha1", - ERR_get_error()); -#else - (void)SHA1(buf, len, res); -#endif - return 1; - default: - return 0; - } -} - -void -secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) -{ -#ifdef OPENSSL_FIPS - if(!sldns_digest_evp(buf, len, res, EVP_sha256())) - log_crypto_error("could not digest with EVP_sha256", - ERR_get_error()); -#else - (void)SHA256(buf, len, res); -#endif -} - -/** hash structure for keeping track of running hashes */ -struct secalgo_hash { - /** the openssl message digest context */ - EVP_MD_CTX* ctx; -}; - -/** create secalgo hash with hash type */ -static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md) -{ - struct secalgo_hash* h; - if(!md) - return NULL; - h = calloc(1, sizeof(*h)); - if(!h) - return NULL; - h->ctx = EVP_MD_CTX_create(); - if(!h->ctx) { - free(h); - return NULL; - } - if(!EVP_DigestInit_ex(h->ctx, md, NULL)) { - EVP_MD_CTX_destroy(h->ctx); - free(h); - return NULL; - } - return h; -} - -struct secalgo_hash* secalgo_hash_create_sha384(void) -{ - return secalgo_hash_create_md(EVP_sha384()); -} - -struct secalgo_hash* secalgo_hash_create_sha512(void) -{ - return secalgo_hash_create_md(EVP_sha512()); -} - -int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) -{ - return EVP_DigestUpdate(hash->ctx, (unsigned char*)data, - (unsigned int)len); -} - -int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, - size_t maxlen, size_t* resultlen) -{ - if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) { - *resultlen = 0; - log_err("secalgo_hash_final: hash buffer too small"); - return 0; - } - *resultlen = EVP_MD_CTX_size(hash->ctx); - return EVP_DigestFinal_ex(hash->ctx, result, NULL); -} - -void secalgo_hash_delete(struct secalgo_hash* hash) -{ - if(!hash) return; - EVP_MD_CTX_destroy(hash->ctx); - free(hash); -} - -/** - * Return size of DS digest according to its hash algorithm. - * @param algo: DS digest algo. - * @return size in bytes of digest, or 0 if not supported. - */ -size_t -ds_digest_size_supported(int algo) -{ - switch(algo) { - case LDNS_SHA1: -#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1) -#ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED - if (EVP_default_properties_is_fips_enabled(NULL)) - return 0; -#endif - return SHA_DIGEST_LENGTH; -#else - if(fake_sha1) return 20; - return 0; -#endif -#ifdef HAVE_EVP_SHA256 - case LDNS_SHA256: - return SHA256_DIGEST_LENGTH; -#endif -#ifdef USE_GOST - case LDNS_HASH_GOST: - /* we support GOST if it can be loaded */ - (void)sldns_key_EVP_load_gost_id(); - if(EVP_get_digestbyname("md_gost94")) - return 32; - else return 0; -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: - return SHA384_DIGEST_LENGTH; -#endif - default: break; - } - return 0; -} - -#ifdef USE_GOST -/** Perform GOST hash */ -static int -do_gost94(unsigned char* data, size_t len, unsigned char* dest) -{ - const EVP_MD* md = EVP_get_digestbyname("md_gost94"); - if(!md) - return 0; - return sldns_digest_evp(data, (unsigned int)len, dest, md); -} -#endif - -int -secalgo_ds_digest(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - switch(algo) { -#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1) - case LDNS_SHA1: -#ifdef OPENSSL_FIPS - if(!sldns_digest_evp(buf, len, res, EVP_sha1())) - log_crypto_error("could not digest with EVP_sha1", - ERR_get_error()); -#else - (void)SHA1(buf, len, res); -#endif - return 1; -#endif -#ifdef HAVE_EVP_SHA256 - case LDNS_SHA256: -#ifdef OPENSSL_FIPS - if(!sldns_digest_evp(buf, len, res, EVP_sha256())) - log_crypto_error("could not digest with EVP_sha256", - ERR_get_error()); -#else - (void)SHA256(buf, len, res); -#endif - return 1; -#endif -#ifdef USE_GOST - case LDNS_HASH_GOST: - if(do_gost94(buf, len, res)) - return 1; - break; -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: -#ifdef OPENSSL_FIPS - if(!sldns_digest_evp(buf, len, res, EVP_sha384())) - log_crypto_error("could not digest with EVP_sha384", - ERR_get_error()); -#else - (void)SHA384(buf, len, res); -#endif - return 1; -#endif - default: - verbose(VERB_QUERY, "unknown DS digest algorithm %d", - algo); - break; - } - return 0; -} - -/** return true if DNSKEY algorithm id is supported */ -int -dnskey_algo_id_is_supported(int id) -{ - switch(id) { - case LDNS_RSAMD5: - /* RFC 6725 deprecates RSAMD5 */ - return 0; - case LDNS_DSA: - case LDNS_DSA_NSEC3: -#if defined(USE_DSA) && defined(USE_SHA1) - return 1; -#else - if(fake_dsa || fake_sha1) return 1; - return 0; -#endif - - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#ifdef USE_SHA1 -#ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED - return !EVP_default_properties_is_fips_enabled(NULL); -#else - return 1; -#endif -#else - if(fake_sha1) return 1; - return 0; -#endif - -#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) - case LDNS_RSASHA256: -#endif -#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) - case LDNS_RSASHA512: -#endif -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - case LDNS_ECDSAP384SHA384: -#endif -#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) - return 1; -#endif -#ifdef USE_ED25519 - case LDNS_ED25519: -#endif -#ifdef USE_ED448 - case LDNS_ED448: -#endif -#if defined(USE_ED25519) || defined(USE_ED448) -#ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED - return !EVP_default_properties_is_fips_enabled(NULL); -#else - return 1; -#endif -#endif - -#ifdef USE_GOST - case LDNS_ECC_GOST: - /* we support GOST if it can be loaded */ - return sldns_key_EVP_load_gost_id(); -#endif - default: - return 0; - } -} - -#ifdef USE_DSA -/** - * Setup DSA key digest in DER encoding ... - * @param sig: input is signature output alloced ptr (unless failure). - * caller must free alloced ptr if this routine returns true. - * @param len: input is initial siglen, output is output len. - * @return false on failure. - */ -static int -setup_dsa_sig(unsigned char** sig, unsigned int* len) -{ - unsigned char* orig = *sig; - unsigned int origlen = *len; - int newlen; - BIGNUM *R, *S; - DSA_SIG *dsasig; - - /* extract the R and S field from the sig buffer */ - if(origlen < 1 + 2*SHA_DIGEST_LENGTH) - return 0; - R = BN_new(); - if(!R) return 0; - (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); - S = BN_new(); - if(!S) return 0; - (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); - dsasig = DSA_SIG_new(); - if(!dsasig) return 0; - -#ifdef HAVE_DSA_SIG_SET0 - if(!DSA_SIG_set0(dsasig, R, S)) return 0; -#else -# ifndef S_SPLINT_S - dsasig->r = R; - dsasig->s = S; -# endif /* S_SPLINT_S */ -#endif - *sig = NULL; - newlen = i2d_DSA_SIG(dsasig, sig); - if(newlen < 0) { - DSA_SIG_free(dsasig); - free(*sig); - return 0; - } - *len = (unsigned int)newlen; - DSA_SIG_free(dsasig); - return 1; -} -#endif /* USE_DSA */ - -#ifdef USE_ECDSA -/** - * Setup the ECDSA signature in its encoding that the library wants. - * Converts from plain numbers to ASN formatted. - * @param sig: input is signature, output alloced ptr (unless failure). - * caller must free alloced ptr if this routine returns true. - * @param len: input is initial siglen, output is output len. - * @return false on failure. - */ -static int -setup_ecdsa_sig(unsigned char** sig, unsigned int* len) -{ - /* convert from two BIGNUMs in the rdata buffer, to ASN notation. - * ASN preamble: 30440220 0220 - * the '20' is the length of that field (=bnsize). -i * the '44' is the total remaining length. - * if negative, start with leading zero. - * if starts with 00s, remove them from the number. - */ - uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; - int pre_len = 4; - uint8_t mid[] = {0x02, 0x20}; - int mid_len = 2; - int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0; - int bnsize = (int)((*len)/2); - unsigned char* d = *sig; - uint8_t* p; - /* if too short or not even length, fails */ - if(*len < 16 || bnsize*2 != (int)*len) - return 0; - - /* strip leading zeroes from r (but not last one) */ - while(r_rem < bnsize-1 && d[r_rem] == 0) - r_rem++; - /* strip leading zeroes from s (but not last one) */ - while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0) - s_rem++; - - r_high = ((d[0+r_rem]&0x80)?1:0); - s_high = ((d[bnsize+s_rem]&0x80)?1:0); - raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len + - s_high + bnsize - s_rem; - *sig = (unsigned char*)malloc((size_t)raw_sig_len); - if(!*sig) - return 0; - p = (uint8_t*)*sig; - p[0] = pre[0]; - p[1] = (uint8_t)(raw_sig_len-2); - p[2] = pre[2]; - p[3] = (uint8_t)(bnsize + r_high - r_rem); - p += 4; - if(r_high) { - *p = 0; - p += 1; - } - memmove(p, d+r_rem, (size_t)bnsize-r_rem); - p += bnsize-r_rem; - memmove(p, mid, (size_t)mid_len-1); - p += mid_len-1; - *p = (uint8_t)(bnsize + s_high - s_rem); - p += 1; - if(s_high) { - *p = 0; - p += 1; - } - memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem); - *len = (unsigned int)raw_sig_len; - return 1; -} -#endif /* USE_ECDSA */ - -#ifdef USE_ECDSA_EVP_WORKAROUND -static EVP_MD ecdsa_evp_256_md; -static EVP_MD ecdsa_evp_384_md; -void ecdsa_evp_workaround_init(void) -{ - /* openssl before 1.0.0 fixes RSA with the SHA256 - * hash in EVP. We create one for ecdsa_sha256 */ - ecdsa_evp_256_md = *EVP_sha256(); - ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC; - ecdsa_evp_256_md.verify = (void*)ECDSA_verify; - - ecdsa_evp_384_md = *EVP_sha384(); - ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC; - ecdsa_evp_384_md.verify = (void*)ECDSA_verify; -} -#endif /* USE_ECDSA_EVP_WORKAROUND */ - -/** - * Setup key and digest for verification. Adjust sig if necessary. - * - * @param algo: key algorithm - * @param evp_key: EVP PKEY public key to create. - * @param digest_type: digest type to use - * @param key: key to setup for. - * @param keylen: length of key. - * @return false on failure. - */ -static int -setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, - unsigned char* key, size_t keylen) -{ - switch(algo) { -#if defined(USE_DSA) && defined(USE_SHA1) - case LDNS_DSA: - case LDNS_DSA_NSEC3: - *evp_key = sldns_key_dsa2pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: sldns_key_dsa2pkey failed"); - return 0; - } -#ifdef HAVE_EVP_DSS1 - *digest_type = EVP_dss1(); -#else - *digest_type = EVP_sha1(); -#endif - - break; -#endif /* USE_DSA && USE_SHA1 */ - -#if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) -#ifdef USE_SHA1 - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#endif -#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) - case LDNS_RSASHA256: -#endif -#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) - case LDNS_RSASHA512: -#endif - *evp_key = sldns_key_rsa2pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey SHA failed"); - return 0; - } - - /* select SHA version */ -#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) - if(algo == LDNS_RSASHA256) - *digest_type = EVP_sha256(); - else -#endif -#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) - if(algo == LDNS_RSASHA512) - *digest_type = EVP_sha512(); - else -#endif -#ifdef USE_SHA1 - *digest_type = EVP_sha1(); -#else - { verbose(VERB_QUERY, "no digest available"); return 0; } -#endif - break; -#endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */ - - case LDNS_RSAMD5: - *evp_key = sldns_key_rsa2pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey MD5 failed"); - return 0; - } - *digest_type = EVP_md5(); - - break; -#ifdef USE_GOST - case LDNS_ECC_GOST: - *evp_key = sldns_gost2pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: " - "sldns_gost2pkey_raw failed"); - return 0; - } - *digest_type = EVP_get_digestbyname("md_gost94"); - if(!*digest_type) { - verbose(VERB_QUERY, "verify: " - "EVP_getdigest md_gost94 failed"); - return 0; - } - break; -#endif -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - *evp_key = sldns_ecdsa2pkey_raw(key, keylen, - LDNS_ECDSAP256SHA256); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: " - "sldns_ecdsa2pkey_raw failed"); - return 0; - } -#ifdef USE_ECDSA_EVP_WORKAROUND - *digest_type = &ecdsa_evp_256_md; -#else - *digest_type = EVP_sha256(); -#endif - break; - case LDNS_ECDSAP384SHA384: - *evp_key = sldns_ecdsa2pkey_raw(key, keylen, - LDNS_ECDSAP384SHA384); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: " - "sldns_ecdsa2pkey_raw failed"); - return 0; - } -#ifdef USE_ECDSA_EVP_WORKAROUND - *digest_type = &ecdsa_evp_384_md; -#else - *digest_type = EVP_sha384(); -#endif - break; -#endif /* USE_ECDSA */ -#ifdef USE_ED25519 - case LDNS_ED25519: - *evp_key = sldns_ed255192pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: " - "sldns_ed255192pkey_raw failed"); - return 0; - } - *digest_type = NULL; - break; -#endif /* USE_ED25519 */ -#ifdef USE_ED448 - case LDNS_ED448: - *evp_key = sldns_ed4482pkey_raw(key, keylen); - if(!*evp_key) { - verbose(VERB_QUERY, "verify: " - "sldns_ed4482pkey_raw failed"); - return 0; - } - *digest_type = NULL; - break; -#endif /* USE_ED448 */ - default: - verbose(VERB_QUERY, "verify: unknown algorithm %d", - algo); - return 0; - } - return 1; -} - -static void -digest_ctx_free(EVP_MD_CTX* ctx, EVP_PKEY *evp_key, - unsigned char* sigblock, int dofree, int docrypto_free) -{ -#ifdef HAVE_EVP_MD_CTX_NEW - EVP_MD_CTX_destroy(ctx); -#else - EVP_MD_CTX_cleanup(ctx); - free(ctx); -#endif - EVP_PKEY_free(evp_key); - if(dofree) free(sigblock); - else if(docrypto_free) OPENSSL_free(sigblock); -} - -static enum sec_status -digest_error_status(const char *str) -{ - unsigned long e = ERR_get_error(); -#ifdef EVP_R_INVALID_DIGEST - if (ERR_GET_LIB(e) == ERR_LIB_EVP && - ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) { - log_crypto_verbose(VERB_ALGO, str, e); - return sec_status_indeterminate; - } -#endif - log_crypto_verbose(VERB_QUERY, str, e); - return sec_status_unchecked; -} - -/** - * Check a canonical sig+rrset and signature against a dnskey - * @param buf: buffer with data to verify, the first rrsig part and the - * canonicalized rrset. - * @param algo: DNSKEY algorithm. - * @param sigblock: signature rdata field from RRSIG - * @param sigblock_len: length of sigblock data. - * @param key: public key data from DNSKEY RR. - * @param keylen: length of keydata. - * @param reason: bogus reason in more detail. - * @return secure if verification succeeded, bogus on crypto failure, - * unchecked on format errors and alloc failures, indeterminate - * if digest is not supported by the crypto library (openssl3+ only). - */ -enum sec_status -verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen, - char** reason) -{ - const EVP_MD *digest_type; - EVP_MD_CTX* ctx; - int res, dofree = 0, docrypto_free = 0; - EVP_PKEY *evp_key = NULL; - -#ifndef USE_DSA - if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1)) - return sec_status_secure; -#endif -#ifndef USE_SHA1 - if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3)) - return sec_status_secure; -#endif - - if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { - verbose(VERB_QUERY, "verify: failed to setup key"); - *reason = "use of key for crypto failed"; - EVP_PKEY_free(evp_key); - return sec_status_bogus; - } -#ifdef USE_DSA - /* if it is a DSA signature in bind format, convert to DER format */ - if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && - sigblock_len == 1+2*SHA_DIGEST_LENGTH) { - if(!setup_dsa_sig(&sigblock, &sigblock_len)) { - verbose(VERB_QUERY, "verify: failed to setup DSA sig"); - *reason = "use of key for DSA crypto failed"; - EVP_PKEY_free(evp_key); - return sec_status_bogus; - } - docrypto_free = 1; - } -#endif -#if defined(USE_ECDSA) && defined(USE_DSA) - else -#endif -#ifdef USE_ECDSA - if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) { - /* EVP uses ASN prefix on sig, which is not in the wire data */ - if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) { - verbose(VERB_QUERY, "verify: failed to setup ECDSA sig"); - *reason = "use of signature for ECDSA crypto failed"; - EVP_PKEY_free(evp_key); - return sec_status_bogus; - } - dofree = 1; - } -#endif /* USE_ECDSA */ - - /* do the signature cryptography work */ -#ifdef HAVE_EVP_MD_CTX_NEW - ctx = EVP_MD_CTX_new(); -#else - ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); - if(ctx) EVP_MD_CTX_init(ctx); -#endif - if(!ctx) { - log_err("EVP_MD_CTX_new: malloc failure"); - EVP_PKEY_free(evp_key); - if(dofree) free(sigblock); - else if(docrypto_free) OPENSSL_free(sigblock); - return sec_status_unchecked; - } -#ifndef HAVE_EVP_DIGESTVERIFY - if(EVP_DigestInit(ctx, digest_type) == 0) { - enum sec_status sec; - sec = digest_error_status("verify: EVP_DigestInit failed"); - digest_ctx_free(ctx, evp_key, sigblock, - dofree, docrypto_free); - return sec; - } - if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf)) == 0) { - log_crypto_verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed", - ERR_get_error()); - digest_ctx_free(ctx, evp_key, sigblock, - dofree, docrypto_free); - return sec_status_unchecked; - } - - res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); -#else /* HAVE_EVP_DIGESTVERIFY */ - if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) { - enum sec_status sec; - sec = digest_error_status("verify: EVP_DigestVerifyInit failed"); - digest_ctx_free(ctx, evp_key, sigblock, - dofree, docrypto_free); - return sec; - } - res = EVP_DigestVerify(ctx, sigblock, sigblock_len, - (unsigned char*)sldns_buffer_begin(buf), - sldns_buffer_limit(buf)); -#endif - digest_ctx_free(ctx, evp_key, sigblock, - dofree, docrypto_free); - - if(res == 1) { - return sec_status_secure; - } else if(res == 0) { - verbose(VERB_QUERY, "verify: signature mismatch"); - *reason = "signature crypto failed"; - return sec_status_bogus; - } - - log_crypto_error("verify:", ERR_get_error()); - return sec_status_unchecked; -} - -/**************************************************/ -#elif defined(HAVE_NSS) -/* libnss implementation */ -/* nss3 */ -#include "sechash.h" -#include "pk11pub.h" -#include "keyhi.h" -#include "secerr.h" -#include "cryptohi.h" -/* nspr4 */ -#include "prerror.h" - -/* return size of digest if supported, or 0 otherwise */ -size_t -nsec3_hash_algo_size_supported(int id) -{ - switch(id) { - case NSEC3_HASH_SHA1: - return SHA1_LENGTH; - default: - return 0; - } -} - -/* perform nsec3 hash. return false on failure */ -int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - switch(algo) { - case NSEC3_HASH_SHA1: - (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len); - return 1; - default: - return 0; - } -} - -void -secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) -{ - (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len); -} - -/** the secalgo hash structure */ -struct secalgo_hash { - /** hash context */ - HASHContext* ctx; -}; - -/** create hash struct of type */ -static struct secalgo_hash* secalgo_hash_create_type(HASH_HashType tp) -{ - struct secalgo_hash* h = calloc(1, sizeof(*h)); - if(!h) - return NULL; - h->ctx = HASH_Create(tp); - if(!h->ctx) { - free(h); - return NULL; - } - return h; -} - -struct secalgo_hash* secalgo_hash_create_sha384(void) -{ - return secalgo_hash_create_type(HASH_AlgSHA384); -} - -struct secalgo_hash* secalgo_hash_create_sha512(void) -{ - return secalgo_hash_create_type(HASH_AlgSHA512); -} - -int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) -{ - HASH_Update(hash->ctx, (unsigned char*)data, (unsigned int)len); - return 1; -} - -int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, - size_t maxlen, size_t* resultlen) -{ - unsigned int reslen = 0; - if(HASH_ResultLenContext(hash->ctx) > (unsigned int)maxlen) { - *resultlen = 0; - log_err("secalgo_hash_final: hash buffer too small"); - return 0; - } - HASH_End(hash->ctx, (unsigned char*)result, &reslen, - (unsigned int)maxlen); - *resultlen = (size_t)reslen; - return 1; -} - -void secalgo_hash_delete(struct secalgo_hash* hash) -{ - if(!hash) return; - HASH_Destroy(hash->ctx); - free(hash); -} - -size_t -ds_digest_size_supported(int algo) -{ - /* uses libNSS */ - switch(algo) { -#ifdef USE_SHA1 - case LDNS_SHA1: - return SHA1_LENGTH; -#endif -#ifdef USE_SHA2 - case LDNS_SHA256: - return SHA256_LENGTH; -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: - return SHA384_LENGTH; -#endif - /* GOST not supported in NSS */ - case LDNS_HASH_GOST: - default: break; - } - return 0; -} - -int -secalgo_ds_digest(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - /* uses libNSS */ - switch(algo) { -#ifdef USE_SHA1 - case LDNS_SHA1: - return HASH_HashBuf(HASH_AlgSHA1, res, buf, len) - == SECSuccess; -#endif -#if defined(USE_SHA2) - case LDNS_SHA256: - return HASH_HashBuf(HASH_AlgSHA256, res, buf, len) - == SECSuccess; -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: - return HASH_HashBuf(HASH_AlgSHA384, res, buf, len) - == SECSuccess; -#endif - case LDNS_HASH_GOST: - default: - verbose(VERB_QUERY, "unknown DS digest algorithm %d", - algo); - break; - } - return 0; -} - -int -dnskey_algo_id_is_supported(int id) -{ - /* uses libNSS */ - switch(id) { - case LDNS_RSAMD5: - /* RFC 6725 deprecates RSAMD5 */ - return 0; -#if defined(USE_SHA1) || defined(USE_SHA2) -#if defined(USE_DSA) && defined(USE_SHA1) - case LDNS_DSA: - case LDNS_DSA_NSEC3: -#endif -#ifdef USE_SHA1 - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#endif -#ifdef USE_SHA2 - case LDNS_RSASHA256: -#endif -#ifdef USE_SHA2 - case LDNS_RSASHA512: -#endif - return 1; -#endif /* SHA1 or SHA2 */ - -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - case LDNS_ECDSAP384SHA384: - return PK11_TokenExists(CKM_ECDSA); -#endif - case LDNS_ECC_GOST: - default: - return 0; - } -} - -/* return a new public key for NSS */ -static SECKEYPublicKey* nss_key_create(KeyType ktype) -{ - SECKEYPublicKey* key; - PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(!arena) { - log_err("out of memory, PORT_NewArena failed"); - return NULL; - } - key = PORT_ArenaZNew(arena, SECKEYPublicKey); - if(!key) { - log_err("out of memory, PORT_ArenaZNew failed"); - PORT_FreeArena(arena, PR_FALSE); - return NULL; - } - key->arena = arena; - key->keyType = ktype; - key->pkcs11Slot = NULL; - key->pkcs11ID = CK_INVALID_HANDLE; - return key; -} - -static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo) -{ - SECKEYPublicKey* pk; - SECItem pub = {siBuffer, NULL, 0}; - SECItem params = {siBuffer, NULL, 0}; - static unsigned char param256[] = { - /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256) - * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */ - 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 - }; - static unsigned char param384[] = { - /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384) - * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */ - 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 - }; - unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ - - /* check length, which uncompressed must be 2 bignums */ - if(algo == LDNS_ECDSAP256SHA256) { - if(len != 2*256/8) return NULL; - /* ECCurve_X9_62_PRIME_256V1 */ - } else if(algo == LDNS_ECDSAP384SHA384) { - if(len != 2*384/8) return NULL; - /* ECCurve_X9_62_PRIME_384R1 */ - } else return NULL; - - buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */ - memmove(buf+1, key, len); - pub.data = buf; - pub.len = len+1; - if(algo == LDNS_ECDSAP256SHA256) { - params.data = param256; - params.len = sizeof(param256); - } else { - params.data = param384; - params.len = sizeof(param384); - } - - pk = nss_key_create(ecKey); - if(!pk) - return NULL; - pk->u.ec.size = (len/2)*8; - if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - - return pk; -} - -#if defined(USE_DSA) && defined(USE_SHA1) -static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) -{ - SECKEYPublicKey* pk; - uint8_t T; - uint16_t length; - uint16_t offset; - SECItem Q = {siBuffer, NULL, 0}; - SECItem P = {siBuffer, NULL, 0}; - SECItem G = {siBuffer, NULL, 0}; - SECItem Y = {siBuffer, NULL, 0}; - - if(len == 0) - return NULL; - T = (uint8_t)key[0]; - length = (64 + T * 8); - offset = 1; - - if (T > 8) { - return NULL; - } - if(len < (size_t)1 + SHA1_LENGTH + 3*length) - return NULL; - - Q.data = key+offset; - Q.len = SHA1_LENGTH; - offset += SHA1_LENGTH; - - P.data = key+offset; - P.len = length; - offset += length; - - G.data = key+offset; - G.len = length; - offset += length; - - Y.data = key+offset; - Y.len = length; - offset += length; - - pk = nss_key_create(dsaKey); - if(!pk) - return NULL; - if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - return pk; -} -#endif /* USE_DSA && USE_SHA1 */ - -static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len) -{ - SECKEYPublicKey* pk; - uint16_t exp; - uint16_t offset; - uint16_t int16; - SECItem modulus = {siBuffer, NULL, 0}; - SECItem exponent = {siBuffer, NULL, 0}; - if(len == 0) - return NULL; - if(key[0] == 0) { - if(len < 3) - return NULL; - /* the exponent is too large so it's places further */ - memmove(&int16, key+1, 2); - exp = ntohs(int16); - offset = 3; - } else { - exp = key[0]; - offset = 1; - } - - /* key length at least one */ - if(len < (size_t)offset + exp + 1) - return NULL; - - exponent.data = key+offset; - exponent.len = exp; - offset += exp; - modulus.data = key+offset; - modulus.len = (len - offset); - - pk = nss_key_create(rsaKey); - if(!pk) - return NULL; - if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) { - SECKEY_DestroyPublicKey(pk); - return NULL; - } - return pk; -} - -/** - * Setup key and digest for verification. Adjust sig if necessary. - * - * @param algo: key algorithm - * @param evp_key: EVP PKEY public key to create. - * @param digest_type: digest type to use - * @param key: key to setup for. - * @param keylen: length of key. - * @param prefix: if returned, the ASN prefix for the hashblob. - * @param prefixlen: length of the prefix. - * @return false on failure. - */ -static int -nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, - unsigned char* key, size_t keylen, unsigned char** prefix, - size_t* prefixlen) -{ - /* uses libNSS */ - - /* hash prefix for md5, RFC2537 */ - static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; - /* hash prefix to prepend to hash output, from RFC3110 */ - static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, - 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; - /* from RFC5702 */ - static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; - static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; - /* from RFC6234 */ - /* for future RSASHA384 .. - static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; - */ - - switch(algo) { - -#if defined(USE_SHA1) || defined(USE_SHA2) -#if defined(USE_DSA) && defined(USE_SHA1) - case LDNS_DSA: - case LDNS_DSA_NSEC3: - *pubkey = nss_buf2dsa(key, keylen); - if(!*pubkey) { - log_err("verify: malloc failure in crypto"); - return 0; - } - *htype = HASH_AlgSHA1; - /* no prefix for DSA verification */ - break; -#endif -#ifdef USE_SHA1 - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#endif -#ifdef USE_SHA2 - case LDNS_RSASHA256: -#endif -#ifdef USE_SHA2 - case LDNS_RSASHA512: -#endif - *pubkey = nss_buf2rsa(key, keylen); - if(!*pubkey) { - log_err("verify: malloc failure in crypto"); - return 0; - } - /* select SHA version */ -#ifdef USE_SHA2 - if(algo == LDNS_RSASHA256) { - *htype = HASH_AlgSHA256; - *prefix = p_sha256; - *prefixlen = sizeof(p_sha256); - } else -#endif -#ifdef USE_SHA2 - if(algo == LDNS_RSASHA512) { - *htype = HASH_AlgSHA512; - *prefix = p_sha512; - *prefixlen = sizeof(p_sha512); - } else -#endif -#ifdef USE_SHA1 - { - *htype = HASH_AlgSHA1; - *prefix = p_sha1; - *prefixlen = sizeof(p_sha1); - } -#else - { - verbose(VERB_QUERY, "verify: no digest algo"); - return 0; - } -#endif - - break; -#endif /* SHA1 or SHA2 */ - - case LDNS_RSAMD5: - *pubkey = nss_buf2rsa(key, keylen); - if(!*pubkey) { - log_err("verify: malloc failure in crypto"); - return 0; - } - *htype = HASH_AlgMD5; - *prefix = p_md5; - *prefixlen = sizeof(p_md5); - - break; -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - *pubkey = nss_buf2ecdsa(key, keylen, - LDNS_ECDSAP256SHA256); - if(!*pubkey) { - log_err("verify: malloc failure in crypto"); - return 0; - } - *htype = HASH_AlgSHA256; - /* no prefix for DSA verification */ - break; - case LDNS_ECDSAP384SHA384: - *pubkey = nss_buf2ecdsa(key, keylen, - LDNS_ECDSAP384SHA384); - if(!*pubkey) { - log_err("verify: malloc failure in crypto"); - return 0; - } - *htype = HASH_AlgSHA384; - /* no prefix for DSA verification */ - break; -#endif /* USE_ECDSA */ - case LDNS_ECC_GOST: - default: - verbose(VERB_QUERY, "verify: unknown algorithm %d", - algo); - return 0; - } - return 1; -} - -/** - * Check a canonical sig+rrset and signature against a dnskey - * @param buf: buffer with data to verify, the first rrsig part and the - * canonicalized rrset. - * @param algo: DNSKEY algorithm. - * @param sigblock: signature rdata field from RRSIG - * @param sigblock_len: length of sigblock data. - * @param key: public key data from DNSKEY RR. - * @param keylen: length of keydata. - * @param reason: bogus reason in more detail. - * @return secure if verification succeeded, bogus on crypto failure, - * unchecked on format errors and alloc failures. - */ -enum sec_status -verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen, - char** reason) -{ - /* uses libNSS */ - /* large enough for the different hashes */ - unsigned char hash[HASH_LENGTH_MAX]; - unsigned char hash2[HASH_LENGTH_MAX*2]; - HASH_HashType htype = 0; - SECKEYPublicKey* pubkey = NULL; - SECItem secsig = {siBuffer, sigblock, sigblock_len}; - SECItem sechash = {siBuffer, hash, 0}; - SECStatus res; - unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */ - size_t prefixlen = 0; - int err; - - if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen, - &prefix, &prefixlen)) { - verbose(VERB_QUERY, "verify: failed to setup key"); - *reason = "use of key for crypto failed"; - SECKEY_DestroyPublicKey(pubkey); - return sec_status_bogus; - } - -#if defined(USE_DSA) && defined(USE_SHA1) - /* need to convert DSA, ECDSA signatures? */ - if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { - if(sigblock_len == 1+2*SHA1_LENGTH) { - secsig.data ++; - secsig.len --; - } else { - SECItem* p = DSAU_DecodeDerSig(&secsig); - if(!p) { - verbose(VERB_QUERY, "verify: failed DER decode"); - *reason = "signature DER decode failed"; - SECKEY_DestroyPublicKey(pubkey); - return sec_status_bogus; - } - if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) { - log_err("alloc failure in DER decode"); - SECKEY_DestroyPublicKey(pubkey); - SECITEM_FreeItem(p, PR_TRUE); - return sec_status_unchecked; - } - SECITEM_FreeItem(p, PR_TRUE); - } - } -#endif /* USE_DSA */ - - /* do the signature cryptography work */ - /* hash the data */ - sechash.len = HASH_ResultLen(htype); - if(sechash.len > sizeof(hash)) { - verbose(VERB_QUERY, "verify: hash too large for buffer"); - SECKEY_DestroyPublicKey(pubkey); - return sec_status_unchecked; - } - if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf)) != SECSuccess) { - verbose(VERB_QUERY, "verify: HASH_HashBuf failed"); - SECKEY_DestroyPublicKey(pubkey); - return sec_status_unchecked; - } - if(prefix) { - int hashlen = sechash.len; - if(prefixlen+hashlen > sizeof(hash2)) { - verbose(VERB_QUERY, "verify: hashprefix too large"); - SECKEY_DestroyPublicKey(pubkey); - return sec_status_unchecked; - } - sechash.data = hash2; - sechash.len = prefixlen+hashlen; - memcpy(sechash.data, prefix, prefixlen); - memmove(sechash.data+prefixlen, hash, hashlen); - } - - /* verify the signature */ - res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/); - SECKEY_DestroyPublicKey(pubkey); - - if(res == SECSuccess) { - return sec_status_secure; - } - err = PORT_GetError(); - if(err != SEC_ERROR_BAD_SIGNATURE) { - /* failed to verify */ - verbose(VERB_QUERY, "verify: PK11_Verify failed: %s", - PORT_ErrorToString(err)); - /* if it is not supported, like ECC is removed, we get, - * SEC_ERROR_NO_MODULE */ - if(err == SEC_ERROR_NO_MODULE) - return sec_status_unchecked; - /* but other errors are commonly returned - * for a bad signature from NSS. Thus we return bogus, - * not unchecked */ - *reason = "signature crypto failed"; - return sec_status_bogus; - } - verbose(VERB_QUERY, "verify: signature mismatch: %s", - PORT_ErrorToString(err)); - *reason = "signature crypto failed"; - return sec_status_bogus; -} - -#elif defined(HAVE_NETTLE) - -#include "sha.h" -#include "bignum.h" -#include "macros.h" -#include "rsa.h" -#include "dsa.h" -#ifdef HAVE_NETTLE_DSA_COMPAT_H -#include "dsa-compat.h" -#endif -#include "asn1.h" -#ifdef USE_ECDSA -#include "ecdsa.h" -#include "ecc-curve.h" -#endif -#ifdef HAVE_NETTLE_EDDSA_H -#include "eddsa.h" -#endif - -static int -_digest_nettle(int algo, uint8_t* buf, size_t len, - unsigned char* res) -{ - switch(algo) { - case SHA1_DIGEST_SIZE: - { - struct sha1_ctx ctx; - sha1_init(&ctx); - sha1_update(&ctx, len, buf); - sha1_digest(&ctx, SHA1_DIGEST_SIZE, res); - return 1; - } - case SHA256_DIGEST_SIZE: - { - struct sha256_ctx ctx; - sha256_init(&ctx); - sha256_update(&ctx, len, buf); - sha256_digest(&ctx, SHA256_DIGEST_SIZE, res); - return 1; - } - case SHA384_DIGEST_SIZE: - { - struct sha384_ctx ctx; - sha384_init(&ctx); - sha384_update(&ctx, len, buf); - sha384_digest(&ctx, SHA384_DIGEST_SIZE, res); - return 1; - } - case SHA512_DIGEST_SIZE: - { - struct sha512_ctx ctx; - sha512_init(&ctx); - sha512_update(&ctx, len, buf); - sha512_digest(&ctx, SHA512_DIGEST_SIZE, res); - return 1; - } - default: - break; - } - return 0; -} - -/* return size of digest if supported, or 0 otherwise */ -size_t -nsec3_hash_algo_size_supported(int id) -{ - switch(id) { - case NSEC3_HASH_SHA1: - return SHA1_DIGEST_SIZE; - default: - return 0; - } -} - -/* perform nsec3 hash. return false on failure */ -int -secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - switch(algo) { - case NSEC3_HASH_SHA1: - return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len, - res); - default: - return 0; - } -} - -void -secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) -{ - _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res); -} - -/** secalgo hash structure */ -struct secalgo_hash { - /** if it is 384 or 512 */ - int active; - /** context for sha384 */ - struct sha384_ctx ctx384; - /** context for sha512 */ - struct sha512_ctx ctx512; -}; - -struct secalgo_hash* secalgo_hash_create_sha384(void) -{ - struct secalgo_hash* h = calloc(1, sizeof(*h)); - if(!h) - return NULL; - h->active = 384; - sha384_init(&h->ctx384); - return h; -} - -struct secalgo_hash* secalgo_hash_create_sha512(void) -{ - struct secalgo_hash* h = calloc(1, sizeof(*h)); - if(!h) - return NULL; - h->active = 512; - sha512_init(&h->ctx512); - return h; -} - -int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len) -{ - if(hash->active == 384) { - sha384_update(&hash->ctx384, len, data); - } else if(hash->active == 512) { - sha512_update(&hash->ctx512, len, data); - } else { - return 0; - } - return 1; -} - -int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, - size_t maxlen, size_t* resultlen) -{ - if(hash->active == 384) { - if(SHA384_DIGEST_SIZE > maxlen) { - *resultlen = 0; - log_err("secalgo_hash_final: hash buffer too small"); - return 0; - } - *resultlen = SHA384_DIGEST_SIZE; - sha384_digest(&hash->ctx384, SHA384_DIGEST_SIZE, - (unsigned char*)result); - } else if(hash->active == 512) { - if(SHA512_DIGEST_SIZE > maxlen) { - *resultlen = 0; - log_err("secalgo_hash_final: hash buffer too small"); - return 0; - } - *resultlen = SHA512_DIGEST_SIZE; - sha512_digest(&hash->ctx512, SHA512_DIGEST_SIZE, - (unsigned char*)result); - } else { - *resultlen = 0; - return 0; - } - return 1; -} - -void secalgo_hash_delete(struct secalgo_hash* hash) -{ - if(!hash) return; - free(hash); -} - -/** - * Return size of DS digest according to its hash algorithm. - * @param algo: DS digest algo. - * @return size in bytes of digest, or 0 if not supported. - */ -size_t -ds_digest_size_supported(int algo) -{ - switch(algo) { - case LDNS_SHA1: -#ifdef USE_SHA1 - return SHA1_DIGEST_SIZE; -#else - if(fake_sha1) return 20; - return 0; -#endif -#ifdef USE_SHA2 - case LDNS_SHA256: - return SHA256_DIGEST_SIZE; -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: - return SHA384_DIGEST_SIZE; -#endif - /* GOST not supported */ - case LDNS_HASH_GOST: - default: - break; - } - return 0; -} - -int -secalgo_ds_digest(int algo, unsigned char* buf, size_t len, - unsigned char* res) -{ - switch(algo) { -#ifdef USE_SHA1 - case LDNS_SHA1: - return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res); -#endif -#if defined(USE_SHA2) - case LDNS_SHA256: - return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res); -#endif -#ifdef USE_ECDSA - case LDNS_SHA384: - return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res); - -#endif - case LDNS_HASH_GOST: - default: - verbose(VERB_QUERY, "unknown DS digest algorithm %d", - algo); - break; - } - return 0; -} - -int -dnskey_algo_id_is_supported(int id) -{ - /* uses libnettle */ - switch(id) { - case LDNS_DSA: - case LDNS_DSA_NSEC3: -#if defined(USE_DSA) && defined(USE_SHA1) - return 1; -#else - if(fake_dsa || fake_sha1) return 1; - return 0; -#endif - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: -#ifdef USE_SHA1 - return 1; -#else - if(fake_sha1) return 1; - return 0; -#endif -#ifdef USE_SHA2 - case LDNS_RSASHA256: - case LDNS_RSASHA512: -#endif -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - case LDNS_ECDSAP384SHA384: -#endif - return 1; -#ifdef USE_ED25519 - case LDNS_ED25519: - return 1; -#endif - case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ - case LDNS_ECC_GOST: - default: - return 0; - } -} - -#if defined(USE_DSA) && defined(USE_SHA1) -static char * -_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen) -{ - uint8_t digest[SHA1_DIGEST_SIZE]; - uint8_t key_t_value; - int res = 0; - size_t offset; - struct dsa_public_key pubkey; - struct dsa_signature signature; - unsigned int expected_len; - - /* Extract DSA signature from the record */ - nettle_dsa_signature_init(&signature); - /* Signature length: 41 bytes - RFC 2536 sec. 3 */ - if(sigblock_len == 41) { - if(key[0] != sigblock[0]) - return "invalid T value in DSA signature or pubkey"; - nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1); - nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20); - } else { - /* DER encoded, decode the ASN1 notated R and S bignums */ - /* SEQUENCE { r INTEGER, s INTEGER } */ - struct asn1_der_iterator i, seq; - if(asn1_der_iterator_first(&i, sigblock_len, - (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED - || i.type != ASN1_SEQUENCE) - return "malformed DER encoded DSA signature"; - /* decode this element of i using the seq iterator */ - if(asn1_der_decode_constructed(&i, &seq) != - ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) - return "malformed DER encoded DSA signature"; - if(!asn1_der_get_bignum(&seq, signature.r, 20*8)) - return "malformed DER encoded DSA signature"; - if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE - || seq.type != ASN1_INTEGER) - return "malformed DER encoded DSA signature"; - if(!asn1_der_get_bignum(&seq, signature.s, 20*8)) - return "malformed DER encoded DSA signature"; - if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) - return "malformed DER encoded DSA signature"; - } - - /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */ - key_t_value = key[0]; - if (key_t_value > 8) { - return "invalid T value in DSA pubkey"; - } - - /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */ - if (keylen < 21) { - return "DSA pubkey too short"; - } - - expected_len = 1 + /* T */ - 20 + /* Q */ - (64 + key_t_value*8) + /* P */ - (64 + key_t_value*8) + /* G */ - (64 + key_t_value*8); /* Y */ - if (keylen != expected_len ) { - return "invalid DSA pubkey length"; - } - - /* Extract DSA pubkey from the record */ - nettle_dsa_public_key_init(&pubkey); - offset = 1; - nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset); - offset += 20; - nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset); - offset += (64 + key_t_value*8); - nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset); - offset += (64 + key_t_value*8); - nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset); - - /* Digest content of "buf" and verify its DSA signature in "sigblock"*/ - res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= dsa_sha1_verify_digest(&pubkey, digest, &signature); - - /* Clear and return */ - nettle_dsa_signature_clear(&signature); - nettle_dsa_public_key_clear(&pubkey); - if (!res) - return "DSA signature verification failed"; - else - return NULL; -} -#endif /* USE_DSA */ - -static char * -_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock, - unsigned int sigblock_len, uint8_t* key, unsigned int keylen) -{ - uint16_t exp_len = 0; - size_t exp_offset = 0, mod_offset = 0; - struct rsa_public_key pubkey; - mpz_t signature; - int res = 0; - - /* RSA pubkey parsing as per RFC 3110 sec. 2 */ - if( keylen <= 1) { - return "null RSA key"; - } - if (key[0] != 0) { - /* 1-byte length */ - exp_len = key[0]; - exp_offset = 1; - } else { - /* 1-byte NUL + 2-bytes exponent length */ - if (keylen < 3) { - return "incorrect RSA key length"; - } - exp_len = READ_UINT16(key+1); - if (exp_len == 0) - return "null RSA exponent length"; - exp_offset = 3; - } - /* Check that we are not over-running input length */ - if (keylen < exp_offset + exp_len + 1) { - return "RSA key content shorter than expected"; - } - mod_offset = exp_offset + exp_len; - nettle_rsa_public_key_init(&pubkey); - pubkey.size = keylen - mod_offset; - nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]); - nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]); - - /* Digest content of "buf" and verify its RSA signature in "sigblock"*/ - nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock); - switch (digest_size) { - case SHA1_DIGEST_SIZE: - { - uint8_t digest[SHA1_DIGEST_SIZE]; - res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= rsa_sha1_verify_digest(&pubkey, digest, signature); - break; - } - case SHA256_DIGEST_SIZE: - { - uint8_t digest[SHA256_DIGEST_SIZE]; - res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= rsa_sha256_verify_digest(&pubkey, digest, signature); - break; - } - case SHA512_DIGEST_SIZE: - { - uint8_t digest[SHA512_DIGEST_SIZE]; - res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= rsa_sha512_verify_digest(&pubkey, digest, signature); - break; - } - default: - break; - } - - /* Clear and return */ - nettle_rsa_public_key_clear(&pubkey); - mpz_clear(signature); - if (!res) { - return "RSA signature verification failed"; - } else { - return NULL; - } -} - -#ifdef USE_ECDSA -static char * -_verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen) -{ - int res = 0; - struct ecc_point pubkey; - struct dsa_signature signature; - - /* Always matched strength, as per RFC 6605 sec. 1 */ - if (sigblock_len != 2*digest_size || keylen != 2*digest_size) { - return "wrong ECDSA signature length"; - } - - /* Parse ECDSA signature as per RFC 6605 sec. 4 */ - nettle_dsa_signature_init(&signature); - switch (digest_size) { - case SHA256_DIGEST_SIZE: - { - uint8_t digest[SHA256_DIGEST_SIZE]; - mpz_t x, y; - nettle_ecc_point_init(&pubkey, nettle_get_secp_256r1()); - nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key); - nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE); - nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock); - nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE); - res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= nettle_ecc_point_set(&pubkey, x, y); - res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature); - mpz_clear(x); - mpz_clear(y); - nettle_ecc_point_clear(&pubkey); - break; - } - case SHA384_DIGEST_SIZE: - { - uint8_t digest[SHA384_DIGEST_SIZE]; - mpz_t x, y; - nettle_ecc_point_init(&pubkey, nettle_get_secp_384r1()); - nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key); - nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE); - nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock); - nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE); - res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), - (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); - res &= nettle_ecc_point_set(&pubkey, x, y); - res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature); - mpz_clear(x); - mpz_clear(y); - nettle_ecc_point_clear(&pubkey); - break; - } - default: - return "unknown ECDSA algorithm"; - } - - /* Clear and return */ - nettle_dsa_signature_clear(&signature); - if (!res) - return "ECDSA signature verification failed"; - else - return NULL; -} -#endif - -#ifdef USE_ED25519 -static char * -_verify_nettle_ed25519(sldns_buffer* buf, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen) -{ - int res = 0; - - if(sigblock_len != ED25519_SIGNATURE_SIZE) { - return "wrong ED25519 signature length"; - } - if(keylen != ED25519_KEY_SIZE) { - return "wrong ED25519 key length"; - } - - res = ed25519_sha512_verify((uint8_t*)key, sldns_buffer_limit(buf), - sldns_buffer_begin(buf), (uint8_t*)sigblock); - - if (!res) - return "ED25519 signature verification failed"; - else - return NULL; -} -#endif - -/** - * Check a canonical sig+rrset and signature against a dnskey - * @param buf: buffer with data to verify, the first rrsig part and the - * canonicalized rrset. - * @param algo: DNSKEY algorithm. - * @param sigblock: signature rdata field from RRSIG - * @param sigblock_len: length of sigblock data. - * @param key: public key data from DNSKEY RR. - * @param keylen: length of keydata. - * @param reason: bogus reason in more detail. - * @return secure if verification succeeded, bogus on crypto failure, - * unchecked on format errors and alloc failures. - */ -enum sec_status -verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, - unsigned int sigblock_len, unsigned char* key, unsigned int keylen, - char** reason) -{ - unsigned int digest_size = 0; - - if (sigblock_len == 0 || keylen == 0) { - *reason = "null signature"; - return sec_status_bogus; - } - -#ifndef USE_DSA - if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1)) - return sec_status_secure; -#endif -#ifndef USE_SHA1 - if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3)) - return sec_status_secure; -#endif - - switch(algo) { -#if defined(USE_DSA) && defined(USE_SHA1) - case LDNS_DSA: - case LDNS_DSA_NSEC3: - *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); - if (*reason != NULL) - return sec_status_bogus; - else - return sec_status_secure; -#endif /* USE_DSA */ - -#ifdef USE_SHA1 - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: - digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE); -#endif - /* double fallthrough annotation to please gcc parser */ - /* fallthrough */ -#ifdef USE_SHA2 - /* fallthrough */ - case LDNS_RSASHA256: - digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); - /* fallthrough */ - case LDNS_RSASHA512: - digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE); - -#endif - *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock, - sigblock_len, key, keylen); - if (*reason != NULL) - return sec_status_bogus; - else - return sec_status_secure; - -#ifdef USE_ECDSA - case LDNS_ECDSAP256SHA256: - digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); - /* fallthrough */ - case LDNS_ECDSAP384SHA384: - digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE); - *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock, - sigblock_len, key, keylen); - if (*reason != NULL) - return sec_status_bogus; - else - return sec_status_secure; -#endif -#ifdef USE_ED25519 - case LDNS_ED25519: - *reason = _verify_nettle_ed25519(buf, sigblock, sigblock_len, - key, keylen); - if (*reason != NULL) - return sec_status_bogus; - else - return sec_status_secure; -#endif - case LDNS_RSAMD5: - case LDNS_ECC_GOST: - default: - *reason = "unable to verify signature, unknown algorithm"; - return sec_status_bogus; - } -} - -#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */ diff --git a/crates/libunbound-sys/unbound/validator/val_secalgo.h b/crates/libunbound-sys/unbound/validator/val_secalgo.h deleted file mode 100644 index 8b6080dc..00000000 --- a/crates/libunbound-sys/unbound/validator/val_secalgo.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * validator/val_secalgo.h - validator security algorithm functions. - * - * Copyright (c) 2012, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions take buffers with raw data and convert to library calls. - */ - -#ifndef VALIDATOR_VAL_SECALGO_H -#define VALIDATOR_VAL_SECALGO_H -struct sldns_buffer; -struct secalgo_hash; - -/** Return size of nsec3 hash algorithm, 0 if not supported */ -size_t nsec3_hash_algo_size_supported(int id); - -/** - * Hash a single hash call of an NSEC3 hash algorithm. - * Iterations and salt are done by the caller. - * @param algo: nsec3 hash algorithm. - * @param buf: the buffer to digest - * @param len: length of buffer to digest. - * @param res: result stored here (must have sufficient space). - * @return false on failure. -*/ -int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, - unsigned char* res); - -/** - * Calculate the sha256 hash for the data buffer into the result. - * @param buf: buffer to digest. - * @param len: length of the buffer to digest. - * @param res: result is stored here (space 256/8 bytes). - */ -void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res); - -/** - * Start a hash of type sha384. Allocates structure, then inits it, - * so that a series of updates can be performed, before the final result. - * @return hash structure. NULL on malloc failure or no support. - */ -struct secalgo_hash* secalgo_hash_create_sha384(void); - -/** - * Start a hash of type sha512. Allocates structure, then inits it, - * so that a series of updates can be performed, before the final result. - * @return hash structure. NULL on malloc failure or no support. - */ -struct secalgo_hash* secalgo_hash_create_sha512(void); - -/** - * Update a hash with more information to add to it. - * @param hash: the hash that is updated. - * @param data: data to add. - * @param len: length of data. - * @return false on failure. - */ -int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len); - -/** - * Get the final result of the hash. - * @param hash: the hash that has had updates to it. - * @param result: where to store the result. - * @param maxlen: length of the result buffer, eg. size of the allocation. - * If not large enough the routine fails. - * @param resultlen: the length of the result, returned to the caller. - * How much of maxlen is used. - * @return false on failure. - */ -int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result, - size_t maxlen, size_t* resultlen); - -/** - * Delete the hash structure. - * @param hash: the hash to delete. - */ -void secalgo_hash_delete(struct secalgo_hash* hash); - -/** - * Return size of DS digest according to its hash algorithm. - * @param algo: DS digest algo. - * @return size in bytes of digest, or 0 if not supported. - */ -size_t ds_digest_size_supported(int algo); - -/** - * @param algo: the DS digest algo - * @param buf: the buffer to digest - * @param len: length of buffer to digest. - * @param res: result stored here (must have sufficient space). - * @return false on failure. - */ -int secalgo_ds_digest(int algo, unsigned char* buf, size_t len, - unsigned char* res); - -/** return true if DNSKEY algorithm id is supported */ -int dnskey_algo_id_is_supported(int id); - -/** - * Check a canonical sig+rrset and signature against a dnskey - * @param buf: buffer with data to verify, the first rrsig part and the - * canonicalized rrset. - * @param algo: DNSKEY algorithm. - * @param sigblock: signature rdata field from RRSIG - * @param sigblock_len: length of sigblock data. - * @param key: public key data from DNSKEY RR. - * @param keylen: length of keydata. - * @param reason: bogus reason in more detail. - * @return secure if verification succeeded, bogus on crypto failure, - * unchecked on format errors and alloc failures. - */ -enum sec_status verify_canonrrset(struct sldns_buffer* buf, int algo, - unsigned char* sigblock, unsigned int sigblock_len, - unsigned char* key, unsigned int keylen, char** reason); - -#endif /* VALIDATOR_VAL_SECALGO_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_sigcrypt.c b/crates/libunbound-sys/unbound/validator/val_sigcrypt.c deleted file mode 100644 index 37730f17..00000000 --- a/crates/libunbound-sys/unbound/validator/val_sigcrypt.c +++ /dev/null @@ -1,1663 +0,0 @@ -/* - * validator/val_sigcrypt.c - validator signature crypto functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with signature verification and checking, the - * bridging between RR wireformat data and crypto calls. - */ -#include "config.h" -#include "validator/val_sigcrypt.h" -#include "validator/val_secalgo.h" -#include "validator/validator.h" -#include "util/data/msgreply.h" -#include "util/data/msgparse.h" -#include "util/data/dname.h" -#include "util/rbtree.h" -#include "util/rfc_1982.h" -#include "util/module.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "sldns/keyraw.h" -#include "sldns/sbuffer.h" -#include "sldns/parseutil.h" -#include "sldns/wire2str.h" - -#include -#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE) -#error "Need crypto library to do digital signature cryptography" -#endif - -#ifdef HAVE_OPENSSL_ERR_H -#include -#endif - -#ifdef HAVE_OPENSSL_RAND_H -#include -#endif - -#ifdef HAVE_OPENSSL_CONF_H -#include -#endif - -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif - -/** return number of rrs in an rrset */ -static size_t -rrset_get_count(struct ub_packed_rrset_key* rrset) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - if(!d) return 0; - return d->count; -} - -/** - * Get RR signature count - */ -static size_t -rrset_get_sigcount(struct ub_packed_rrset_key* k) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - return d->rrsig_count; -} - -/** - * Get signature keytag value - * @param k: rrset (with signatures) - * @param sig_idx: signature index. - * @return keytag or 0 if malformed rrsig. - */ -static uint16_t -rrset_get_sig_keytag(struct ub_packed_rrset_key* k, size_t sig_idx) -{ - uint16_t t; - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - log_assert(sig_idx < d->rrsig_count); - if(d->rr_len[d->count + sig_idx] < 2+18) - return 0; - memmove(&t, d->rr_data[d->count + sig_idx]+2+16, 2); - return ntohs(t); -} - -/** - * Get signature signing algorithm value - * @param k: rrset (with signatures) - * @param sig_idx: signature index. - * @return algo or 0 if malformed rrsig. - */ -static int -rrset_get_sig_algo(struct ub_packed_rrset_key* k, size_t sig_idx) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - log_assert(sig_idx < d->rrsig_count); - if(d->rr_len[d->count + sig_idx] < 2+3) - return 0; - return (int)d->rr_data[d->count + sig_idx][2+2]; -} - -/** get rdata pointer and size */ -static void -rrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata, - size_t* len) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - log_assert(d && idx < (d->count + d->rrsig_count)); - *rdata = d->rr_data[idx]; - *len = d->rr_len[idx]; -} - -uint16_t -dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx) -{ - uint8_t* rdata; - size_t len; - uint16_t f; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+2) - return 0; - memmove(&f, rdata+2, 2); - f = ntohs(f); - return f; -} - -/** - * Get DNSKEY protocol value from rdata - * @param k: DNSKEY rrset. - * @param idx: which key. - * @return protocol octet value - */ -static int -dnskey_get_protocol(struct ub_packed_rrset_key* k, size_t idx) -{ - uint8_t* rdata; - size_t len; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+4) - return 0; - return (int)rdata[2+2]; -} - -int -dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx) -{ - uint8_t* rdata; - size_t len; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+4) - return 0; - return (int)rdata[2+3]; -} - -/** get public key rdata field from a dnskey RR and do some checks */ -static void -dnskey_get_pubkey(struct ub_packed_rrset_key* k, size_t idx, - unsigned char** pk, unsigned int* pklen) -{ - uint8_t* rdata; - size_t len; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+5) { - *pk = NULL; - *pklen = 0; - return; - } - *pk = (unsigned char*)rdata+2+4; - *pklen = (unsigned)len-2-4; -} - -int -ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx) -{ - uint8_t* rdata; - size_t len; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+3) - return 0; - return (int)rdata[2+2]; -} - -int -ds_get_digest_algo(struct ub_packed_rrset_key* k, size_t idx) -{ - uint8_t* rdata; - size_t len; - rrset_get_rdata(k, idx, &rdata, &len); - if(len < 2+4) - return 0; - return (int)rdata[2+3]; -} - -uint16_t -ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx) -{ - uint16_t t; - uint8_t* rdata; - size_t len; - rrset_get_rdata(ds_rrset, ds_idx, &rdata, &len); - if(len < 2+2) - return 0; - memmove(&t, rdata+2, 2); - return ntohs(t); -} - -/** - * Return pointer to the digest in a DS RR. - * @param k: DS rrset. - * @param idx: which DS. - * @param digest: digest data is returned. - * on error, this is NULL. - * @param len: length of digest is returned. - * on error, the length is 0. - */ -static void -ds_get_sigdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** digest, - size_t* len) -{ - uint8_t* rdata; - size_t rdlen; - rrset_get_rdata(k, idx, &rdata, &rdlen); - if(rdlen < 2+5) { - *digest = NULL; - *len = 0; - return; - } - *digest = rdata + 2 + 4; - *len = rdlen - 2 - 4; -} - -/** - * Return size of DS digest according to its hash algorithm. - * @param k: DS rrset. - * @param idx: which DS. - * @return size in bytes of digest, or 0 if not supported. - */ -static size_t -ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx) -{ - return ds_digest_size_supported(ds_get_digest_algo(k, idx)); -} - -/** - * Create a DS digest for a DNSKEY entry. - * - * @param env: module environment. Uses scratch space. - * @param dnskey_rrset: DNSKEY rrset. - * @param dnskey_idx: index of RR in rrset. - * @param ds_rrset: DS rrset - * @param ds_idx: index of RR in DS rrset. - * @param digest: digest is returned in here (must be correctly sized). - * @return false on error. - */ -static int -ds_create_dnskey_digest(struct module_env* env, - struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, - struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, - uint8_t* digest) -{ - sldns_buffer* b = env->scratch_buffer; - uint8_t* dnskey_rdata; - size_t dnskey_len; - rrset_get_rdata(dnskey_rrset, dnskey_idx, &dnskey_rdata, &dnskey_len); - - /* create digest source material in buffer - * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); - * DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. */ - sldns_buffer_clear(b); - sldns_buffer_write(b, dnskey_rrset->rk.dname, - dnskey_rrset->rk.dname_len); - query_dname_tolower(sldns_buffer_begin(b)); - sldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/ - sldns_buffer_flip(b); - - return secalgo_ds_digest(ds_get_digest_algo(ds_rrset, ds_idx), - (unsigned char*)sldns_buffer_begin(b), sldns_buffer_limit(b), - (unsigned char*)digest); -} - -int ds_digest_match_dnskey(struct module_env* env, - struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, - struct ub_packed_rrset_key* ds_rrset, size_t ds_idx) -{ - uint8_t* ds; /* DS digest */ - size_t dslen; - uint8_t* digest; /* generated digest */ - size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx); - - if(digestlen == 0) { - verbose(VERB_QUERY, "DS fail: not supported, or DS RR " - "format error"); - return 0; /* not supported, or DS RR format error */ - } -#ifndef USE_SHA1 - if(fake_sha1 && ds_get_digest_algo(ds_rrset, ds_idx)==LDNS_SHA1) - return 1; -#endif - - /* check digest length in DS with length from hash function */ - ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen); - if(!ds || dslen != digestlen) { - verbose(VERB_QUERY, "DS fail: DS RR algo and digest do not " - "match each other"); - return 0; /* DS algorithm and digest do not match */ - } - - digest = regional_alloc(env->scratch, digestlen); - if(!digest) { - verbose(VERB_QUERY, "DS fail: out of memory"); - return 0; /* mem error */ - } - if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, - ds_idx, digest)) { - verbose(VERB_QUERY, "DS fail: could not calc key digest"); - return 0; /* digest algo failed */ - } - if(memcmp(digest, ds, dslen) != 0) { - verbose(VERB_QUERY, "DS fail: digest is different"); - return 0; /* digest different */ - } - return 1; -} - -int -ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, - size_t ds_idx) -{ - return (ds_digest_size_algo(ds_rrset, ds_idx) != 0); -} - -int -ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, - size_t ds_idx) -{ - return dnskey_algo_id_is_supported(ds_get_key_algo(ds_rrset, ds_idx)); -} - -uint16_t -dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx) -{ - uint8_t* data; - size_t len; - rrset_get_rdata(dnskey_rrset, dnskey_idx, &data, &len); - /* do not pass rdatalen to ldns */ - return sldns_calc_keytag_raw(data+2, len-2); -} - -int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, - size_t dnskey_idx) -{ - return dnskey_algo_id_is_supported(dnskey_get_algo(dnskey_rrset, - dnskey_idx)); -} - -int dnskey_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset, - size_t dnskey_idx) -{ -#ifdef DEPRECATE_RSA_1024 - uint8_t* rdata; - size_t len; - int alg = dnskey_get_algo(dnskey_rrset, dnskey_idx); - size_t keysize; - - rrset_get_rdata(dnskey_rrset, dnskey_idx, &rdata, &len); - if(len < 2+4) - return 0; - keysize = sldns_rr_dnskey_key_size_raw(rdata+2+4, len-2-4, alg); - - switch((sldns_algorithm)alg) { - case LDNS_RSAMD5: - case LDNS_RSASHA1: - case LDNS_RSASHA1_NSEC3: - case LDNS_RSASHA256: - case LDNS_RSASHA512: - /* reject RSA keys of 1024 bits and shorter */ - if(keysize <= 1024) - return 0; - break; - default: - break; - } -#else - (void)dnskey_rrset; (void)dnskey_idx; -#endif /* DEPRECATE_RSA_1024 */ - return 1; -} - -int dnskeyset_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset) -{ - size_t i, num = rrset_get_count(dnskey_rrset); - for(i=0; inum; - size_t num = rrset_get_count(dnskey); - - for(i=0; ineeds[algo] == 0) { - n->needs[algo] = 1; - sigalg[total] = algo; - total++; - } - } - sigalg[total] = 0; - n->num = total; -} - -void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg) -{ - uint8_t algo; - size_t total = 0; - - memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX); - while( (algo=*sigalg++) != 0) { - log_assert(dnskey_algo_id_is_supported((int)algo)); - log_assert(n->needs[algo] == 0); - n->needs[algo] = 1; - total++; - } - n->num = total; -} - -void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, - int fav_ds_algo, uint8_t* sigalg) -{ - uint8_t algo; - size_t i, total = 0; - size_t num = rrset_get_count(ds); - - memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX); - for(i=0; ineeds[algo] == 0) { - n->needs[algo] = 1; - sigalg[total] = algo; - total++; - } - } - sigalg[total] = 0; - n->num = total; -} - -int algo_needs_set_secure(struct algo_needs* n, uint8_t algo) -{ - if(n->needs[algo]) { - n->needs[algo] = 0; - n->num --; - if(n->num == 0) /* done! */ - return 1; - } - return 0; -} - -void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo) -{ - if(n->needs[algo]) n->needs[algo] = 2; /* need it, but bogus */ -} - -size_t algo_needs_num_missing(struct algo_needs* n) -{ - return n->num; -} - -int algo_needs_missing(struct algo_needs* n) -{ - int i, miss = -1; - /* check if a needed algo was bogus - report that; - * check the first missing algo - report that; - * or return 0 */ - for(i=0; ineeds[i] == 2) - return 0; - if(n->needs[i] == 1 && miss == -1) - miss = i; - } - if(miss != -1) return miss; - return 0; -} - -/** - * verify rrset, with dnskey rrset, for a specific rrsig in rrset - * @param env: module environment, scratch space is used. - * @param ve: validator environment, date settings. - * @param now: current time for validation (can be overridden). - * @param rrset: to be validated. - * @param dnskey: DNSKEY rrset, keyset to try. - * @param sig_idx: which signature to try to validate. - * @param sortree: reused sorted order. Stored in region. Pass NULL at start, - * and for a new rrset. - * @param reason: if bogus, a string returned, fixed or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return secure if any key signs *this* signature. bogus if no key signs it, - * unchecked on error, or indeterminate if all keys are not supported by - * the crypto library (openssl3+ only). - */ -static enum sec_status -dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, - time_t now, struct ub_packed_rrset_key* rrset, - struct ub_packed_rrset_key* dnskey, size_t sig_idx, - struct rbtree_type** sortree, - char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - /* find matching keys and check them */ - enum sec_status sec = sec_status_bogus; - uint16_t tag = rrset_get_sig_keytag(rrset, sig_idx); - int algo = rrset_get_sig_algo(rrset, sig_idx); - size_t i, num = rrset_get_count(dnskey); - size_t numchecked = 0; - size_t numindeterminate = 0; - int buf_canon = 0; - verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo); - if(!dnskey_algo_id_is_supported(algo)) { - if(reason_bogus) - *reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG; - verbose(VERB_QUERY, "verify sig: unknown algorithm"); - return sec_status_insecure; - } - - for(i=0; iscratch, - env->scratch_buffer, ve, now, rrset, dnskey, i, - sig_idx, sortree, &buf_canon, reason, reason_bogus, - section, qstate); - if(sec == sec_status_secure) - return sec; - else if(sec == sec_status_indeterminate) - numindeterminate ++; - } - if(numchecked == 0) { - *reason = "signatures from unknown keys"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSKEY_MISSING; - verbose(VERB_QUERY, "verify: could not find appropriate key"); - return sec_status_bogus; - } - if(numindeterminate == numchecked) { - *reason = "unsupported algorithm by crypto library"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG; - verbose(VERB_ALGO, "verify sig: unsupported algorithm by " - "crypto library"); - return sec_status_indeterminate; - } - return sec_status_bogus; -} - -enum sec_status -dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, - uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - enum sec_status sec; - size_t i, num; - rbtree_type* sortree = NULL; - /* make sure that for all DNSKEY algorithms there are valid sigs */ - struct algo_needs needs; - int alg; - - num = rrset_get_sigcount(rrset); - if(num == 0) { - verbose(VERB_QUERY, "rrset failed to verify due to a lack of " - "signatures"); - *reason = "no signatures"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_RRSIGS_MISSING; - return sec_status_bogus; - } - - if(sigalg) { - algo_needs_init_list(&needs, sigalg); - if(algo_needs_num_missing(&needs) == 0) { - verbose(VERB_QUERY, "zone has no known algorithms"); - *reason = "zone has no known algorithms"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG; - return sec_status_insecure; - } - } - for(i=0; inow, rrset, - dnskey, i, &sortree, reason, reason_bogus, - section, qstate); - /* see which algorithm has been fixed up */ - if(sec == sec_status_secure) { - if(!sigalg) - return sec; /* done! */ - else if(algo_needs_set_secure(&needs, - (uint8_t)rrset_get_sig_algo(rrset, i))) - return sec; /* done! */ - } else if(sigalg && sec == sec_status_bogus) { - algo_needs_set_bogus(&needs, - (uint8_t)rrset_get_sig_algo(rrset, i)); - } - } - if(sigalg && (alg=algo_needs_missing(&needs)) != 0) { - verbose(VERB_ALGO, "rrset failed to verify: " - "no valid signatures for %d algorithms", - (int)algo_needs_num_missing(&needs)); - algo_needs_reason(env, alg, reason, "no signatures"); - } else { - verbose(VERB_ALGO, "rrset failed to verify: " - "no valid signatures"); - } - return sec_status_bogus; -} - -void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s) -{ - char buf[256]; - sldns_lookup_table *t = sldns_lookup_by_id(sldns_algorithms, alg); - if(t&&t->name) - snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name); - else snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s, - (unsigned)alg); - *reason = regional_strdup(env->scratch, buf); - if(!*reason) - *reason = s; -} - -enum sec_status -dnskey_verify_rrset(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, - size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - enum sec_status sec; - size_t i, num, numchecked = 0, numindeterminate = 0; - rbtree_type* sortree = NULL; - int buf_canon = 0; - uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx); - int algo = dnskey_get_algo(dnskey, dnskey_idx); - - num = rrset_get_sigcount(rrset); - if(num == 0) { - verbose(VERB_QUERY, "rrset failed to verify due to a lack of " - "signatures"); - *reason = "no signatures"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_RRSIGS_MISSING; - return sec_status_bogus; - } - for(i=0; iscratch, - env->scratch_buffer, ve, *env->now, rrset, - dnskey, dnskey_idx, i, &sortree, &buf_canon, reason, - reason_bogus, section, qstate); - if(sec == sec_status_secure) - return sec; - numchecked ++; - if(sec == sec_status_indeterminate) - numindeterminate ++; - } - verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus"); - if(!numchecked) { - *reason = "signature for expected key and algorithm missing"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - } else if(numchecked == numindeterminate) { - verbose(VERB_ALGO, "rrset failed to verify due to algorithm " - "refusal by cryptolib"); - if(reason_bogus) - *reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG; - *reason = "algorithm refused by cryptolib"; - return sec_status_indeterminate; - } - return sec_status_bogus; -} - -/** - * RR entries in a canonical sorted tree of RRs - */ -struct canon_rr { - /** rbtree node, key is this structure */ - rbnode_type node; - /** rrset the RR is in */ - struct ub_packed_rrset_key* rrset; - /** which RR in the rrset */ - size_t rr_idx; -}; - -/** - * Compare two RR for canonical order, in a field-style sweep. - * @param d: rrset data - * @param desc: ldns wireformat descriptor. - * @param i: first RR to compare - * @param j: first RR to compare - * @return comparison code. - */ -static int -canonical_compare_byfield(struct packed_rrset_data* d, - const sldns_rr_descriptor* desc, size_t i, size_t j) -{ - /* sweep across rdata, keep track of some state: - * which rr field, and bytes left in field. - * current position in rdata, length left. - * are we in a dname, length left in a label. - */ - int wfi = -1; /* current wireformat rdata field (rdf) */ - int wfj = -1; - uint8_t* di = d->rr_data[i]+2; /* ptr to current rdata byte */ - uint8_t* dj = d->rr_data[j]+2; - size_t ilen = d->rr_len[i]-2; /* length left in rdata */ - size_t jlen = d->rr_len[j]-2; - int dname_i = 0; /* true if these bytes are part of a name */ - int dname_j = 0; - size_t lablen_i = 0; /* 0 for label length byte,for first byte of rdf*/ - size_t lablen_j = 0; /* otherwise remaining length of rdf or label */ - int dname_num_i = (int)desc->_dname_count; /* decreased at root label */ - int dname_num_j = (int)desc->_dname_count; - - /* loop while there are rdata bytes available for both rrs, - * and still some lowercasing needs to be done; either the dnames - * have not been reached yet, or they are currently being processed */ - while(ilen > 0 && jlen > 0 && (dname_num_i > 0 || dname_num_j > 0)) { - /* compare these two bytes */ - /* lowercase if in a dname and not a label length byte */ - if( ((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di) - != ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj) - ) { - if(((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di) - < ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj)) - return -1; - return 1; - } - ilen--; - jlen--; - /* bytes are equal */ - - /* advance field i */ - /* lablen 0 means that this byte is the first byte of the - * next rdata field; inspect this rdata field and setup - * to process the rest of this rdata field. - * The reason to first read the byte, then setup the rdf, - * is that we are then sure the byte is available and short - * rdata is handled gracefully (even if it is a formerr). */ - if(lablen_i == 0) { - if(dname_i) { - /* scan this dname label */ - /* capture length to lowercase */ - lablen_i = (size_t)*di; - if(lablen_i == 0) { - /* end root label */ - dname_i = 0; - dname_num_i--; - /* if dname num is 0, then the - * remainder is binary only */ - if(dname_num_i == 0) - lablen_i = ilen; - } - } else { - /* scan this rdata field */ - wfi++; - if(desc->_wireformat[wfi] - == LDNS_RDF_TYPE_DNAME) { - dname_i = 1; - lablen_i = (size_t)*di; - if(lablen_i == 0) { - dname_i = 0; - dname_num_i--; - if(dname_num_i == 0) - lablen_i = ilen; - } - } else if(desc->_wireformat[wfi] - == LDNS_RDF_TYPE_STR) - lablen_i = (size_t)*di; - else lablen_i = get_rdf_size( - desc->_wireformat[wfi]) - 1; - } - } else lablen_i--; - - /* advance field j; same as for i */ - if(lablen_j == 0) { - if(dname_j) { - lablen_j = (size_t)*dj; - if(lablen_j == 0) { - dname_j = 0; - dname_num_j--; - if(dname_num_j == 0) - lablen_j = jlen; - } - } else { - wfj++; - if(desc->_wireformat[wfj] - == LDNS_RDF_TYPE_DNAME) { - dname_j = 1; - lablen_j = (size_t)*dj; - if(lablen_j == 0) { - dname_j = 0; - dname_num_j--; - if(dname_num_j == 0) - lablen_j = jlen; - } - } else if(desc->_wireformat[wfj] - == LDNS_RDF_TYPE_STR) - lablen_j = (size_t)*dj; - else lablen_j = get_rdf_size( - desc->_wireformat[wfj]) - 1; - } - } else lablen_j--; - di++; - dj++; - } - /* end of the loop; because we advanced byte by byte; now we have - * that the rdata has ended, or that there is a binary remainder */ - /* shortest first */ - if(ilen == 0 && jlen == 0) - return 0; - if(ilen == 0) - return -1; - if(jlen == 0) - return 1; - /* binary remainder, capture comparison in wfi variable */ - if((wfi = memcmp(di, dj, (ilen. - */ -static int -canonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - const sldns_rr_descriptor* desc; - uint16_t type = ntohs(rrset->rk.type); - size_t minlen; - int c; - - if(i==j) - return 0; - - switch(type) { - /* These RR types have only a name as RDATA. - * This name has to be canonicalized.*/ - case LDNS_RR_TYPE_NS: - case LDNS_RR_TYPE_MD: - case LDNS_RR_TYPE_MF: - case LDNS_RR_TYPE_CNAME: - case LDNS_RR_TYPE_MB: - case LDNS_RR_TYPE_MG: - case LDNS_RR_TYPE_MR: - case LDNS_RR_TYPE_PTR: - case LDNS_RR_TYPE_DNAME: - /* the wireread function has already checked these - * dname's for correctness, and this double checks */ - if(!dname_valid(d->rr_data[i]+2, d->rr_len[i]-2) || - !dname_valid(d->rr_data[j]+2, d->rr_len[j]-2)) - return 0; - return query_dname_compare(d->rr_data[i]+2, - d->rr_data[j]+2); - - /* These RR types have STR and fixed size rdata fields - * before one or more name fields that need canonicalizing, - * and after that a byte-for byte remainder can be compared. - */ - /* type starts with the name; remainder is binary compared */ - case LDNS_RR_TYPE_NXT: - /* use rdata field formats */ - case LDNS_RR_TYPE_MINFO: - case LDNS_RR_TYPE_RP: - case LDNS_RR_TYPE_SOA: - case LDNS_RR_TYPE_RT: - case LDNS_RR_TYPE_AFSDB: - case LDNS_RR_TYPE_KX: - case LDNS_RR_TYPE_MX: - case LDNS_RR_TYPE_SIG: - /* RRSIG signer name has to be downcased */ - case LDNS_RR_TYPE_RRSIG: - case LDNS_RR_TYPE_PX: - case LDNS_RR_TYPE_NAPTR: - case LDNS_RR_TYPE_SRV: - desc = sldns_rr_descript(type); - log_assert(desc); - /* this holds for the types that need canonicalizing */ - log_assert(desc->_minimum == desc->_maximum); - return canonical_compare_byfield(d, desc, i, j); - - case LDNS_RR_TYPE_HINFO: /* no longer downcased */ - case LDNS_RR_TYPE_NSEC: - default: - /* For unknown RR types, or types not listed above, - * no canonicalization is needed, do binary compare */ - /* byte for byte compare, equal means shortest first*/ - minlen = d->rr_len[i]-2; - if(minlen > d->rr_len[j]-2) - minlen = d->rr_len[j]-2; - c = memcmp(d->rr_data[i]+2, d->rr_data[j]+2, minlen); - if(c!=0) - return c; - /* rdata equal, shortest is first */ - if(d->rr_len[i] < d->rr_len[j]) - return -1; - if(d->rr_len[i] > d->rr_len[j]) - return 1; - /* rdata equal, length equal */ - break; - } - return 0; -} - -int -canonical_tree_compare(const void* k1, const void* k2) -{ - struct canon_rr* r1 = (struct canon_rr*)k1; - struct canon_rr* r2 = (struct canon_rr*)k2; - log_assert(r1->rrset == r2->rrset); - return canonical_compare(r1->rrset, r1->rr_idx, r2->rr_idx); -} - -/** - * Sort RRs for rrset in canonical order. - * Does not actually canonicalize the RR rdatas. - * Does not touch rrsigs. - * @param rrset: to sort. - * @param d: rrset data. - * @param sortree: tree to sort into. - * @param rrs: rr storage. - */ -static void -canonical_sort(struct ub_packed_rrset_key* rrset, struct packed_rrset_data* d, - rbtree_type* sortree, struct canon_rr* rrs) -{ - size_t i; - /* insert into rbtree to sort and detect duplicates */ - for(i=0; icount; i++) { - rrs[i].node.key = &rrs[i]; - rrs[i].rrset = rrset; - rrs[i].rr_idx = i; - if(!rbtree_insert(sortree, &rrs[i].node)) { - /* this was a duplicate */ - } - } -} - -/** - * Insert canonical owner name into buffer. - * @param buf: buffer to insert into at current position. - * @param k: rrset with its owner name. - * @param sig: signature with signer name and label count. - * must be length checked, at least 18 bytes long. - * @param can_owner: position in buffer returned for future use. - * @param can_owner_len: length of canonical owner name. - */ -static void -insert_can_owner(sldns_buffer* buf, struct ub_packed_rrset_key* k, - uint8_t* sig, uint8_t** can_owner, size_t* can_owner_len) -{ - int rrsig_labels = (int)sig[3]; - int fqdn_labels = dname_signame_label_count(k->rk.dname); - *can_owner = sldns_buffer_current(buf); - if(rrsig_labels == fqdn_labels) { - /* no change */ - sldns_buffer_write(buf, k->rk.dname, k->rk.dname_len); - query_dname_tolower(*can_owner); - *can_owner_len = k->rk.dname_len; - return; - } - log_assert(rrsig_labels < fqdn_labels); - /* *. | fqdn(rightmost rrsig_labels) */ - if(rrsig_labels < fqdn_labels) { - int i; - uint8_t* nm = k->rk.dname; - size_t len = k->rk.dname_len; - /* so skip fqdn_labels-rrsig_labels */ - for(i=0; irk.type)) { - case LDNS_RR_TYPE_NXT: - case LDNS_RR_TYPE_NS: - case LDNS_RR_TYPE_MD: - case LDNS_RR_TYPE_MF: - case LDNS_RR_TYPE_CNAME: - case LDNS_RR_TYPE_MB: - case LDNS_RR_TYPE_MG: - case LDNS_RR_TYPE_MR: - case LDNS_RR_TYPE_PTR: - case LDNS_RR_TYPE_DNAME: - /* type only has a single argument, the name */ - query_dname_tolower(datstart); - return; - case LDNS_RR_TYPE_MINFO: - case LDNS_RR_TYPE_RP: - case LDNS_RR_TYPE_SOA: - /* two names after another */ - query_dname_tolower(datstart); - query_dname_tolower(datstart + - dname_valid(datstart, len-2)); - return; - case LDNS_RR_TYPE_RT: - case LDNS_RR_TYPE_AFSDB: - case LDNS_RR_TYPE_KX: - case LDNS_RR_TYPE_MX: - /* skip fixed part */ - if(len < 2+2+1) /* rdlen, skiplen, 1byteroot */ - return; - datstart += 2; - query_dname_tolower(datstart); - return; - case LDNS_RR_TYPE_SIG: - /* downcase the RRSIG, compat with BIND (kept it from SIG) */ - case LDNS_RR_TYPE_RRSIG: - /* skip fixed part */ - if(len < 2+18+1) - return; - datstart += 18; - query_dname_tolower(datstart); - return; - case LDNS_RR_TYPE_PX: - /* skip, then two names after another */ - if(len < 2+2+1) - return; - datstart += 2; - query_dname_tolower(datstart); - query_dname_tolower(datstart + - dname_valid(datstart, len-2-2)); - return; - case LDNS_RR_TYPE_NAPTR: - if(len < 2+4) - return; - len -= 2+4; - datstart += 4; - if(len < (size_t)datstart[0]+1) /* skip text field */ - return; - len -= (size_t)datstart[0]+1; - datstart += (size_t)datstart[0]+1; - if(len < (size_t)datstart[0]+1) /* skip text field */ - return; - len -= (size_t)datstart[0]+1; - datstart += (size_t)datstart[0]+1; - if(len < (size_t)datstart[0]+1) /* skip text field */ - return; - len -= (size_t)datstart[0]+1; - datstart += (size_t)datstart[0]+1; - if(len < 1) /* check name is at least 1 byte*/ - return; - query_dname_tolower(datstart); - return; - case LDNS_RR_TYPE_SRV: - /* skip fixed part */ - if(len < 2+6+1) - return; - datstart += 6; - query_dname_tolower(datstart); - return; - - /* do not canonicalize NSEC rdata name, compat with - * from bind 9.4 signer, where it does not do so */ - case LDNS_RR_TYPE_NSEC: /* type starts with the name */ - case LDNS_RR_TYPE_HINFO: /* not downcased */ - /* A6 not supported */ - default: - /* nothing to do for unknown types */ - return; - } -} - -int rrset_canonical_equal(struct regional* region, - struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) -{ - struct rbtree_type sortree1, sortree2; - struct canon_rr *rrs1, *rrs2, *p1, *p2; - struct packed_rrset_data* d1=(struct packed_rrset_data*)k1->entry.data; - struct packed_rrset_data* d2=(struct packed_rrset_data*)k2->entry.data; - struct ub_packed_rrset_key fk; - struct packed_rrset_data fd; - size_t flen[2]; - uint8_t* fdata[2]; - - /* basic compare */ - if(k1->rk.dname_len != k2->rk.dname_len || - k1->rk.flags != k2->rk.flags || - k1->rk.type != k2->rk.type || - k1->rk.rrset_class != k2->rk.rrset_class || - query_dname_compare(k1->rk.dname, k2->rk.dname) != 0) - return 0; - if(d1->ttl != d2->ttl || - d1->count != d2->count || - d1->rrsig_count != d2->rrsig_count || - d1->trust != d2->trust || - d1->security != d2->security) - return 0; - - /* init */ - memset(&fk, 0, sizeof(fk)); - memset(&fd, 0, sizeof(fd)); - fk.entry.data = &fd; - fd.count = 2; - fd.rr_len = flen; - fd.rr_data = fdata; - rbtree_init(&sortree1, &canonical_tree_compare); - rbtree_init(&sortree2, &canonical_tree_compare); - if(d1->count > RR_COUNT_MAX || d2->count > RR_COUNT_MAX) - return 1; /* protection against integer overflow */ - rrs1 = regional_alloc(region, sizeof(struct canon_rr)*d1->count); - rrs2 = regional_alloc(region, sizeof(struct canon_rr)*d2->count); - if(!rrs1 || !rrs2) return 1; /* alloc failure */ - - /* sort */ - canonical_sort(k1, d1, &sortree1, rrs1); - canonical_sort(k2, d2, &sortree2, rrs2); - - /* compare canonical-sorted RRs for canonical-equality */ - if(sortree1.count != sortree2.count) - return 0; - p1 = (struct canon_rr*)rbtree_first(&sortree1); - p2 = (struct canon_rr*)rbtree_first(&sortree2); - while(p1 != (struct canon_rr*)RBTREE_NULL && - p2 != (struct canon_rr*)RBTREE_NULL) { - flen[0] = d1->rr_len[p1->rr_idx]; - flen[1] = d2->rr_len[p2->rr_idx]; - fdata[0] = d1->rr_data[p1->rr_idx]; - fdata[1] = d2->rr_data[p2->rr_idx]; - - if(canonical_compare(&fk, 0, 1) != 0) - return 0; - p1 = (struct canon_rr*)rbtree_next(&p1->node); - p2 = (struct canon_rr*)rbtree_next(&p2->node); - } - return 1; -} - -/** - * Create canonical form of rrset in the scratch buffer. - * @param region: temporary region. - * @param buf: the buffer to use. - * @param k: the rrset to insert. - * @param sig: RRSIG rdata to include. - * @param siglen: RRSIG rdata len excluding signature field, but inclusive - * signer name length. - * @param sortree: if NULL is passed a new sorted rrset tree is built. - * Otherwise it is reused. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return false on alloc error. - */ -static int -rrset_canonical(struct regional* region, sldns_buffer* buf, - struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen, - struct rbtree_type** sortree, sldns_pkt_section section, - struct module_qstate* qstate) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - uint8_t* can_owner = NULL; - size_t can_owner_len = 0; - struct canon_rr* walk; - struct canon_rr* rrs; - - if(!*sortree) { - *sortree = (struct rbtree_type*)regional_alloc(region, - sizeof(rbtree_type)); - if(!*sortree) - return 0; - if(d->count > RR_COUNT_MAX) - return 0; /* integer overflow protection */ - rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count); - if(!rrs) { - *sortree = NULL; - return 0; - } - rbtree_init(*sortree, &canonical_tree_compare); - canonical_sort(k, d, *sortree, rrs); - } - - sldns_buffer_clear(buf); - sldns_buffer_write(buf, sig, siglen); - /* canonicalize signer name */ - query_dname_tolower(sldns_buffer_begin(buf)+18); - RBTREE_FOR(walk, struct canon_rr*, (*sortree)) { - /* see if there is enough space left in the buffer */ - if(sldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4 - + d->rr_len[walk->rr_idx]) { - log_err("verify: failed to canonicalize, " - "rrset too big"); - return 0; - } - /* determine canonical owner name */ - if(can_owner) - sldns_buffer_write(buf, can_owner, can_owner_len); - else insert_can_owner(buf, k, sig, &can_owner, - &can_owner_len); - sldns_buffer_write(buf, &k->rk.type, 2); - sldns_buffer_write(buf, &k->rk.rrset_class, 2); - sldns_buffer_write(buf, sig+4, 4); - sldns_buffer_write(buf, d->rr_data[walk->rr_idx], - d->rr_len[walk->rr_idx]); - canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]); - } - sldns_buffer_flip(buf); - - /* Replace RR owner with canonical owner for NSEC records in authority - * section, to prevent that a wildcard synthesized NSEC can be used in - * the non-existence proves. */ - if(ntohs(k->rk.type) == LDNS_RR_TYPE_NSEC && - section == LDNS_SECTION_AUTHORITY && qstate) { - k->rk.dname = regional_alloc_init(qstate->region, can_owner, - can_owner_len); - if(!k->rk.dname) - return 0; - k->rk.dname_len = can_owner_len; - } - - - return 1; -} - -int -rrset_canonicalize_to_buffer(struct regional* region, sldns_buffer* buf, - struct ub_packed_rrset_key* k) -{ - struct rbtree_type* sortree = NULL; - struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; - uint8_t* can_owner = NULL; - size_t can_owner_len = 0; - struct canon_rr* walk; - struct canon_rr* rrs; - - sortree = (struct rbtree_type*)regional_alloc(region, - sizeof(rbtree_type)); - if(!sortree) - return 0; - if(d->count > RR_COUNT_MAX) - return 0; /* integer overflow protection */ - rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count); - if(!rrs) { - return 0; - } - rbtree_init(sortree, &canonical_tree_compare); - canonical_sort(k, d, sortree, rrs); - - sldns_buffer_clear(buf); - RBTREE_FOR(walk, struct canon_rr*, sortree) { - /* see if there is enough space left in the buffer */ - if(sldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4 - + d->rr_len[walk->rr_idx]) { - log_err("verify: failed to canonicalize, " - "rrset too big"); - return 0; - } - /* determine canonical owner name */ - if(can_owner) - sldns_buffer_write(buf, can_owner, can_owner_len); - else { - can_owner = sldns_buffer_current(buf); - sldns_buffer_write(buf, k->rk.dname, k->rk.dname_len); - query_dname_tolower(can_owner); - can_owner_len = k->rk.dname_len; - } - sldns_buffer_write(buf, &k->rk.type, 2); - sldns_buffer_write(buf, &k->rk.rrset_class, 2); - sldns_buffer_write_u32(buf, d->rr_ttl[walk->rr_idx]); - sldns_buffer_write(buf, d->rr_data[walk->rr_idx], - d->rr_len[walk->rr_idx]); - canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]); - } - sldns_buffer_flip(buf); - return 1; -} - -/** pretty print rrsig error with dates */ -static void -sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now) -{ - struct tm tm; - char expi_buf[16]; - char incep_buf[16]; - char now_buf[16]; - time_t te, ti, tn; - - if(verbosity < VERB_QUERY) - return; - te = (time_t)expi; - ti = (time_t)incep; - tn = (time_t)now; - memset(&tm, 0, sizeof(tm)); - if(gmtime_r(&te, &tm) && strftime(expi_buf, 15, "%Y%m%d%H%M%S", &tm) - &&gmtime_r(&ti, &tm) && strftime(incep_buf, 15, "%Y%m%d%H%M%S", &tm) - &&gmtime_r(&tn, &tm) && strftime(now_buf, 15, "%Y%m%d%H%M%S", &tm)) { - log_info("%s expi=%s incep=%s now=%s", str, expi_buf, - incep_buf, now_buf); - } else - log_info("%s expi=%u incep=%u now=%u", str, (unsigned)expi, - (unsigned)incep, (unsigned)now); -} - -/** check rrsig dates */ -static int -check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p, - uint8_t* incep_p, char** reason, sldns_ede_code *reason_bogus) -{ - /* read out the dates */ - uint32_t expi, incep, now; - memmove(&expi, expi_p, sizeof(expi)); - memmove(&incep, incep_p, sizeof(incep)); - expi = ntohl(expi); - incep = ntohl(incep); - - /* get current date */ - if(ve->date_override) { - if(ve->date_override == -1) { - verbose(VERB_ALGO, "date override: ignore date"); - return 1; - } - now = ve->date_override; - verbose(VERB_ALGO, "date override option %d", (int)now); - } else now = unow; - - /* check them */ - if(compare_1982(incep, expi) > 0) { - sigdate_error("verify: inception after expiration, " - "signature bad", expi, incep, now); - *reason = "signature inception after expiration"; - if(reason_bogus){ - /* from RFC8914 on Signature Not Yet Valid: The resolver - * attempted to perform DNSSEC validation, but no - * signatures are presently valid and at least some are - * not yet valid. */ - *reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID; - } - - return 0; - } - if(compare_1982(incep, now) > 0) { - /* within skew ? (calc here to avoid calculation normally) */ - uint32_t skew = subtract_1982(incep, expi)/10; - if(skew < (uint32_t)ve->skew_min) skew = ve->skew_min; - if(skew > (uint32_t)ve->skew_max) skew = ve->skew_max; - if(subtract_1982(now, incep) > skew) { - sigdate_error("verify: signature bad, current time is" - " before inception date", expi, incep, now); - *reason = "signature before inception date"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID; - return 0; - } - sigdate_error("verify warning suspicious signature inception " - " or bad local clock", expi, incep, now); - } - if(compare_1982(now, expi) > 0) { - uint32_t skew = subtract_1982(incep, expi)/10; - if(skew < (uint32_t)ve->skew_min) skew = ve->skew_min; - if(skew > (uint32_t)ve->skew_max) skew = ve->skew_max; - if(subtract_1982(expi, now) > skew) { - sigdate_error("verify: signature expired", expi, - incep, now); - *reason = "signature expired"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_SIGNATURE_EXPIRED; - return 0; - } - sigdate_error("verify warning suspicious signature expiration " - " or bad local clock", expi, incep, now); - } - return 1; -} - -/** adjust rrset TTL for verified rrset, compare to original TTL and expi */ -static void -adjust_ttl(struct val_env* ve, uint32_t unow, - struct ub_packed_rrset_key* rrset, uint8_t* orig_p, - uint8_t* expi_p, uint8_t* incep_p) -{ - struct packed_rrset_data* d = - (struct packed_rrset_data*)rrset->entry.data; - /* read out the dates */ - int32_t origttl, expittl, expi, incep, now; - memmove(&origttl, orig_p, sizeof(origttl)); - memmove(&expi, expi_p, sizeof(expi)); - memmove(&incep, incep_p, sizeof(incep)); - expi = ntohl(expi); - incep = ntohl(incep); - origttl = ntohl(origttl); - - /* get current date */ - if(ve->date_override) { - now = ve->date_override; - } else now = (int32_t)unow; - expittl = (int32_t)((uint32_t)expi - (uint32_t)now); - - /* so now: - * d->ttl: rrset ttl read from message or cache. May be reduced - * origttl: original TTL from signature, authoritative TTL max. - * MIN_TTL: minimum TTL from config. - * expittl: TTL until the signature expires. - * - * Use the smallest of these, but don't let origttl set the TTL - * below the minimum. - */ - if(MIN_TTL > (time_t)origttl && d->ttl > MIN_TTL) { - verbose(VERB_QUERY, "rrset TTL larger than original and minimum" - " TTL, adjusting TTL downwards to minimum ttl"); - d->ttl = MIN_TTL; - } - else if(MIN_TTL <= origttl && d->ttl > (time_t)origttl) { - verbose(VERB_QUERY, "rrset TTL larger than original TTL, " - "adjusting TTL downwards to original ttl"); - d->ttl = origttl; - } - - if(expittl > 0 && d->ttl > (time_t)expittl) { - verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl," - " adjusting TTL downwards"); - d->ttl = expittl; - } -} - -enum sec_status -dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf, - struct val_env* ve, time_t now, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, - size_t dnskey_idx, size_t sig_idx, - struct rbtree_type** sortree, int* buf_canon, - char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - enum sec_status sec; - uint8_t* sig; /* RRSIG rdata */ - size_t siglen; - size_t rrnum = rrset_get_count(rrset); - uint8_t* signer; /* rrsig signer name */ - size_t signer_len; - unsigned char* sigblock; /* signature rdata field */ - unsigned int sigblock_len; - uint16_t ktag; /* DNSKEY key tag */ - unsigned char* key; /* public key rdata field */ - unsigned int keylen; - rrset_get_rdata(rrset, rrnum + sig_idx, &sig, &siglen); - /* min length of rdatalen, fixed rrsig, root signer, 1 byte sig */ - if(siglen < 2+20) { - verbose(VERB_QUERY, "verify: signature too short"); - *reason = "signature too short"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - - if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) { - verbose(VERB_QUERY, "verify: dnskey without ZSK flag"); - *reason = "dnskey without ZSK flag"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_NO_ZONE_KEY_BIT_SET; - return sec_status_bogus; - } - - if(dnskey_get_protocol(dnskey, dnskey_idx) != LDNS_DNSSEC_KEYPROTO) { - /* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */ - verbose(VERB_QUERY, "verify: dnskey has wrong key protocol"); - *reason = "dnskey has wrong protocolnumber"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - - /* verify as many fields in rrsig as possible */ - signer = sig+2+18; - signer_len = dname_valid(signer, siglen-2-18); - if(!signer_len) { - verbose(VERB_QUERY, "verify: malformed signer name"); - *reason = "signer name malformed"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; /* signer name invalid */ - } - if(!dname_subdomain_c(rrset->rk.dname, signer)) { - verbose(VERB_QUERY, "verify: signer name is off-tree"); - *reason = "signer name off-tree"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; /* signer name offtree */ - } - sigblock = (unsigned char*)signer+signer_len; - if(siglen < 2+18+signer_len+1) { - verbose(VERB_QUERY, "verify: too short, no signature data"); - *reason = "signature too short, no signature data"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; /* sig rdf is < 1 byte */ - } - sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len); - - /* verify key dname == sig signer name */ - if(query_dname_compare(signer, dnskey->rk.dname) != 0) { - verbose(VERB_QUERY, "verify: wrong key for rrsig"); - log_nametypeclass(VERB_QUERY, "RRSIG signername is", - signer, 0, 0); - log_nametypeclass(VERB_QUERY, "the key name is", - dnskey->rk.dname, 0, 0); - *reason = "signer name mismatches key name"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - - /* verify covered type */ - /* memcmp works because type is in network format for rrset */ - if(memcmp(sig+2, &rrset->rk.type, 2) != 0) { - verbose(VERB_QUERY, "verify: wrong type covered"); - *reason = "signature covers wrong type"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - /* verify keytag and sig algo (possibly again) */ - if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) { - verbose(VERB_QUERY, "verify: wrong algorithm"); - *reason = "signature has wrong algorithm"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx)); - if(memcmp(sig+2+16, &ktag, 2) != 0) { - verbose(VERB_QUERY, "verify: wrong keytag"); - *reason = "signature has wrong keytag"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - - /* verify labels is in a valid range */ - if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) { - verbose(VERB_QUERY, "verify: labelcount out of range"); - *reason = "signature labelcount out of range"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - return sec_status_bogus; - } - - /* original ttl, always ok */ - - if(!*buf_canon) { - /* create rrset canonical format in buffer, ready for - * signature */ - if(!rrset_canonical(region, buf, rrset, sig+2, - 18 + signer_len, sortree, section, qstate)) { - log_err("verify: failed due to alloc error"); - return sec_status_unchecked; - } - *buf_canon = 1; - } - - /* check that dnskey is available */ - dnskey_get_pubkey(dnskey, dnskey_idx, &key, &keylen); - if(!key) { - verbose(VERB_QUERY, "verify: short DNSKEY RR"); - return sec_status_unchecked; - } - - /* verify */ - sec = verify_canonrrset(buf, (int)sig[2+2], - sigblock, sigblock_len, key, keylen, reason); - - if(sec == sec_status_secure) { - /* check if TTL is too high - reduce if so */ - adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12); - - /* verify inception, expiration dates - * Do this last so that if you ignore expired-sigs the - * rest is sure to be OK. */ - if(!check_dates(ve, now, sig+2+8, sig+2+12, - reason, reason_bogus)) { - return sec_status_bogus; - } - } - - return sec; -} diff --git a/crates/libunbound-sys/unbound/validator/val_sigcrypt.h b/crates/libunbound-sys/unbound/validator/val_sigcrypt.h deleted file mode 100644 index 7f52b71e..00000000 --- a/crates/libunbound-sys/unbound/validator/val_sigcrypt.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * validator/val_sigcrypt.h - validator signature crypto functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - * The functions help with signature verification and checking, the - * bridging between RR wireformat data and crypto calls. - */ - -#ifndef VALIDATOR_VAL_SIGCRYPT_H -#define VALIDATOR_VAL_SIGCRYPT_H -#include "util/data/packed_rrset.h" -#include "sldns/pkthdr.h" -#include "sldns/rrdef.h" -struct val_env; -struct module_env; -struct module_qstate; -struct ub_packed_rrset_key; -struct rbtree_type; -struct regional; -struct sldns_buffer; - -/** number of entries in algorithm needs array */ -#define ALGO_NEEDS_MAX 256 - -/** - * Storage for algorithm needs. DNSKEY algorithms. - */ -struct algo_needs { - /** the algorithms (8-bit) with each a number. - * 0: not marked. - * 1: marked 'necessary but not yet fulfilled' - * 2: marked bogus. - * Indexed by algorithm number. - */ - uint8_t needs[ALGO_NEEDS_MAX]; - /** the number of entries in the array that are unfulfilled */ - size_t num; -}; - -/** - * Initialize algo needs structure, set algos from rrset as needed. - * Results are added to an existing need structure. - * @param n: struct with storage. - * @param dnskey: algos from this struct set as necessary. DNSKEY set. - * @param sigalg: adds to signalled algorithm list too. - */ -void algo_needs_init_dnskey_add(struct algo_needs* n, - struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); - -/** - * Initialize algo needs structure from a signalled algo list. - * @param n: struct with storage. - * @param sigalg: signalled algorithm list, numbers ends with 0. - */ -void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); - -/** - * Initialize algo needs structure, set algos from rrset as needed. - * @param n: struct with storage. - * @param ds: algos from this struct set as necessary. DS set. - * @param fav_ds_algo: filter to use only this DS algo. - * @param sigalg: list of signalled algos, constructed as output, - * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. - */ -void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, - int fav_ds_algo, uint8_t* sigalg); - -/** - * Mark this algorithm as a success, sec_secure, and see if we are done. - * @param n: storage structure processed. - * @param algo: the algorithm processed to be secure. - * @return if true, processing has finished successfully, we are satisfied. - */ -int algo_needs_set_secure(struct algo_needs* n, uint8_t algo); - -/** - * Mark this algorithm a failure, sec_bogus. It can later be overridden - * by a success for this algorithm (with a different signature). - * @param n: storage structure processed. - * @param algo: the algorithm processed to be bogus. - */ -void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); - -/** - * See how many algorithms are missing (not bogus or secure, but not processed) - * @param n: storage structure processed. - * @return number of algorithms missing after processing. - */ -size_t algo_needs_num_missing(struct algo_needs* n); - -/** - * See which algo is missing. - * @param n: struct after processing. - * @return if 0 an algorithm was bogus, if a number, this algorithm was - * missing. So on 0, report why that was bogus, on number report a missing - * algorithm. There could be multiple missing, this reports the first one. - */ -int algo_needs_missing(struct algo_needs* n); - -/** - * Format error reason for algorithm missing. - * @param env: module env with scratch for temp storage of string. - * @param alg: DNSKEY-algorithm missing. - * @param reason: destination. - * @param s: string, appended with 'with algorithm ..'. - */ -void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s); - -/** - * Check if dnskey matches a DS digest - * Does not check dnskey-keyid footprint, just the digest. - * @param env: module environment. Uses scratch space. - * @param dnskey_rrset: DNSKEY rrset. - * @param dnskey_idx: index of RR in rrset. - * @param ds_rrset: DS rrset - * @param ds_idx: index of RR in DS rrset. - * @return true if it matches, false on error, not supported or no match. - */ -int ds_digest_match_dnskey(struct module_env* env, - struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, - struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); - -/** - * Get dnskey keytag, footprint value - * @param dnskey_rrset: DNSKEY rrset. - * @param dnskey_idx: index of RR in rrset. - * @return the keytag or 0 for badly formatted DNSKEYs. - */ -uint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, - size_t dnskey_idx); - -/** - * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. - * @param ds_rrset: DS rrset - * @param ds_idx: index of RR in DS rrset. - * @return the keytag or 0 for badly formatted DSs. - */ -uint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); - -/** - * See if DNSKEY algorithm is supported - * @param dnskey_rrset: DNSKEY rrset. - * @param dnskey_idx: index of RR in rrset. - * @return true if supported. - */ -int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, - size_t dnskey_idx); - -/** - * See if the DNSKEY size at that algorithm is supported. - * @param dnskey_rrset: DNSKEY rrset. - * @param dnskey_idx: index of RR in rrset. - * @return true if supported. - */ -int dnskey_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset, - size_t dnskey_idx); - -/** - * See if the DNSKEY size at that algorithm is supported for all the - * RRs in the DNSKEY RRset. - * @param dnskey_rrset: DNSKEY rrset. - * @return true if supported. - */ -int dnskeyset_size_is_supported(struct ub_packed_rrset_key* dnskey_rrset); - -/** - * See if DS digest algorithm is supported - * @param ds_rrset: DS rrset - * @param ds_idx: index of RR in DS rrset. - * @return true if supported. - */ -int ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, - size_t ds_idx); - -/** - * Get DS RR digest algorithm - * @param ds_rrset: DS rrset. - * @param ds_idx: which DS. - * @return algorithm or 0 if DS too short. - */ -int ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); - -/** - * See if DS key algorithm is supported - * @param ds_rrset: DS rrset - * @param ds_idx: index of RR in DS rrset. - * @return true if supported. - */ -int ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, - size_t ds_idx); - -/** - * Get DS RR key algorithm. This value should match with the DNSKEY algo. - * @param k: DS rrset. - * @param idx: which DS. - * @return algorithm or 0 if DS too short. - */ -int ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); - -/** - * Get DNSKEY RR signature algorithm - * @param k: DNSKEY rrset. - * @param idx: which DNSKEY RR. - * @return algorithm or 0 if DNSKEY too short. - */ -int dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); - -/** - * Get DNSKEY RR flags - * @param k: DNSKEY rrset. - * @param idx: which DNSKEY RR. - * @return flags or 0 if DNSKEY too short. - */ -uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); - -/** - * Verify rrset against dnskey rrset. - * @param env: module environment, scratch space is used. - * @param ve: validator environment, date settings. - * @param rrset: to be validated. - * @param dnskey: DNSKEY rrset, keyset to try. - * @param sigalg: if nonNULL provide downgrade protection otherwise one - * algorithm is enough. - * @param reason: if bogus, a string returned, fixed or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return SECURE if one key in the set verifies one rrsig. - * UNCHECKED on allocation errors, unsupported algorithms, malformed data, - * and BOGUS on verification failures (no keys match any signatures). - */ -enum sec_status dnskeyset_verify_rrset(struct module_env* env, - struct val_env* ve, struct ub_packed_rrset_key* rrset, - struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, - char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate); - - -/** - * verify rrset against one specific dnskey (from rrset) - * @param env: module environment, scratch space is used. - * @param ve: validator environment, date settings. - * @param rrset: to be validated. - * @param dnskey: DNSKEY rrset, keyset. - * @param dnskey_idx: which key from the rrset to try. - * @param reason: if bogus, a string returned, fixed or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return secure if *this* key signs any of the signatures on rrset. - * unchecked on error or and bogus on bad signature. - */ -enum sec_status dnskey_verify_rrset(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, - size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate); - -/** - * verify rrset, with specific dnskey(from set), for a specific rrsig - * @param region: scratch region used for temporary allocation. - * @param buf: scratch buffer used for canonicalized rrset data. - * @param ve: validator environment, date settings. - * @param now: current time for validation (can be overridden). - * @param rrset: to be validated. - * @param dnskey: DNSKEY rrset, keyset. - * @param dnskey_idx: which key from the rrset to try. - * @param sig_idx: which signature to try to validate. - * @param sortree: pass NULL at start, the sorted rrset order is returned. - * pass it again for the same rrset. - * @param buf_canon: if true, the buffer is already canonical. - * pass false at start. pass old value only for same rrset and same - * signature (but perhaps different key) for reuse. - * @param reason: if bogus, a string returned, fixed or alloced in scratch. - * @param reason_bogus: EDE (8914) code paired with the reason of failure. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return secure if this key signs this signature. unchecked on error or - * bogus if it did not validate. - */ -enum sec_status dnskey_verify_rrset_sig(struct regional* region, - struct sldns_buffer* buf, struct val_env* ve, time_t now, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, - size_t dnskey_idx, size_t sig_idx, - struct rbtree_type** sortree, int* buf_canon, - char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate); - -/** - * canonical compare for two tree entries - */ -int canonical_tree_compare(const void* k1, const void* k2); - -/** - * Compare two rrsets and see if they are the same, canonicalised. - * The rrsets are not altered. - * @param region: temporary region. - * @param k1: rrset1 - * @param k2: rrset2 - * @return true if equal. - */ -int rrset_canonical_equal(struct regional* region, - struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2); - -/** - * Canonicalize an rrset into the buffer. For an auth zone record, so - * this does not use a signature, or the RRSIG TTL or the wildcard label - * count from the RRSIG. - * @param region: temporary region. - * @param buf: the buffer to use. - * @param k: the rrset to insert. - * @return false on alloc error. - */ -int rrset_canonicalize_to_buffer(struct regional* region, - struct sldns_buffer* buf, struct ub_packed_rrset_key* k); - -#endif /* VALIDATOR_VAL_SIGCRYPT_H */ diff --git a/crates/libunbound-sys/unbound/validator/val_utils.c b/crates/libunbound-sys/unbound/validator/val_utils.c deleted file mode 100644 index 8b388882..00000000 --- a/crates/libunbound-sys/unbound/validator/val_utils.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * validator/val_utils.c - validator utility functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - */ -#include "config.h" -#include "validator/val_utils.h" -#include "validator/validator.h" -#include "validator/val_kentry.h" -#include "validator/val_sigcrypt.h" -#include "validator/val_anchor.h" -#include "validator/val_nsec.h" -#include "validator/val_neg.h" -#include "services/cache/rrset.h" -#include "services/cache/dns.h" -#include "util/data/msgreply.h" -#include "util/data/packed_rrset.h" -#include "util/data/dname.h" -#include "util/net_help.h" -#include "util/module.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "sldns/wire2str.h" -#include "sldns/parseutil.h" - -enum val_classification -val_classify_response(uint16_t query_flags, struct query_info* origqinf, - struct query_info* qinf, struct reply_info* rep, size_t skip) -{ - int rcode = (int)FLAGS_GET_RCODE(rep->flags); - size_t i; - - /* Normal Name Error's are easy to detect -- but don't mistake a CNAME - * chain ending in NXDOMAIN. */ - if(rcode == LDNS_RCODE_NXDOMAIN && rep->an_numrrsets == 0) - return VAL_CLASS_NAMEERROR; - - /* check for referral: nonRD query and it looks like a nodata */ - if(!(query_flags&BIT_RD) && rep->an_numrrsets == 0 && - rcode == LDNS_RCODE_NOERROR) { - /* SOA record in auth indicates it is NODATA instead. - * All validation requiring NODATA messages have SOA in - * authority section. */ - /* uses fact that answer section is empty */ - int saw_ns = 0; - for(i=0; ins_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA) - return VAL_CLASS_NODATA; - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DS) - return VAL_CLASS_REFERRAL; - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS) - saw_ns = 1; - } - return saw_ns?VAL_CLASS_REFERRAL:VAL_CLASS_NODATA; - } - /* root referral where NS set is in the answer section */ - if(!(query_flags&BIT_RD) && rep->ns_numrrsets == 0 && - rep->an_numrrsets == 1 && rcode == LDNS_RCODE_NOERROR && - ntohs(rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_NS && - query_dname_compare(rep->rrsets[0]->rk.dname, - origqinf->qname) != 0) - return VAL_CLASS_REFERRAL; - - /* dump bad messages */ - if(rcode != LDNS_RCODE_NOERROR && rcode != LDNS_RCODE_NXDOMAIN) - return VAL_CLASS_UNKNOWN; - /* next check if the skip into the answer section shows no answer */ - if(skip>0 && rep->an_numrrsets <= skip) - return VAL_CLASS_CNAMENOANSWER; - - /* Next is NODATA */ - if(rcode == LDNS_RCODE_NOERROR && rep->an_numrrsets == 0) - return VAL_CLASS_NODATA; - - /* We distinguish between CNAME response and other positive/negative - * responses because CNAME answers require extra processing. */ - - /* We distinguish between ANY and CNAME or POSITIVE because - * ANY responses are validated differently. */ - if(rcode == LDNS_RCODE_NOERROR && qinf->qtype == LDNS_RR_TYPE_ANY) - return VAL_CLASS_ANY; - - /* Note that DNAMEs will be ignored here, unless qtype=DNAME. Unless - * qtype=CNAME, this will yield a CNAME response. */ - for(i=skip; ian_numrrsets; i++) { - if(rcode == LDNS_RCODE_NOERROR && - ntohs(rep->rrsets[i]->rk.type) == qinf->qtype) - return VAL_CLASS_POSITIVE; - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME) - return VAL_CLASS_CNAME; - } - log_dns_msg("validator: error. failed to classify response message: ", - qinf, rep); - return VAL_CLASS_UNKNOWN; -} - -/** Get signer name from RRSIG */ -static void -rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname, size_t* slen) -{ - /* RRSIG rdata is not allowed to be compressed, it is stored - * uncompressed in memory as well, so return a ptr to the name */ - if(len < 21) { - /* too short RRSig: - * short, byte, byte, long, long, long, short, "." is - * 2 1 1 4 4 4 2 1 = 19 - * and a skip of 18 bytes to the name. - * +2 for the rdatalen is 21 bytes len for root label */ - *sname = NULL; - *slen = 0; - return; - } - data += 20; /* skip the fixed size bits */ - len -= 20; - *slen = dname_valid(data, len); - if(!*slen) { - /* bad dname in this rrsig. */ - *sname = NULL; - return; - } - *sname = data; -} - -void -val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname, - size_t* slen) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - /* return signer for first signature, or NULL */ - if(d->rrsig_count == 0) { - *sname = NULL; - *slen = 0; - return; - } - /* get rrsig signer name out of the signature */ - rrsig_get_signer(d->rr_data[d->count], d->rr_len[d->count], - sname, slen); -} - -/** - * Find best signer name in this set of rrsigs. - * @param rrset: which rrsigs to look through. - * @param qinf: the query name that needs validation. - * @param signer_name: the best signer_name. Updated if a better one is found. - * @param signer_len: length of signer name. - * @param matchcount: count of current best name (starts at 0 for no match). - * Updated if match is improved. - */ -static void -val_find_best_signer(struct ub_packed_rrset_key* rrset, - struct query_info* qinf, uint8_t** signer_name, size_t* signer_len, - int* matchcount) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - uint8_t* sign; - size_t i; - int m; - for(i=d->count; icount+d->rrsig_count; i++) { - sign = d->rr_data[i]+2+18; - /* look at signatures that are valid (long enough), - * and have a signer name that is a superdomain of qname, - * and then check the number of labels in the shared topdomain - * improve the match if possible */ - if(d->rr_len[i] > 2+19 && /* rdata, sig + root label*/ - dname_subdomain_c(qinf->qname, sign)) { - (void)dname_lab_cmp(qinf->qname, - dname_count_labels(qinf->qname), - sign, dname_count_labels(sign), &m); - if(m > *matchcount) { - *matchcount = m; - *signer_name = sign; - (void)dname_count_size_labels(*signer_name, - signer_len); - } - } - } -} - -void -val_find_signer(enum val_classification subtype, struct query_info* qinf, - struct reply_info* rep, size_t skip, uint8_t** signer_name, - size_t* signer_len) -{ - size_t i; - - if(subtype == VAL_CLASS_POSITIVE) { - /* check for the answer rrset */ - for(i=skip; ian_numrrsets; i++) { - if(query_dname_compare(qinf->qname, - rep->rrsets[i]->rk.dname) == 0) { - val_find_rrset_signer(rep->rrsets[i], - signer_name, signer_len); - return; - } - } - *signer_name = NULL; - *signer_len = 0; - } else if(subtype == VAL_CLASS_CNAME) { - /* check for the first signed cname/dname rrset */ - for(i=skip; ian_numrrsets; i++) { - val_find_rrset_signer(rep->rrsets[i], - signer_name, signer_len); - if(*signer_name) - return; - if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME) - break; /* only check CNAME after a DNAME */ - } - *signer_name = NULL; - *signer_len = 0; - } else if(subtype == VAL_CLASS_NAMEERROR - || subtype == VAL_CLASS_NODATA) { - /*Check to see if the AUTH section NSEC record(s) have rrsigs*/ - for(i=rep->an_numrrsets; i< - rep->an_numrrsets+rep->ns_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC - || ntohs(rep->rrsets[i]->rk.type) == - LDNS_RR_TYPE_NSEC3) { - val_find_rrset_signer(rep->rrsets[i], - signer_name, signer_len); - return; - } - } - } else if(subtype == VAL_CLASS_CNAMENOANSWER) { - /* find closest superdomain signer name in authority section - * NSEC and NSEC3s */ - int matchcount = 0; - *signer_name = NULL; - *signer_len = 0; - for(i=rep->an_numrrsets; ian_numrrsets+rep-> - ns_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC - || ntohs(rep->rrsets[i]->rk.type) == - LDNS_RR_TYPE_NSEC3) { - val_find_best_signer(rep->rrsets[i], qinf, - signer_name, signer_len, &matchcount); - } - } - } else if(subtype == VAL_CLASS_ANY) { - /* check for one of the answer rrset that has signatures, - * or potentially a DNAME is in use with a different qname */ - for(i=skip; ian_numrrsets; i++) { - if(query_dname_compare(qinf->qname, - rep->rrsets[i]->rk.dname) == 0) { - val_find_rrset_signer(rep->rrsets[i], - signer_name, signer_len); - if(*signer_name) - return; - } - } - /* no answer RRSIGs with qname, try a DNAME */ - if(skip < rep->an_numrrsets && - ntohs(rep->rrsets[skip]->rk.type) == - LDNS_RR_TYPE_DNAME) { - val_find_rrset_signer(rep->rrsets[skip], - signer_name, signer_len); - if(*signer_name) - return; - } - *signer_name = NULL; - *signer_len = 0; - } else if(subtype == VAL_CLASS_REFERRAL) { - /* find keys for the item at skip */ - if(skip < rep->rrset_count) { - val_find_rrset_signer(rep->rrsets[skip], - signer_name, signer_len); - return; - } - *signer_name = NULL; - *signer_len = 0; - } else { - verbose(VERB_QUERY, "find_signer: could not find signer name" - " for unknown type response"); - *signer_name = NULL; - *signer_len = 0; - } -} - -/** return number of rrs in an rrset */ -static size_t -rrset_get_count(struct ub_packed_rrset_key* rrset) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - if(!d) return 0; - return d->count; -} - -/** return TTL of rrset */ -static uint32_t -rrset_get_ttl(struct ub_packed_rrset_key* rrset) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*) - rrset->entry.data; - if(!d) return 0; - return d->ttl; -} - -static enum sec_status -val_verify_rrset(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, - uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - enum sec_status sec; - struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> - entry.data; - if(d->security == sec_status_secure) { - /* re-verify all other statuses, because keyset may change*/ - log_nametypeclass(VERB_ALGO, "verify rrset cached", - rrset->rk.dname, ntohs(rrset->rk.type), - ntohs(rrset->rk.rrset_class)); - return d->security; - } - /* check in the cache if verification has already been done */ - rrset_check_sec_status(env->rrset_cache, rrset, *env->now); - if(d->security == sec_status_secure) { - log_nametypeclass(VERB_ALGO, "verify rrset from cache", - rrset->rk.dname, ntohs(rrset->rk.type), - ntohs(rrset->rk.rrset_class)); - return d->security; - } - log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname, - ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); - sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason, - reason_bogus, section, qstate); - verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec)); - regional_free_all(env->scratch); - - /* update rrset security status - * only improves security status - * and bogus is set only once, even if we rechecked the status */ - if(sec > d->security) { - d->security = sec; - if(sec == sec_status_secure) - d->trust = rrset_trust_validated; - else if(sec == sec_status_bogus) { - size_t i; - /* update ttl for rrset to fixed value. */ - d->ttl = ve->bogus_ttl; - for(i=0; icount+d->rrsig_count; i++) - d->rr_ttl[i] = ve->bogus_ttl; - /* leave RR specific TTL: not used for determine - * if RRset timed out and clients see proper value. */ - lock_basic_lock(&ve->bogus_lock); - ve->num_rrset_bogus++; - lock_basic_unlock(&ve->bogus_lock); - } - /* if status updated - store in cache for reuse */ - rrset_update_sec_status(env->rrset_cache, rrset, *env->now); - } - - return sec; -} - -enum sec_status -val_verify_rrset_entry(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey, - char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate) -{ - /* temporary dnskey rrset-key */ - struct ub_packed_rrset_key dnskey; - struct key_entry_data* kd = (struct key_entry_data*)kkey->entry.data; - enum sec_status sec; - dnskey.rk.type = htons(kd->rrset_type); - dnskey.rk.rrset_class = htons(kkey->key_class); - dnskey.rk.flags = 0; - dnskey.rk.dname = kkey->name; - dnskey.rk.dname_len = kkey->namelen; - dnskey.entry.key = &dnskey; - dnskey.entry.data = kd->rrset_data; - sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason, - reason_bogus, section, qstate); - return sec; -} - -/** verify that a DS RR hashes to a key and that key signs the set */ -static enum sec_status -verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate) -{ - enum sec_status sec = sec_status_bogus; - size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0; - num = rrset_get_count(dnskey_rrset); - for(i=0; i digest_algo) - digest_algo = d; - } - return digest_algo; -} - -enum sec_status -val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate) -{ - /* as long as this is false, we can consider this DS rrset to be - * equivalent to no DS rrset. */ - int has_useful_ds = 0, digest_algo, alg; - struct algo_needs needs; - size_t i, num; - enum sec_status sec; - - if(dnskey_rrset->rk.dname_len != ds_rrset->rk.dname_len || - query_dname_compare(dnskey_rrset->rk.dname, ds_rrset->rk.dname) - != 0) { - verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " - "by name"); - *reason = "DNSKEY RRset did not match DS RRset by name"; - return sec_status_bogus; - } - - if(sigalg) { - /* harden against algo downgrade is enabled */ - digest_algo = val_favorite_ds_algo(ds_rrset); - algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg); - } else { - /* accept any key algo, any digest algo */ - digest_algo = -1; - } - num = rrset_get_count(ds_rrset); - for(i=0; irk.dname, ds_rrset->rk.dname_len, - ntohs(ds_rrset->rk.rrset_class), dnskey_rrset, - downprot?sigalg:NULL, LDNS_EDE_NONE, NULL, - *env->now); - } else if(sec == sec_status_insecure) { - return key_entry_create_null(region, ds_rrset->rk.dname, - ds_rrset->rk.dname_len, - ntohs(ds_rrset->rk.rrset_class), - rrset_get_ttl(ds_rrset), *reason_bogus, *reason, - *env->now); - } - return key_entry_create_bad(region, ds_rrset->rk.dname, - ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class), - BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now); -} - -enum sec_status -val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ta_ds, - struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate) -{ - /* as long as this is false, we can consider this anchor to be - * equivalent to no anchor. */ - int has_useful_ta = 0, digest_algo = 0, alg; - struct algo_needs needs; - size_t i, num; - enum sec_status sec; - - if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len || - query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname) - != 0)) { - verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " - "by name"); - *reason = "DNSKEY RRset did not match DS RRset by name"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSKEY_MISSING; - return sec_status_bogus; - } - if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len - || query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname) - != 0)) { - verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset " - "by name"); - *reason = "DNSKEY RRset did not match anchor RRset by name"; - if(reason_bogus) - *reason_bogus = LDNS_EDE_DNSKEY_MISSING; - return sec_status_bogus; - } - - if(ta_ds) - digest_algo = val_favorite_ds_algo(ta_ds); - if(sigalg) { - if(ta_ds) - algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg); - else memset(&needs, 0, sizeof(needs)); - if(ta_dnskey) - algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg); - } - if(ta_ds) { - num = rrset_get_count(ta_ds); - for(i=0; irk.dname, dnskey_rrset->rk.dname_len, - ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset, - downprot?sigalg:NULL, LDNS_EDE_NONE, NULL, *env->now); - } else if(sec == sec_status_insecure) { - return key_entry_create_null(region, dnskey_rrset->rk.dname, - dnskey_rrset->rk.dname_len, - ntohs(dnskey_rrset->rk.rrset_class), - rrset_get_ttl(dnskey_rrset), *reason_bogus, *reason, - *env->now); - } - return key_entry_create_bad(region, dnskey_rrset->rk.dname, - dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class), - BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now); -} - -int -val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset) -{ - size_t i; - for(i=0; iname); - else snprintf(herr, sizeof(herr), "%d", - (int)ds_get_digest_algo(ds_rrset, 0)); - lt = sldns_lookup_by_id(sldns_algorithms, - (int)ds_get_key_algo(ds_rrset, 0)); - if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name); - else snprintf(aerr, sizeof(aerr), "%d", - (int)ds_get_key_algo(ds_rrset, 0)); - - verbose(VERB_ALGO, "DS unsupported, hash %s %s, " - "key algorithm %s %s", herr, - (ds_digest_algo_is_supported(ds_rrset, 0)? - "(supported)":"(unsupported)"), aerr, - (ds_key_algo_is_supported(ds_rrset, 0)? - "(supported)":"(unsupported)")); - } - return 0; -} - -/** get label count for a signature */ -static uint8_t -rrsig_get_labcount(struct packed_rrset_data* d, size_t sig) -{ - if(d->rr_len[sig] < 2+4) - return 0; /* bad sig length */ - return d->rr_data[sig][2+3]; -} - -int -val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc, - size_t* wc_len) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> - entry.data; - uint8_t labcount; - int labdiff; - uint8_t* wn; - size_t i, wl; - if(d->rrsig_count == 0) { - return 1; - } - labcount = rrsig_get_labcount(d, d->count + 0); - /* check rest of signatures identical */ - for(i=1; irrsig_count; i++) { - if(labcount != rrsig_get_labcount(d, d->count + i)) { - return 0; - } - } - /* OK the rrsigs check out */ - /* if the RRSIG label count is shorter than the number of actual - * labels, then this rrset was synthesized from a wildcard. - * Note that the RRSIG label count doesn't count the root label. */ - wn = rrset->rk.dname; - wl = rrset->rk.dname_len; - /* skip a leading wildcard label in the dname (RFC4035 2.2) */ - if(dname_is_wild(wn)) { - wn += 2; - wl -= 2; - } - labdiff = (dname_count_labels(wn) - 1) - (int)labcount; - if(labdiff > 0) { - *wc = wn; - dname_remove_labels(wc, &wl, labdiff); - *wc_len = wl; - return 1; - } - return 1; -} - -int -val_chase_cname(struct query_info* qchase, struct reply_info* rep, - size_t* cname_skip) { - size_t i; - /* skip any DNAMEs, go to the CNAME for next part */ - for(i = *cname_skip; i < rep->an_numrrsets; i++) { - if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME && - query_dname_compare(qchase->qname, rep->rrsets[i]-> - rk.dname) == 0) { - qchase->qname = NULL; - get_cname_target(rep->rrsets[i], &qchase->qname, - &qchase->qname_len); - if(!qchase->qname) - return 0; /* bad CNAME rdata */ - (*cname_skip) = i+1; - return 1; - } - } - return 0; /* CNAME classified but no matching CNAME ?! */ -} - -/** see if rrset has signer name as one of the rrsig signers */ -static int -rrset_has_signer(struct ub_packed_rrset_key* rrset, uint8_t* name, size_t len) -{ - struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> - entry.data; - size_t i; - for(i = d->count; i< d->count+d->rrsig_count; i++) { - if(d->rr_len[i] > 2+18+len) { - /* at least rdatalen + signature + signame (+1 sig)*/ - if(!dname_valid(d->rr_data[i]+2+18, d->rr_len[i]-2-18)) - continue; - if(query_dname_compare(name, d->rr_data[i]+2+18) == 0) - { - return 1; - } - } - } - return 0; -} - -void -val_fill_reply(struct reply_info* chase, struct reply_info* orig, - size_t skip, uint8_t* name, size_t len, uint8_t* signer) -{ - size_t i; - int seen_dname = 0; - chase->rrset_count = 0; - chase->an_numrrsets = 0; - chase->ns_numrrsets = 0; - chase->ar_numrrsets = 0; - /* ANSWER section */ - for(i=skip; ian_numrrsets; i++) { - if(!signer) { - if(query_dname_compare(name, - orig->rrsets[i]->rk.dname) == 0) - chase->rrsets[chase->an_numrrsets++] = - orig->rrsets[i]; - } else if(seen_dname && ntohs(orig->rrsets[i]->rk.type) == - LDNS_RR_TYPE_CNAME) { - chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i]; - seen_dname = 0; - } else if(rrset_has_signer(orig->rrsets[i], name, len)) { - chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i]; - if(ntohs(orig->rrsets[i]->rk.type) == - LDNS_RR_TYPE_DNAME) { - seen_dname = 1; - } - } - } - /* AUTHORITY section */ - for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets; - ian_numrrsets+orig->ns_numrrsets; - i++) { - if(!signer) { - if(query_dname_compare(name, - orig->rrsets[i]->rk.dname) == 0) - chase->rrsets[chase->an_numrrsets+ - chase->ns_numrrsets++] = orig->rrsets[i]; - } else if(rrset_has_signer(orig->rrsets[i], name, len)) { - chase->rrsets[chase->an_numrrsets+ - chase->ns_numrrsets++] = orig->rrsets[i]; - } - } - /* ADDITIONAL section */ - for(i= (skip>orig->an_numrrsets+orig->ns_numrrsets)? - skip:orig->an_numrrsets+orig->ns_numrrsets; - irrset_count; i++) { - if(!signer) { - if(query_dname_compare(name, - orig->rrsets[i]->rk.dname) == 0) - chase->rrsets[chase->an_numrrsets - +orig->ns_numrrsets+chase->ar_numrrsets++] - = orig->rrsets[i]; - } else if(rrset_has_signer(orig->rrsets[i], name, len)) { - chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+ - chase->ar_numrrsets++] = orig->rrsets[i]; - } - } - chase->rrset_count = chase->an_numrrsets + chase->ns_numrrsets + - chase->ar_numrrsets; -} - -void val_reply_remove_auth(struct reply_info* rep, size_t index) -{ - log_assert(index < rep->rrset_count); - log_assert(index >= rep->an_numrrsets); - log_assert(index < rep->an_numrrsets+rep->ns_numrrsets); - memmove(rep->rrsets+index, rep->rrsets+index+1, - sizeof(struct ub_packed_rrset_key*)* - (rep->rrset_count - index - 1)); - rep->ns_numrrsets--; - rep->rrset_count--; -} - -void -val_check_nonsecure(struct module_env* env, struct reply_info* rep) -{ - size_t i; - /* authority */ - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { - if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data) - ->security != sec_status_secure) { - /* because we want to return the authentic original - * message when presented with CD-flagged queries, - * we need to preserve AUTHORITY section data. - * However, this rrset is not signed or signed - * with the wrong keys. Validation has tried to - * verify this rrset with the keysets of import. - * But this rrset did not verify. - * Therefore the message is bogus. - */ - - /* check if authority has an NS record - * which is bad, and there is an answer section with - * data. In that case, delete NS and additional to - * be lenient and make a minimal response */ - if(rep->an_numrrsets != 0 && - ntohs(rep->rrsets[i]->rk.type) - == LDNS_RR_TYPE_NS) { - verbose(VERB_ALGO, "truncate to minimal"); - rep->ar_numrrsets = 0; - rep->rrset_count = rep->an_numrrsets + - rep->ns_numrrsets; - /* remove this unneeded authority rrset */ - memmove(rep->rrsets+i, rep->rrsets+i+1, - sizeof(struct ub_packed_rrset_key*)* - (rep->rrset_count - i - 1)); - rep->ns_numrrsets--; - rep->rrset_count--; - i--; - return; - } - - log_nametypeclass(VERB_QUERY, "message is bogus, " - "non secure rrset", - rep->rrsets[i]->rk.dname, - ntohs(rep->rrsets[i]->rk.type), - ntohs(rep->rrsets[i]->rk.rrset_class)); - rep->security = sec_status_bogus; - return; - } - } - /* additional */ - if(!env->cfg->val_clean_additional) - return; - for(i=rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { - if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data) - ->security != sec_status_secure) { - /* This does not cause message invalidation. It was - * simply unsigned data in the additional. The - * RRSIG must have been truncated off the message. - * - * However, we do not want to return possible bogus - * data to clients that rely on this service for - * their authentication. - */ - /* remove this unneeded additional rrset */ - memmove(rep->rrsets+i, rep->rrsets+i+1, - sizeof(struct ub_packed_rrset_key*)* - (rep->rrset_count - i - 1)); - rep->ar_numrrsets--; - rep->rrset_count--; - i--; - } - } -} - -/** check no anchor and unlock */ -static int -check_no_anchor(struct val_anchors* anchors, uint8_t* nm, size_t l, uint16_t c) -{ - struct trust_anchor* ta; - if((ta=anchors_lookup(anchors, nm, l, c))) { - lock_basic_unlock(&ta->lock); - } - return !ta; -} - -void -val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors, - struct rrset_cache* r, struct module_env* env) -{ - size_t i; - struct packed_rrset_data* d; - for(i=0; irrset_count; i++) { - d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; - if(d->security == sec_status_unchecked && - check_no_anchor(anchors, rep->rrsets[i]->rk.dname, - rep->rrsets[i]->rk.dname_len, - ntohs(rep->rrsets[i]->rk.rrset_class))) - { - /* mark as indeterminate */ - d->security = sec_status_indeterminate; - rrset_update_sec_status(r, rep->rrsets[i], *env->now); - } - } -} - -void -val_mark_insecure(struct reply_info* rep, uint8_t* kname, - struct rrset_cache* r, struct module_env* env) -{ - size_t i; - struct packed_rrset_data* d; - for(i=0; irrset_count; i++) { - d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; - if(d->security == sec_status_unchecked && - dname_subdomain_c(rep->rrsets[i]->rk.dname, kname)) { - /* mark as insecure */ - d->security = sec_status_insecure; - rrset_update_sec_status(r, rep->rrsets[i], *env->now); - } - } -} - -size_t -val_next_unchecked(struct reply_info* rep, size_t skip) -{ - size_t i; - struct packed_rrset_data* d; - for(i=skip+1; irrset_count; i++) { - d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; - if(d->security == sec_status_unchecked) { - return i; - } - } - return rep->rrset_count; -} - -const char* -val_classification_to_string(enum val_classification subtype) -{ - switch(subtype) { - case VAL_CLASS_UNTYPED: return "untyped"; - case VAL_CLASS_UNKNOWN: return "unknown"; - case VAL_CLASS_POSITIVE: return "positive"; - case VAL_CLASS_CNAME: return "cname"; - case VAL_CLASS_NODATA: return "nodata"; - case VAL_CLASS_NAMEERROR: return "nameerror"; - case VAL_CLASS_CNAMENOANSWER: return "cnamenoanswer"; - case VAL_CLASS_REFERRAL: return "referral"; - case VAL_CLASS_ANY: return "qtype_any"; - default: - return "bad_val_classification"; - } -} - -/** log a sock_list entry */ -static void -sock_list_logentry(enum verbosity_value v, const char* s, struct sock_list* p) -{ - if(p->len) - log_addr(v, s, &p->addr, p->len); - else verbose(v, "%s cache", s); -} - -void val_blacklist(struct sock_list** blacklist, struct regional* region, - struct sock_list* origin, int cross) -{ - /* debug printout */ - if(verbosity >= VERB_ALGO) { - struct sock_list* p; - for(p=*blacklist; p; p=p->next) - sock_list_logentry(VERB_ALGO, "blacklist", p); - if(!origin) - verbose(VERB_ALGO, "blacklist add: cache"); - for(p=origin; p; p=p->next) - sock_list_logentry(VERB_ALGO, "blacklist add", p); - } - /* blacklist the IPs or the cache */ - if(!origin) { - /* only add if nothing there. anything else also stops cache*/ - if(!*blacklist) - sock_list_insert(blacklist, NULL, 0, region); - } else if(!cross) - sock_list_prepend(blacklist, origin); - else sock_list_merge(blacklist, region, origin); -} - -int val_has_signed_nsecs(struct reply_info* rep, char** reason) -{ - size_t i, num_nsec = 0, num_nsec3 = 0; - struct packed_rrset_data* d; - for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { - if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC)) - num_nsec++; - else if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC3)) - num_nsec3++; - else continue; - d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; - if(d && d->rrsig_count != 0) { - return 1; - } - } - if(num_nsec == 0 && num_nsec3 == 0) - *reason = "no DNSSEC records"; - else if(num_nsec != 0) - *reason = "no signatures over NSECs"; - else *reason = "no signatures over NSEC3s"; - return 0; -} - -struct dns_msg* -val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, - struct regional* region, uint8_t* topname) -{ - struct dns_msg* msg; - struct query_info qinfo; - struct ub_packed_rrset_key *rrset = rrset_cache_lookup( - env->rrset_cache, nm, nmlen, LDNS_RR_TYPE_DS, c, 0, - *env->now, 0); - if(rrset) { - /* DS rrset exists. Return it to the validator immediately*/ - struct ub_packed_rrset_key* copy = packed_rrset_copy_region( - rrset, region, *env->now); - lock_rw_unlock(&rrset->entry.lock); - if(!copy) - return NULL; - msg = dns_msg_create(nm, nmlen, LDNS_RR_TYPE_DS, c, region, 1); - if(!msg) - return NULL; - msg->rep->rrsets[0] = copy; - msg->rep->rrset_count++; - msg->rep->an_numrrsets++; - return msg; - } - /* lookup in rrset and negative cache for NSEC/NSEC3 */ - qinfo.qname = nm; - qinfo.qname_len = nmlen; - qinfo.qtype = LDNS_RR_TYPE_DS; - qinfo.qclass = c; - qinfo.local_alias = NULL; - /* do not add SOA to reply message, it is going to be used internal */ - msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache, - env->scratch_buffer, *env->now, 0, topname, env->cfg); - return msg; -} diff --git a/crates/libunbound-sys/unbound/validator/val_utils.h b/crates/libunbound-sys/unbound/validator/val_utils.h deleted file mode 100644 index 83e3d0ad..00000000 --- a/crates/libunbound-sys/unbound/validator/val_utils.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - * validator/val_utils.h - validator utility functions. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains helper functions for the validator module. - */ - -#ifndef VALIDATOR_VAL_UTILS_H -#define VALIDATOR_VAL_UTILS_H -#include "util/data/packed_rrset.h" -#include "sldns/pkthdr.h" -#include "sldns/rrdef.h" -struct query_info; -struct reply_info; -struct val_env; -struct module_env; -struct module_qstate; -struct ub_packed_rrset_key; -struct key_entry_key; -struct regional; -struct val_anchors; -struct rrset_cache; -struct sock_list; - -/** - * Response classifications for the validator. The different types of proofs. - */ -enum val_classification { - /** Not subtyped yet. */ - VAL_CLASS_UNTYPED = 0, - /** Not a recognized subtype. */ - VAL_CLASS_UNKNOWN, - /** A positive, direct, response */ - VAL_CLASS_POSITIVE, - /** A positive response, with a CNAME/DNAME chain. */ - VAL_CLASS_CNAME, - /** A NOERROR/NODATA response. */ - VAL_CLASS_NODATA, - /** A NXDOMAIN response. */ - VAL_CLASS_NAMEERROR, - /** A CNAME/DNAME chain, and the offset is at the end of it, - * but there is no answer here, it can be NAMEERROR or NODATA. */ - VAL_CLASS_CNAMENOANSWER, - /** A referral, from cache with a nonRD query. */ - VAL_CLASS_REFERRAL, - /** A response to a qtype=ANY query. */ - VAL_CLASS_ANY -}; - -/** - * Given a response, classify ANSWER responses into a subtype. - * @param query_flags: query flags for the original query. - * @param origqinf: query info. The original query name. - * @param qinf: query info. The chased query name. - * @param rep: response. The original response. - * @param skip: offset into the original response answer section. - * @return A subtype, all values possible except UNTYPED . - * Once CNAME type is returned you can increase skip. - * Then, another CNAME type, CNAME_NOANSWER or POSITIVE are possible. - */ -enum val_classification val_classify_response(uint16_t query_flags, - struct query_info* origqinf, struct query_info* qinf, - struct reply_info* rep, size_t skip); - -/** - * Given a response, determine the name of the "signer". This is primarily - * to determine if the response is, in fact, signed at all, and, if so, what - * is the name of the most pertinent keyset. - * - * @param subtype: the type from classify. - * @param qinf: query, the chased query name. - * @param rep: response to that, original response. - * @param cname_skip: how many answer rrsets have been skipped due to CNAME - * chains being chased around. - * @param signer_name: signer name, if the response is signed - * (even partially), or null if the response isn't signed. - * @param signer_len: length of signer_name of 0 if signer_name is NULL. - */ -void val_find_signer(enum val_classification subtype, - struct query_info* qinf, struct reply_info* rep, - size_t cname_skip, uint8_t** signer_name, size_t* signer_len); - -/** - * Verify RRset with keys from a keyset. - * @param env: module environment (scratch buffer) - * @param ve: validator environment (verification settings) - * @param rrset: what to verify - * @param kkey: key_entry to verify with. - * @param reason: reason of failure. Fixed string or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param section: section of packet where this rrset comes from. - * @param qstate: qstate with region. - * @return security status of verification. - */ -enum sec_status val_verify_rrset_entry(struct module_env* env, - struct val_env* ve, struct ub_packed_rrset_key* rrset, - struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus, - sldns_pkt_section section, struct module_qstate* qstate); - -/** - * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but - * returns a sec_status instead of a key_entry. - * @param env: module environment (scratch buffer) - * @param ve: validator environment (verification settings) - * @param dnskey_rrset: DNSKEY rrset to verify - * @param ds_rrset: DS rrset to verify with. - * @param sigalg: if nonNULL provide downgrade protection otherwise one - * algorithm is enough. The list of signalled algorithms is returned, - * must have enough space for ALGO_NEEDS_MAX+1. - * @param reason: reason of failure. Fixed string or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param qstate: qstate with region. - * @return: sec_status_secure if a DS matches. - * sec_status_insecure if end of trust (i.e., unknown algorithms). - * sec_status_bogus if it fails. - */ -enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env, - struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate); - -/** - * Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS - * but for a trust anchor. - * @param env: module environment (scratch buffer) - * @param ve: validator environment (verification settings) - * @param dnskey_rrset: DNSKEY rrset to verify - * @param ta_ds: DS rrset to verify with. - * @param ta_dnskey: DNSKEY rrset to verify with. - * @param sigalg: if nonNULL provide downgrade protection otherwise one - * algorithm is enough. The list of signalled algorithms is returned, - * must have enough space for ALGO_NEEDS_MAX+1. - * @param reason: reason of failure. Fixed string or alloced in scratch. -* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param qstate: qstate with region. - * @return: sec_status_secure if a DS matches. - * sec_status_insecure if end of trust (i.e., unknown algorithms). - * sec_status_bogus if it fails. - */ -enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env, - struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ta_ds, - struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate); - -/** - * Verify new DNSKEYs with DS rrset. The DS contains hash values that should - * match the DNSKEY keys. - * match the DS to a DNSKEY and verify the DNSKEY rrset with that key. - * - * @param region: where to allocate key entry result. - * @param env: module environment (scratch buffer) - * @param ve: validator environment (verification settings) - * @param dnskey_rrset: DNSKEY rrset to verify - * @param ds_rrset: DS rrset to verify with. - * @param downprot: if true provide downgrade protection otherwise one - * algorithm is enough. - * @param reason: reason of failure. Fixed string or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param qstate: qstate with region. - * @return a KeyEntry. This will either contain the now trusted - * dnskey_rrset, a "null" key entry indicating that this DS - * rrset/DNSKEY pair indicate an secure end to the island of trust - * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey - * rrset fails to verify. Note that the "null" response should - * generally only occur in a private algorithm scenario: normally - * this sort of thing is checked before fetching the matching DNSKEY - * rrset. - * if downprot is set, a key entry with an algo list is made. - */ -struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region, - struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, - sldns_ede_code *reason_bogus, struct module_qstate* qstate); - -/** - * Verify rrset with trust anchor: DS and DNSKEY rrset. - * - * @param region: where to allocate key entry result. - * @param env: module environment (scratch buffer) - * @param ve: validator environment (verification settings) - * @param dnskey_rrset: DNSKEY rrset to verify - * @param ta_ds_rrset: DS rrset to verify with. - * @param ta_dnskey_rrset: the DNSKEY rrset to verify with. - * @param downprot: if true provide downgrade protection otherwise one - * algorithm is enough. - * @param reason: reason of failure. Fixed string or alloced in scratch. - * @param reason_bogus: EDE (RFC8914) code paired with the reason of failure. - * @param qstate: qstate with region. - * @return a KeyEntry. This will either contain the now trusted - * dnskey_rrset, a "null" key entry indicating that this DS - * rrset/DNSKEY pair indicate an secure end to the island of trust - * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey - * rrset fails to verify. Note that the "null" response should - * generally only occur in a private algorithm scenario: normally - * this sort of thing is checked before fetching the matching DNSKEY - * rrset. - * if downprot is set, a key entry with an algo list is made. - */ -struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region, - struct module_env* env, struct val_env* ve, - struct ub_packed_rrset_key* dnskey_rrset, - struct ub_packed_rrset_key* ta_ds_rrset, - struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, - char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate); - -/** - * Determine if DS rrset is usable for validator or not. - * Returns true if the algorithms for key and DShash are supported, - * for at least one RR. - * - * @param ds_rrset: the newly received DS rrset. - * @return true or false if not usable. - */ -int val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset); - -/** - * Determine by looking at a signed RRset whether or not the RRset name was - * the result of a wildcard expansion. If so, return the name of the - * generating wildcard. - * - * @param rrset The rrset to check. - * @param wc: the wildcard name, if the rrset was synthesized from a wildcard. - * unchanged if not. The wildcard name, without "*." in front, is - * returned. This is a pointer into the rrset owner name. - * @param wc_len: the length of the returned wildcard name. - * @return false if the signatures are inconsistent in indicating the - * wildcard status; possible spoofing of wildcard response for other - * responses is being tried. We lost the status which rrsig was verified - * after the verification routine finished, so we simply check if - * the signatures are consistent; inserting a fake signature is a denial - * of service; but in that you could also have removed the real - * signature anyway. - */ -int val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc, - size_t* wc_len); - -/** - * Chase the cname to the next query name. - * @param qchase: the current query name, updated to next target. - * @param rep: original message reply to look at CNAMEs. - * @param cname_skip: the skip into the answer section. Updated to skip - * DNAME and CNAME to the next part of the answer. - * @return false on error (bad rdata). - */ -int val_chase_cname(struct query_info* qchase, struct reply_info* rep, - size_t* cname_skip); - -/** - * Fill up the chased reply with the content from the original reply; - * as pointers to those rrsets. Select the part after the cname_skip into - * the answer section, NS and AR sections that are signed with same signer. - * - * @param chase: chased reply, filled up. - * @param orig: original reply. - * @param cname_skip: which part of the answer section to skip. - * The skipped part contains CNAME(and DNAME)s that have been chased. - * @param name: the signer name to look for. - * @param len: length of name. - * @param signer: signer name or NULL if an unsigned RRset is considered. - * If NULL, rrsets with the lookup name are copied over. - */ -void val_fill_reply(struct reply_info* chase, struct reply_info* orig, - size_t cname_skip, uint8_t* name, size_t len, uint8_t* signer); - -/** - * Remove rrset with index from reply, from the authority section. - * @param rep: reply to remove it from. - * @param index: rrset to remove, must be in the authority section. - */ -void val_reply_remove_auth(struct reply_info* rep, size_t index); - -/** - * Remove all unsigned or non-secure status rrsets from NS and AR sections. - * So that unsigned data does not get let through to clients, when we have - * found the data to be secure. - * - * @param env: environment with cleaning options. - * @param rep: reply to dump all nonsecure stuff out of. - */ -void val_check_nonsecure(struct module_env* env, struct reply_info* rep); - -/** - * Mark all unchecked rrset entries not below a trust anchor as indeterminate. - * Only security==unchecked rrsets are updated. - * @param rep: the reply with rrsets. - * @param anchors: the trust anchors. - * @param r: rrset cache to store updated security status into. - * @param env: module environment - */ -void val_mark_indeterminate(struct reply_info* rep, - struct val_anchors* anchors, struct rrset_cache* r, - struct module_env* env); - -/** - * Mark all unchecked rrset entries below a NULL key entry as insecure. - * Only security==unchecked rrsets are updated. - * @param rep: the reply with rrsets. - * @param kname: end of secure space name. - * @param r: rrset cache to store updated security status into. - * @param env: module environment - */ -void val_mark_insecure(struct reply_info* rep, uint8_t* kname, - struct rrset_cache* r, struct module_env* env); - -/** - * Find next unchecked rrset position, return it for skip. - * @param rep: the original reply to look into. - * @param skip: the skip now. - * @return new skip, which may be at the rep->rrset_count position to signal - * there are no unchecked items. - */ -size_t val_next_unchecked(struct reply_info* rep, size_t skip); - -/** - * Find the signer name for an RRset. - * @param rrset: the rrset. - * @param sname: signer name is returned or NULL if not signed. - * @param slen: length of sname (or 0). - */ -void val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname, - size_t* slen); - -/** - * Get string to denote the classification result. - * @param subtype: from classification function. - * @return static string to describe the classification. - */ -const char* val_classification_to_string(enum val_classification subtype); - -/** - * Add existing list to blacklist. - * @param blacklist: the blacklist with result - * @param region: the region where blacklist is allocated. - * Allocation failures are logged. - * @param origin: origin list to add, if NULL, a cache-entry is added to - * the blacklist to stop cache from being used. - * @param cross: if true this is a cross-qstate copy, and the 'origin' - * list is not allocated in the same region as the blacklist. - */ -void val_blacklist(struct sock_list** blacklist, struct regional* region, - struct sock_list* origin, int cross); - -/** - * check if has dnssec info, and if it has signed nsecs. gives error reason. - * @param rep: reply to check. - * @param reason: returned on fail. - * @return false if message has no signed nsecs. Can not prove negatives. - */ -int val_has_signed_nsecs(struct reply_info* rep, char** reason); - -/** - * Return algo number for favorite (best) algorithm that we support in DS. - * @param ds_rrset: the DSes in this rrset are inspected and best algo chosen. - * @return algo number or 0 if none supported. 0 is unused as algo number. - */ -int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset); - -/** - * Find DS denial message in cache. Saves new qstate allocation and allows - * the validator to use partial content which is not enough to construct a - * message for network (or user) consumption. Without SOA for example, - * which is a common occurrence in the unbound code since the referrals contain - * NSEC/NSEC3 rrs without the SOA element, thus do not allow synthesis of a - * full negative reply, but do allow synthesis of sufficient proof. - * @param env: query env with caches and time. - * @param nm: name of DS record sought. - * @param nmlen: length of name. - * @param c: class of DS RR. - * @param region: where to allocate result. - * @param topname: name of the key that is currently in use, that will get - * used to validate the result, and thus no higher entries from the - * negative cache need to be examined. - * @return a dns_msg on success. NULL on failure. - */ -struct dns_msg* val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, - uint16_t c, struct regional* region, uint8_t* topname); - -#endif /* VALIDATOR_VAL_UTILS_H */ diff --git a/crates/libunbound-sys/unbound/validator/validator.c b/crates/libunbound-sys/unbound/validator/validator.c deleted file mode 100644 index 9de9d54d..00000000 --- a/crates/libunbound-sys/unbound/validator/validator.c +++ /dev/null @@ -1,3016 +0,0 @@ -/* - * validator/validator.c - secure validator DNS query response module - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs validation of DNS queries. - * According to RFC 4034. - */ -#include "config.h" -#include -#include "validator/validator.h" -#include "validator/val_anchor.h" -#include "validator/val_kcache.h" -#include "validator/val_kentry.h" -#include "validator/val_utils.h" -#include "validator/val_nsec.h" -#include "validator/val_nsec3.h" -#include "validator/val_neg.h" -#include "validator/val_sigcrypt.h" -#include "validator/autotrust.h" -#include "services/cache/dns.h" -#include "services/cache/rrset.h" -#include "util/data/dname.h" -#include "util/module.h" -#include "util/log.h" -#include "util/net_help.h" -#include "util/regional.h" -#include "util/config_file.h" -#include "util/fptr_wlist.h" -#include "sldns/rrdef.h" -#include "sldns/wire2str.h" -#include "sldns/str2wire.h" - -/* forward decl for cache response and normal super inform calls of a DS */ -static void process_ds_response(struct module_qstate* qstate, - struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, - struct query_info* qinfo, struct sock_list* origin); - - -/* Updates the suplied EDE (RFC8914) code selectively so we don't lose - * a more specific code */ -static void -update_reason_bogus(struct reply_info* rep, sldns_ede_code reason_bogus) -{ - if(reason_bogus == LDNS_EDE_NONE) return; - if(reason_bogus == LDNS_EDE_DNSSEC_BOGUS - && rep->reason_bogus != LDNS_EDE_NONE - && rep->reason_bogus != LDNS_EDE_DNSSEC_BOGUS) return; - rep->reason_bogus = reason_bogus; -} - - -/** fill up nsec3 key iterations config entry */ -static int -fill_nsec3_iter(struct val_env* ve, char* s, int c) -{ - char* e; - int i; - free(ve->nsec3_keysize); - free(ve->nsec3_maxiter); - ve->nsec3_keysize = (size_t*)calloc(sizeof(size_t), (size_t)c); - ve->nsec3_maxiter = (size_t*)calloc(sizeof(size_t), (size_t)c); - if(!ve->nsec3_keysize || !ve->nsec3_maxiter) { - log_err("out of memory"); - return 0; - } - for(i=0; insec3_keysize[i] = (size_t)strtol(s, &e, 10); - if(s == e) { - log_err("cannot parse: %s", s); - return 0; - } - s = e; - ve->nsec3_maxiter[i] = (size_t)strtol(s, &e, 10); - if(s == e) { - log_err("cannot parse: %s", s); - return 0; - } - s = e; - if(i>0 && ve->nsec3_keysize[i-1] >= ve->nsec3_keysize[i]) { - log_err("nsec3 key iterations not ascending: %d %d", - (int)ve->nsec3_keysize[i-1], - (int)ve->nsec3_keysize[i]); - return 0; - } - verbose(VERB_ALGO, "validator nsec3cfg keysz %d mxiter %d", - (int)ve->nsec3_keysize[i], (int)ve->nsec3_maxiter[i]); - } - return 1; -} - -/** apply config settings to validator */ -static int -val_apply_cfg(struct module_env* env, struct val_env* val_env, - struct config_file* cfg) -{ - int c; - val_env->bogus_ttl = (uint32_t)cfg->bogus_ttl; - if(!env->anchors) - env->anchors = anchors_create(); - if(!env->anchors) { - log_err("out of memory"); - return 0; - } - if (env->key_cache) - val_env->kcache = env->key_cache; - if(!val_env->kcache) - val_env->kcache = key_cache_create(cfg); - if(!val_env->kcache) { - log_err("out of memory"); - return 0; - } - env->key_cache = val_env->kcache; - if(!anchors_apply_cfg(env->anchors, cfg)) { - log_err("validator: error in trustanchors config"); - return 0; - } - val_env->date_override = cfg->val_date_override; - val_env->skew_min = cfg->val_sig_skew_min; - val_env->skew_max = cfg->val_sig_skew_max; - val_env->max_restart = cfg->val_max_restart; - c = cfg_count_numbers(cfg->val_nsec3_key_iterations); - if(c < 1 || (c&1)) { - log_err("validator: unparsable or odd nsec3 key " - "iterations: %s", cfg->val_nsec3_key_iterations); - return 0; - } - val_env->nsec3_keyiter_count = c/2; - if(!fill_nsec3_iter(val_env, cfg->val_nsec3_key_iterations, c/2)) { - log_err("validator: cannot apply nsec3 key iterations"); - return 0; - } - if (env->neg_cache) - val_env->neg_cache = env->neg_cache; - if(!val_env->neg_cache) - val_env->neg_cache = val_neg_create(cfg, - val_env->nsec3_maxiter[val_env->nsec3_keyiter_count-1]); - if(!val_env->neg_cache) { - log_err("out of memory"); - return 0; - } - env->neg_cache = val_env->neg_cache; - return 1; -} - -#ifdef USE_ECDSA_EVP_WORKAROUND -void ecdsa_evp_workaround_init(void); -#endif -int -val_init(struct module_env* env, int id) -{ - struct val_env* val_env = (struct val_env*)calloc(1, - sizeof(struct val_env)); - if(!val_env) { - log_err("malloc failure"); - return 0; - } - env->modinfo[id] = (void*)val_env; - env->need_to_validate = 1; - lock_basic_init(&val_env->bogus_lock); - lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus, - sizeof(val_env->num_rrset_bogus)); -#ifdef USE_ECDSA_EVP_WORKAROUND - ecdsa_evp_workaround_init(); -#endif - if(!val_apply_cfg(env, val_env, env->cfg)) { - log_err("validator: could not apply configuration settings."); - return 0; - } - - return 1; -} - -void -val_deinit(struct module_env* env, int id) -{ - struct val_env* val_env; - if(!env || !env->modinfo[id]) - return; - val_env = (struct val_env*)env->modinfo[id]; - lock_basic_destroy(&val_env->bogus_lock); - anchors_delete(env->anchors); - env->anchors = NULL; - key_cache_delete(val_env->kcache); - env->key_cache = NULL; - neg_cache_delete(val_env->neg_cache); - env->neg_cache = NULL; - free(val_env->nsec3_keysize); - free(val_env->nsec3_maxiter); - free(val_env); - env->modinfo[id] = NULL; -} - -/** fill in message structure */ -static struct val_qstate* -val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq) -{ - if(!qstate->return_msg || qstate->return_rcode != LDNS_RCODE_NOERROR) { - /* create a message to verify */ - verbose(VERB_ALGO, "constructing reply for validation"); - vq->orig_msg = (struct dns_msg*)regional_alloc(qstate->region, - sizeof(struct dns_msg)); - if(!vq->orig_msg) - return NULL; - vq->orig_msg->qinfo = qstate->qinfo; - vq->orig_msg->rep = (struct reply_info*)regional_alloc( - qstate->region, sizeof(struct reply_info)); - if(!vq->orig_msg->rep) - return NULL; - memset(vq->orig_msg->rep, 0, sizeof(struct reply_info)); - vq->orig_msg->rep->flags = (uint16_t)(qstate->return_rcode&0xf) - |BIT_QR|BIT_RA|(qstate->query_flags|(BIT_CD|BIT_RD)); - vq->orig_msg->rep->qdcount = 1; - vq->orig_msg->rep->reason_bogus = LDNS_EDE_NONE; - } else { - vq->orig_msg = qstate->return_msg; - } - vq->qchase = qstate->qinfo; - /* chase reply will be an edited (sub)set of the orig msg rrset ptrs */ - vq->chase_reply = regional_alloc_init(qstate->region, - vq->orig_msg->rep, - sizeof(struct reply_info) - sizeof(struct rrset_ref)); - if(!vq->chase_reply) - return NULL; - if(vq->orig_msg->rep->rrset_count > RR_COUNT_MAX) - return NULL; /* protect against integer overflow */ - vq->chase_reply->rrsets = regional_alloc_init(qstate->region, - vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*) - * vq->orig_msg->rep->rrset_count); - if(!vq->chase_reply->rrsets) - return NULL; - vq->rrset_skip = 0; - return vq; -} - -/** allocate new validator query state */ -static struct val_qstate* -val_new(struct module_qstate* qstate, int id) -{ - struct val_qstate* vq = (struct val_qstate*)regional_alloc( - qstate->region, sizeof(*vq)); - log_assert(!qstate->minfo[id]); - if(!vq) - return NULL; - memset(vq, 0, sizeof(*vq)); - qstate->minfo[id] = vq; - vq->state = VAL_INIT_STATE; - return val_new_getmsg(qstate, vq); -} - -/** - * Exit validation with an error status - * - * @param qstate: query state - * @param id: validator id. - * @return false, for use by caller to return to stop processing. - */ -static int -val_error(struct module_qstate* qstate, int id) -{ - qstate->ext_state[id] = module_error; - qstate->return_rcode = LDNS_RCODE_SERVFAIL; - return 0; -} - -/** - * Check to see if a given response needs to go through the validation - * process. Typical reasons for this routine to return false are: CD bit was - * on in the original request, or the response is a kind of message that - * is unvalidatable (i.e., SERVFAIL, REFUSED, etc.) - * - * @param qstate: query state. - * @param ret_rc: rcode for this message (if noerror - examine ret_msg). - * @param ret_msg: return msg, can be NULL; look at rcode instead. - * @return true if the response could use validation (although this does not - * mean we can actually validate this response). - */ -static int -needs_validation(struct module_qstate* qstate, int ret_rc, - struct dns_msg* ret_msg) -{ - int rcode; - - /* If the CD bit is on in the original request, then you could think - * that we don't bother to validate anything. - * But this is signalled internally with the valrec flag. - * User queries are validated with BIT_CD to make our cache clean - * so that bogus messages get retried by the upstream also for - * downstream validators that set BIT_CD. - * For DNS64 bit_cd signals no dns64 processing, but we want to - * provide validation there too */ - /* - if(qstate->query_flags & BIT_CD) { - verbose(VERB_ALGO, "not validating response due to CD bit"); - return 0; - } - */ - if(qstate->is_valrec) { - verbose(VERB_ALGO, "not validating response, is valrec" - "(validation recursion lookup)"); - return 0; - } - - if(ret_rc != LDNS_RCODE_NOERROR || !ret_msg) - rcode = ret_rc; - else rcode = (int)FLAGS_GET_RCODE(ret_msg->rep->flags); - - if(rcode != LDNS_RCODE_NOERROR && rcode != LDNS_RCODE_NXDOMAIN) { - if(verbosity >= VERB_ALGO) { - char rc[16]; - rc[0]=0; - (void)sldns_wire2str_rcode_buf(rcode, rc, sizeof(rc)); - verbose(VERB_ALGO, "cannot validate non-answer, rcode %s", rc); - } - return 0; - } - - /* cannot validate positive RRSIG response. (negatives can) */ - if(qstate->qinfo.qtype == LDNS_RR_TYPE_RRSIG && - rcode == LDNS_RCODE_NOERROR && ret_msg && - ret_msg->rep->an_numrrsets > 0) { - verbose(VERB_ALGO, "cannot validate RRSIG, no sigs on sigs."); - return 0; - } - return 1; -} - -/** - * Check to see if the response has already been validated. - * @param ret_msg: return msg, can be NULL - * @return true if the response has already been validated - */ -static int -already_validated(struct dns_msg* ret_msg) -{ - /* validate unchecked, and re-validate bogus messages */ - if (ret_msg && ret_msg->rep->security > sec_status_bogus) - { - verbose(VERB_ALGO, "response has already been validated: %s", - sec_status_to_string(ret_msg->rep->security)); - return 1; - } - return 0; -} - -/** - * Generate a request for DNS data. - * - * @param qstate: query state that is the parent. - * @param id: module id. - * @param name: what name to query for. - * @param namelen: length of name. - * @param qtype: query type. - * @param qclass: query class. - * @param flags: additional flags, such as the CD bit (BIT_CD), or 0. - * @param newq: If the subquery is newly created, it is returned, - * otherwise NULL is returned - * @param detached: true if this qstate should not attach to the subquery - * @return false on alloc failure. - */ -static int -generate_request(struct module_qstate* qstate, int id, uint8_t* name, - size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags, - struct module_qstate** newq, int detached) -{ - struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id]; - struct query_info ask; - int valrec; - ask.qname = name; - ask.qname_len = namelen; - ask.qtype = qtype; - ask.qclass = qclass; - ask.local_alias = NULL; - log_query_info(VERB_ALGO, "generate request", &ask); - /* enable valrec flag to avoid recursion to the same validation - * routine, this lookup is simply a lookup. */ - valrec = 1; - - fptr_ok(fptr_whitelist_modenv_detect_cycle(qstate->env->detect_cycle)); - if((*qstate->env->detect_cycle)(qstate, &ask, - (uint16_t)(BIT_RD|flags), 0, valrec)) { - verbose(VERB_ALGO, "Could not generate request: cycle detected"); - return 0; - } - - if(detached) { - struct mesh_state* sub = NULL; - fptr_ok(fptr_whitelist_modenv_add_sub( - qstate->env->add_sub)); - if(!(*qstate->env->add_sub)(qstate, &ask, - (uint16_t)(BIT_RD|flags), 0, valrec, newq, &sub)){ - log_err("Could not generate request: out of memory"); - return 0; - } - } - else { - fptr_ok(fptr_whitelist_modenv_attach_sub( - qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &ask, - (uint16_t)(BIT_RD|flags), 0, valrec, newq)){ - log_err("Could not generate request: out of memory"); - return 0; - } - } - /* newq; validator does not need state created for that - * query, and its a 'normal' for iterator as well */ - if(*newq) { - /* add our blacklist to the query blacklist */ - sock_list_merge(&(*newq)->blacklist, (*newq)->region, - vq->chain_blacklist); - } - qstate->ext_state[id] = module_wait_subquery; - return 1; -} - -/** - * Generate, send and detach key tag signaling query. - * - * @param qstate: query state. - * @param id: module id. - * @param ta: trust anchor, locked. - * @return false on a processing error. - */ -static int -generate_keytag_query(struct module_qstate* qstate, int id, - struct trust_anchor* ta) -{ - /* 3 bytes for "_ta", 5 bytes per tag (4 bytes + "-") */ -#define MAX_LABEL_TAGS (LDNS_MAX_LABELLEN-3)/5 - size_t i, numtag; - uint16_t tags[MAX_LABEL_TAGS]; - char tagstr[LDNS_MAX_LABELLEN+1] = "_ta"; /* +1 for NULL byte */ - size_t tagstr_left = sizeof(tagstr) - strlen(tagstr); - char* tagstr_pos = tagstr + strlen(tagstr); - uint8_t dnamebuf[LDNS_MAX_DOMAINLEN+1]; /* +1 for label length byte */ - size_t dnamebuf_len = sizeof(dnamebuf); - uint8_t* keytagdname; - struct module_qstate* newq = NULL; - enum module_ext_state ext_state = qstate->ext_state[id]; - - numtag = anchor_list_keytags(ta, tags, MAX_LABEL_TAGS); - if(numtag == 0) - return 0; - - for(i=0; iname, ta->namelen); - if(!(keytagdname = (uint8_t*)regional_alloc_init(qstate->region, - dnamebuf, dnamebuf_len))) { - log_err("could not generate key tag query: out of memory"); - return 0; - } - - log_nametypeclass(VERB_OPS, "generate keytag query", keytagdname, - LDNS_RR_TYPE_NULL, ta->dclass); - if(!generate_request(qstate, id, keytagdname, dnamebuf_len, - LDNS_RR_TYPE_NULL, ta->dclass, 0, &newq, 1)) { - verbose(VERB_ALGO, "failed to generate key tag signaling request"); - return 0; - } - - /* Not interested in subquery response. Restore the ext_state, - * that might be changed by generate_request() */ - qstate->ext_state[id] = ext_state; - - return 1; -} - -/** - * Get keytag as uint16_t from string - * - * @param start: start of string containing keytag - * @param keytag: pointer where to store the extracted keytag - * @return: 1 if keytag was extracted, else 0. - */ -static int -sentinel_get_keytag(char* start, uint16_t* keytag) { - char* keytag_str; - char* e = NULL; - keytag_str = calloc(1, SENTINEL_KEYTAG_LEN + 1 /* null byte */); - if(!keytag_str) - return 0; - memmove(keytag_str, start, SENTINEL_KEYTAG_LEN); - keytag_str[SENTINEL_KEYTAG_LEN] = '\0'; - *keytag = (uint16_t)strtol(keytag_str, &e, 10); - if(!e || *e != '\0') { - free(keytag_str); - return 0; - } - free(keytag_str); - return 1; -} - -/** - * Prime trust anchor for use. - * Generate and dispatch a priming query for the given trust anchor. - * The trust anchor can be DNSKEY or DS and does not have to be signed. - * - * @param qstate: query state. - * @param vq: validator query state. - * @param id: module id. - * @param toprime: what to prime. - * @return false on a processing error. - */ -static int -prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq, - int id, struct trust_anchor* toprime) -{ - struct module_qstate* newq = NULL; - int ret = generate_request(qstate, id, toprime->name, toprime->namelen, - LDNS_RR_TYPE_DNSKEY, toprime->dclass, BIT_CD, &newq, 0); - - if(newq && qstate->env->cfg->trust_anchor_signaling && - !generate_keytag_query(qstate, id, toprime)) { - verbose(VERB_ALGO, "keytag signaling query failed"); - return 0; - } - - if(!ret) { - verbose(VERB_ALGO, "Could not prime trust anchor"); - return 0; - } - /* ignore newq; validator does not need state created for that - * query, and its a 'normal' for iterator as well */ - vq->wait_prime_ta = 1; /* to elicit PRIME_RESP_STATE processing - from the validator inform_super() routine */ - /* store trust anchor name for later lookup when prime returns */ - vq->trust_anchor_name = regional_alloc_init(qstate->region, - toprime->name, toprime->namelen); - vq->trust_anchor_len = toprime->namelen; - vq->trust_anchor_labs = toprime->namelabs; - if(!vq->trust_anchor_name) { - log_err("Could not prime trust anchor: out of memory"); - return 0; - } - return 1; -} - -/** - * Validate if the ANSWER and AUTHORITY sections contain valid rrsets. - * They must be validly signed with the given key. - * Tries to validate ADDITIONAL rrsets as well, but only to check them. - * Allows unsigned CNAME after a DNAME that expands the DNAME. - * - * Note that by the time this method is called, the process of finding the - * trusted DNSKEY rrset that signs this response must already have been - * completed. - * - * @param qstate: query state. - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to validate. - * @param key_entry: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - * @return false if any of the rrsets in the an or ns sections of the message - * fail to verify. The message is then set to bogus. - */ -static int -validate_msg_signatures(struct module_qstate* qstate, struct module_env* env, - struct val_env* ve, struct query_info* qchase, - struct reply_info* chase_reply, struct key_entry_key* key_entry) -{ - uint8_t* sname; - size_t i, slen; - struct ub_packed_rrset_key* s; - enum sec_status sec; - int dname_seen = 0; - char* reason = NULL; - sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - - /* validate the ANSWER section */ - for(i=0; ian_numrrsets; i++) { - s = chase_reply->rrsets[i]; - /* Skip the CNAME following a (validated) DNAME. - * Because of the normalization routines in the iterator, - * there will always be an unsigned CNAME following a DNAME - * (unless qtype=DNAME). */ - if(dname_seen && ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { - dname_seen = 0; - /* CNAME was synthesized by our own iterator */ - /* since the DNAME verified, mark the CNAME as secure */ - ((struct packed_rrset_data*)s->entry.data)->security = - sec_status_secure; - ((struct packed_rrset_data*)s->entry.data)->trust = - rrset_trust_validated; - continue; - } - - /* Verify the answer rrset */ - sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason, - &reason_bogus, LDNS_SECTION_ANSWER, qstate); - /* If the (answer) rrset failed to validate, then this - * message is BAD. */ - if(sec != sec_status_secure) { - log_nametypeclass(VERB_QUERY, "validator: response " - "has failed ANSWER rrset:", s->rk.dname, - ntohs(s->rk.type), ntohs(s->rk.rrset_class)); - errinf_ede(qstate, reason, reason_bogus); - if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) - errinf(qstate, "for CNAME"); - else if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) - errinf(qstate, "for DNAME"); - errinf_origin(qstate, qstate->reply_origin); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, reason_bogus); - - return 0; - } - - /* Notice a DNAME that should be followed by an unsigned - * CNAME. */ - if(qchase->qtype != LDNS_RR_TYPE_DNAME && - ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) { - dname_seen = 1; - } - } - - /* validate the AUTHORITY section */ - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason, - &reason_bogus, LDNS_SECTION_AUTHORITY, qstate); - /* If anything in the authority section fails to be secure, - * we have a bad message. */ - if(sec != sec_status_secure) { - log_nametypeclass(VERB_QUERY, "validator: response " - "has failed AUTHORITY rrset:", s->rk.dname, - ntohs(s->rk.type), ntohs(s->rk.rrset_class)); - errinf_ede(qstate, reason, reason_bogus); - errinf_origin(qstate, qstate->reply_origin); - errinf_rrset(qstate, s); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, reason_bogus); - return 0; - } - } - - /* If set, the validator should clean the additional section of - * secure messages. */ - if(!env->cfg->val_clean_additional) - return 1; - /* attempt to validate the ADDITIONAL section rrsets */ - for(i=chase_reply->an_numrrsets+chase_reply->ns_numrrsets; - irrset_count; i++) { - s = chase_reply->rrsets[i]; - /* only validate rrs that have signatures with the key */ - /* leave others unchecked, those get removed later on too */ - val_find_rrset_signer(s, &sname, &slen); - - if(sname && query_dname_compare(sname, key_entry->name)==0) - (void)val_verify_rrset_entry(env, ve, s, key_entry, - &reason, NULL, LDNS_SECTION_ADDITIONAL, qstate); - /* the additional section can fail to be secure, - * it is optional, check signature in case we need - * to clean the additional section later. */ - } - - return 1; -} - -/** - * Detect wrong truncated response (say from BIND 9.6.1 that is forwarding - * and saw the NS record without signatures from a referral). - * The positive response has a mangled authority section. - * Remove that authority section and the additional section. - * @param rep: reply - * @return true if a wrongly truncated response. - */ -static int -detect_wrongly_truncated(struct reply_info* rep) -{ - size_t i; - /* only NS in authority, and it is bogus */ - if(rep->ns_numrrsets != 1 || rep->an_numrrsets == 0) - return 0; - if(ntohs(rep->rrsets[ rep->an_numrrsets ]->rk.type) != LDNS_RR_TYPE_NS) - return 0; - if(((struct packed_rrset_data*)rep->rrsets[ rep->an_numrrsets ] - ->entry.data)->security == sec_status_secure) - return 0; - /* answer section is present and secure */ - for(i=0; ian_numrrsets; i++) { - if(((struct packed_rrset_data*)rep->rrsets[ i ] - ->entry.data)->security != sec_status_secure) - return 0; - } - verbose(VERB_ALGO, "truncating to minimal response"); - return 1; -} - -/** - * For messages that are not referrals, if the chase reply contains an - * unsigned NS record in the authority section it could have been - * inserted by a (BIND) forwarder that thinks the zone is insecure, and - * that has an NS record without signatures in cache. Remove the NS - * record since the reply does not hinge on that record (in the authority - * section), but do not remove it if it removes the last record from the - * answer+authority sections. - * @param chase_reply: the chased reply, we have a key for this contents, - * so we should have signatures for these rrsets and not having - * signatures means it will be bogus. - * @param orig_reply: original reply, remove NS from there as well because - * we cannot mark the NS record as DNSSEC valid because it is not - * validated by signatures. - */ -static void -remove_spurious_authority(struct reply_info* chase_reply, - struct reply_info* orig_reply) -{ - size_t i, found = 0; - int remove = 0; - /* if no answer and only 1 auth RRset, do not remove that one */ - if(chase_reply->an_numrrsets == 0 && chase_reply->ns_numrrsets == 1) - return; - /* search authority section for unsigned NS records */ - for(i = chase_reply->an_numrrsets; - i < chase_reply->an_numrrsets+chase_reply->ns_numrrsets; i++) { - struct packed_rrset_data* d = (struct packed_rrset_data*) - chase_reply->rrsets[i]->entry.data; - if(ntohs(chase_reply->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS - && d->rrsig_count == 0) { - found = i; - remove = 1; - break; - } - } - /* see if we found the entry */ - if(!remove) return; - log_rrset_key(VERB_ALGO, "Removing spurious unsigned NS record " - "(likely inserted by forwarder)", chase_reply->rrsets[found]); - - /* find rrset in orig_reply */ - for(i = orig_reply->an_numrrsets; - i < orig_reply->an_numrrsets+orig_reply->ns_numrrsets; i++) { - if(ntohs(orig_reply->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS - && query_dname_compare(orig_reply->rrsets[i]->rk.dname, - chase_reply->rrsets[found]->rk.dname) == 0) { - /* remove from orig_msg */ - val_reply_remove_auth(orig_reply, i); - break; - } - } - /* remove rrset from chase_reply */ - val_reply_remove_auth(chase_reply, found); -} - -/** - * Given a "positive" response -- a response that contains an answer to the - * question, and no CNAME chain, validate this response. - * - * The answer and authority RRsets must already be verified as secure. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - */ -static void -validate_positive_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey) -{ - uint8_t* wc = NULL; - size_t wl; - int wc_cached = 0; - int wc_NSEC_ok = 0; - int nsec3s_seen = 0; - size_t i; - struct ub_packed_rrset_key* s; - - /* validate the ANSWER section - this will be the answer itself */ - for(i=0; ian_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* Check to see if the rrset is the result of a wildcard - * expansion. If so, an additional check will need to be - * made in the authority section. */ - if(!val_rrset_wildcard(s, &wc, &wl)) { - log_nametypeclass(VERB_QUERY, "Positive response has " - "inconsistent wildcard sigs:", s->rk.dname, - ntohs(s->rk.type), ntohs(s->rk.rrset_class)); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - if(wc && !wc_cached && env->cfg->aggressive_nsec) { - rrset_cache_update_wildcard(env->rrset_cache, s, wc, wl, - env->alloc, *env->now); - wc_cached = 1; - } - - } - - /* validate the AUTHORITY section as well - this will generally be - * the NS rrset (which could be missing, no problem) */ - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* If this is a positive wildcard response, and we have a - * (just verified) NSEC record, try to use it to 1) prove - * that qname doesn't exist and 2) that the correct wildcard - * was used. */ - if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { - wc_NSEC_ok = 1; - } - /* if not, continue looking for proof */ - } - - /* Otherwise, if this is a positive wildcard response and - * we have NSEC3 records */ - if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - nsec3s_seen = 1; - } - } - - /* If this was a positive wildcard response that we haven't already - * proven, and we have NSEC3 records, try to prove it using the NSEC3 - * records. */ - if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { - enum sec_status sec = nsec3_prove_wildcard(env, ve, - chase_reply->rrsets+chase_reply->an_numrrsets, - chase_reply->ns_numrrsets, qchase, kkey, wc); - if(sec == sec_status_insecure) { - verbose(VERB_ALGO, "Positive wildcard response is " - "insecure"); - chase_reply->security = sec_status_insecure; - return; - } else if(sec == sec_status_secure) - wc_NSEC_ok = 1; - } - - /* If after all this, we still haven't proven the positive wildcard - * response, fail. */ - if(wc != NULL && !wc_NSEC_ok) { - verbose(VERB_QUERY, "positive response was wildcard " - "expansion and did not prove original data " - "did not exist"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - verbose(VERB_ALGO, "Successfully validated positive response"); - chase_reply->security = sec_status_secure; -} - -/** - * Validate a NOERROR/NODATA signed response -- a response that has a - * NOERROR Rcode but no ANSWER section RRsets. This consists of making - * certain that the authority section NSEC/NSEC3s proves that the qname - * does exist and the qtype doesn't. - * - * The answer and authority RRsets must already be verified as secure. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - */ -static void -validate_nodata_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey) -{ - /* Since we are here, there must be nothing in the ANSWER section to - * validate. */ - /* (Note: CNAME/DNAME responses will not directly get here -- - * instead, they are chased down into individual CNAME validations, - * and at the end of the cname chain a POSITIVE, or CNAME_NOANSWER - * validation.) */ - - /* validate the AUTHORITY section */ - int has_valid_nsec = 0; /* If true, then the NODATA has been proven.*/ - uint8_t* ce = NULL; /* for wildcard nodata responses. This is the - proven closest encloser. */ - uint8_t* wc = NULL; /* for wildcard nodata responses. wildcard nsec */ - int nsec3s_seen = 0; /* nsec3s seen */ - struct ub_packed_rrset_key* s; - size_t i; - - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - /* If we encounter an NSEC record, try to use it to prove - * NODATA. - * This needs to handle the ENT NODATA case. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(nsec_proves_nodata(s, qchase, &wc)) { - has_valid_nsec = 1; - /* sets wc-encloser if wildcard applicable */ - } - if(val_nsec_proves_name_error(s, qchase->qname)) { - ce = nsec_closest_encloser(qchase->qname, s); - } - if(val_nsec_proves_insecuredelegation(s, qchase)) { - verbose(VERB_ALGO, "delegation is insecure"); - chase_reply->security = sec_status_insecure; - return; - } - } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - nsec3s_seen = 1; - } - } - - /* check to see if we have a wildcard NODATA proof. */ - - /* The wildcard NODATA is 1 NSEC proving that qname does not exist - * (and also proving what the closest encloser is), and 1 NSEC - * showing the matching wildcard, which must be *.closest_encloser. */ - if(wc && !ce) - has_valid_nsec = 0; - else if(wc && ce) { - if(query_dname_compare(wc, ce) != 0) { - has_valid_nsec = 0; - } - } - - if(!has_valid_nsec && nsec3s_seen) { - enum sec_status sec = nsec3_prove_nodata(env, ve, - chase_reply->rrsets+chase_reply->an_numrrsets, - chase_reply->ns_numrrsets, qchase, kkey); - if(sec == sec_status_insecure) { - verbose(VERB_ALGO, "NODATA response is insecure"); - chase_reply->security = sec_status_insecure; - return; - } else if(sec == sec_status_secure) - has_valid_nsec = 1; - } - - if(!has_valid_nsec) { - verbose(VERB_QUERY, "NODATA response failed to prove NODATA " - "status with NSEC/NSEC3"); - if(verbosity >= VERB_ALGO) - log_dns_msg("Failed NODATA", qchase, chase_reply); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - verbose(VERB_ALGO, "successfully validated NODATA response."); - chase_reply->security = sec_status_secure; -} - -/** - * Validate a NAMEERROR signed response -- a response that has a NXDOMAIN - * Rcode. - * This consists of making certain that the authority section NSEC proves - * that the qname doesn't exist and the covering wildcard also doesn't exist.. - * - * The answer and authority RRsets must have already been verified as secure. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - * @param rcode: adjusted RCODE, in case of RCODE/proof mismatch leniency. - */ -static void -validate_nameerror_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey, int* rcode) -{ - int has_valid_nsec = 0; - int has_valid_wnsec = 0; - int nsec3s_seen = 0; - struct ub_packed_rrset_key* s; - size_t i; - uint8_t* ce; - int ce_labs = 0; - int prev_ce_labs = 0; - - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(val_nsec_proves_name_error(s, qchase->qname)) - has_valid_nsec = 1; - ce = nsec_closest_encloser(qchase->qname, s); - ce_labs = dname_count_labels(ce); - /* Use longest closest encloser to prove wildcard. */ - if(ce_labs > prev_ce_labs || - (ce_labs == prev_ce_labs && - has_valid_wnsec == 0)) { - if(val_nsec_proves_no_wc(s, qchase->qname, - qchase->qname_len)) - has_valid_wnsec = 1; - else - has_valid_wnsec = 0; - } - prev_ce_labs = ce_labs; - if(val_nsec_proves_insecuredelegation(s, qchase)) { - verbose(VERB_ALGO, "delegation is insecure"); - chase_reply->security = sec_status_insecure; - return; - } - } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) - nsec3s_seen = 1; - } - - if((!has_valid_nsec || !has_valid_wnsec) && nsec3s_seen) { - /* use NSEC3 proof, both answer and auth rrsets, in case - * NSEC3s end up in the answer (due to qtype=NSEC3 or so) */ - chase_reply->security = nsec3_prove_nameerror(env, ve, - chase_reply->rrsets, chase_reply->an_numrrsets+ - chase_reply->ns_numrrsets, qchase, kkey); - if(chase_reply->security != sec_status_secure) { - verbose(VERB_QUERY, "NameError response failed nsec, " - "nsec3 proof was %s", sec_status_to_string( - chase_reply->security)); - return; - } - has_valid_nsec = 1; - has_valid_wnsec = 1; - } - - /* If the message fails to prove either condition, it is bogus. */ - if(!has_valid_nsec) { - verbose(VERB_QUERY, "NameError response has failed to prove: " - "qname does not exist"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - /* Be lenient with RCODE in NSEC NameError responses */ - validate_nodata_response(env, ve, qchase, chase_reply, kkey); - if (chase_reply->security == sec_status_secure) - *rcode = LDNS_RCODE_NOERROR; - return; - } - - if(!has_valid_wnsec) { - verbose(VERB_QUERY, "NameError response has failed to prove: " - "covering wildcard does not exist"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - /* Be lenient with RCODE in NSEC NameError responses */ - validate_nodata_response(env, ve, qchase, chase_reply, kkey); - if (chase_reply->security == sec_status_secure) - *rcode = LDNS_RCODE_NOERROR; - return; - } - - /* Otherwise, we consider the message secure. */ - verbose(VERB_ALGO, "successfully validated NAME ERROR response."); - chase_reply->security = sec_status_secure; -} - -/** - * Given a referral response, validate rrsets and take least trusted rrset - * as the current validation status. - * - * Note that by the time this method is called, the process of finding the - * trusted DNSKEY rrset that signs this response must already have been - * completed. - * - * @param chase_reply: answer to validate. - */ -static void -validate_referral_response(struct reply_info* chase_reply) -{ - size_t i; - enum sec_status s; - /* message security equals lowest rrset security */ - chase_reply->security = sec_status_secure; - for(i=0; irrset_count; i++) { - s = ((struct packed_rrset_data*)chase_reply->rrsets[i] - ->entry.data)->security; - if(s < chase_reply->security) - chase_reply->security = s; - } - verbose(VERB_ALGO, "validated part of referral response as %s", - sec_status_to_string(chase_reply->security)); -} - -/** - * Given an "ANY" response -- a response that contains an answer to a - * qtype==ANY question, with answers. This does no checking that all - * types are present. - * - * NOTE: it may be possible to get parent-side delegation point records - * here, which won't all be signed. Right now, this routine relies on the - * upstream iterative resolver to not return these responses -- instead - * treating them as referrals. - * - * NOTE: RFC 4035 is silent on this issue, so this may change upon - * clarification. Clarification draft -05 says to not check all types are - * present. - * - * Note that by the time this method is called, the process of finding the - * trusted DNSKEY rrset that signs this response must already have been - * completed. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - */ -static void -validate_any_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey) -{ - /* all answer and auth rrsets already verified */ - /* but check if a wildcard response is given, then check NSEC/NSEC3 - * for qname denial to see if wildcard is applicable */ - uint8_t* wc = NULL; - size_t wl; - int wc_NSEC_ok = 0; - int nsec3s_seen = 0; - size_t i; - struct ub_packed_rrset_key* s; - - if(qchase->qtype != LDNS_RR_TYPE_ANY) { - log_err("internal error: ANY validation called for non-ANY"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - /* validate the ANSWER section - this will be the answer itself */ - for(i=0; ian_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* Check to see if the rrset is the result of a wildcard - * expansion. If so, an additional check will need to be - * made in the authority section. */ - if(!val_rrset_wildcard(s, &wc, &wl)) { - log_nametypeclass(VERB_QUERY, "Positive ANY response" - " has inconsistent wildcard sigs:", - s->rk.dname, ntohs(s->rk.type), - ntohs(s->rk.rrset_class)); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - } - - /* if it was a wildcard, check for NSEC/NSEC3s in both answer - * and authority sections (NSEC may be moved to the ANSWER section) */ - if(wc != NULL) - for(i=0; ian_numrrsets+chase_reply->ns_numrrsets; - i++) { - s = chase_reply->rrsets[i]; - - /* If this is a positive wildcard response, and we have a - * (just verified) NSEC record, try to use it to 1) prove - * that qname doesn't exist and 2) that the correct wildcard - * was used. */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { - wc_NSEC_ok = 1; - } - /* if not, continue looking for proof */ - } - - /* Otherwise, if this is a positive wildcard response and - * we have NSEC3 records */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - nsec3s_seen = 1; - } - } - - /* If this was a positive wildcard response that we haven't already - * proven, and we have NSEC3 records, try to prove it using the NSEC3 - * records. */ - if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { - /* look both in answer and auth section for NSEC3s */ - enum sec_status sec = nsec3_prove_wildcard(env, ve, - chase_reply->rrsets, - chase_reply->an_numrrsets+chase_reply->ns_numrrsets, - qchase, kkey, wc); - if(sec == sec_status_insecure) { - verbose(VERB_ALGO, "Positive ANY wildcard response is " - "insecure"); - chase_reply->security = sec_status_insecure; - return; - } else if(sec == sec_status_secure) - wc_NSEC_ok = 1; - } - - /* If after all this, we still haven't proven the positive wildcard - * response, fail. */ - if(wc != NULL && !wc_NSEC_ok) { - verbose(VERB_QUERY, "positive ANY response was wildcard " - "expansion and did not prove original data " - "did not exist"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - verbose(VERB_ALGO, "Successfully validated positive ANY response"); - chase_reply->security = sec_status_secure; -} - -/** - * Validate CNAME response, or DNAME+CNAME. - * This is just like a positive proof, except that this is about a - * DNAME+CNAME. Possible wildcard proof. - * Difference with positive proof is that this routine refuses - * wildcarded DNAMEs. - * - * The answer and authority rrsets must already be verified as secure. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - */ -static void -validate_cname_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey) -{ - uint8_t* wc = NULL; - size_t wl; - int wc_NSEC_ok = 0; - int nsec3s_seen = 0; - size_t i; - struct ub_packed_rrset_key* s; - - /* validate the ANSWER section - this will be the CNAME (+DNAME) */ - for(i=0; ian_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* Check to see if the rrset is the result of a wildcard - * expansion. If so, an additional check will need to be - * made in the authority section. */ - if(!val_rrset_wildcard(s, &wc, &wl)) { - log_nametypeclass(VERB_QUERY, "Cname response has " - "inconsistent wildcard sigs:", s->rk.dname, - ntohs(s->rk.type), ntohs(s->rk.rrset_class)); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - /* Refuse wildcarded DNAMEs rfc 4597. - * Do not follow a wildcarded DNAME because - * its synthesized CNAME expansion is underdefined */ - if(qchase->qtype != LDNS_RR_TYPE_DNAME && - ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME && wc) { - log_nametypeclass(VERB_QUERY, "cannot validate a " - "wildcarded DNAME:", s->rk.dname, - ntohs(s->rk.type), ntohs(s->rk.rrset_class)); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - /* If we have found a CNAME, stop looking for one. - * The iterator has placed the CNAME chain in correct - * order. */ - if (ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { - break; - } - } - - /* AUTHORITY section */ - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* If this is a positive wildcard response, and we have a - * (just verified) NSEC record, try to use it to 1) prove - * that qname doesn't exist and 2) that the correct wildcard - * was used. */ - if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { - wc_NSEC_ok = 1; - } - /* if not, continue looking for proof */ - } - - /* Otherwise, if this is a positive wildcard response and - * we have NSEC3 records */ - if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - nsec3s_seen = 1; - } - } - - /* If this was a positive wildcard response that we haven't already - * proven, and we have NSEC3 records, try to prove it using the NSEC3 - * records. */ - if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { - enum sec_status sec = nsec3_prove_wildcard(env, ve, - chase_reply->rrsets+chase_reply->an_numrrsets, - chase_reply->ns_numrrsets, qchase, kkey, wc); - if(sec == sec_status_insecure) { - verbose(VERB_ALGO, "wildcard CNAME response is " - "insecure"); - chase_reply->security = sec_status_insecure; - return; - } else if(sec == sec_status_secure) - wc_NSEC_ok = 1; - } - - /* If after all this, we still haven't proven the positive wildcard - * response, fail. */ - if(wc != NULL && !wc_NSEC_ok) { - verbose(VERB_QUERY, "CNAME response was wildcard " - "expansion and did not prove original data " - "did not exist"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - verbose(VERB_ALGO, "Successfully validated CNAME response"); - chase_reply->security = sec_status_secure; -} - -/** - * Validate CNAME NOANSWER response, no more data after a CNAME chain. - * This can be a NODATA or a NAME ERROR case, but not both at the same time. - * We don't know because the rcode has been set to NOERROR by the CNAME. - * - * The answer and authority rrsets must already be verified as secure. - * - * @param env: module env for verify. - * @param ve: validator env for verify. - * @param qchase: query that was made. - * @param chase_reply: answer to that query to validate. - * @param kkey: the key entry, which is trusted, and which matches - * the signer of the answer. The key entry isgood(). - */ -static void -validate_cname_noanswer_response(struct module_env* env, struct val_env* ve, - struct query_info* qchase, struct reply_info* chase_reply, - struct key_entry_key* kkey) -{ - int nodata_valid_nsec = 0; /* If true, then NODATA has been proven.*/ - uint8_t* ce = NULL; /* for wildcard nodata responses. This is the - proven closest encloser. */ - uint8_t* wc = NULL; /* for wildcard nodata responses. wildcard nsec */ - int nxdomain_valid_nsec = 0; /* if true, nameerror has been proven */ - int nxdomain_valid_wnsec = 0; - int nsec3s_seen = 0; /* nsec3s seen */ - struct ub_packed_rrset_key* s; - size_t i; - uint8_t* nsec_ce; /* Used to find the NSEC with the longest ce */ - int ce_labs = 0; - int prev_ce_labs = 0; - - /* the AUTHORITY section */ - for(i=chase_reply->an_numrrsets; ian_numrrsets+ - chase_reply->ns_numrrsets; i++) { - s = chase_reply->rrsets[i]; - - /* If we encounter an NSEC record, try to use it to prove - * NODATA. This needs to handle the ENT NODATA case. - * Also try to prove NAMEERROR, and absence of a wildcard */ - if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { - if(nsec_proves_nodata(s, qchase, &wc)) { - nodata_valid_nsec = 1; - /* set wc encloser if wildcard applicable */ - } - if(val_nsec_proves_name_error(s, qchase->qname)) { - ce = nsec_closest_encloser(qchase->qname, s); - nxdomain_valid_nsec = 1; - } - nsec_ce = nsec_closest_encloser(qchase->qname, s); - ce_labs = dname_count_labels(nsec_ce); - /* Use longest closest encloser to prove wildcard. */ - if(ce_labs > prev_ce_labs || - (ce_labs == prev_ce_labs && - nxdomain_valid_wnsec == 0)) { - if(val_nsec_proves_no_wc(s, qchase->qname, - qchase->qname_len)) - nxdomain_valid_wnsec = 1; - else - nxdomain_valid_wnsec = 0; - } - prev_ce_labs = ce_labs; - if(val_nsec_proves_insecuredelegation(s, qchase)) { - verbose(VERB_ALGO, "delegation is insecure"); - chase_reply->security = sec_status_insecure; - return; - } - } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { - nsec3s_seen = 1; - } - } - - /* check to see if we have a wildcard NODATA proof. */ - - /* The wildcard NODATA is 1 NSEC proving that qname does not exists - * (and also proving what the closest encloser is), and 1 NSEC - * showing the matching wildcard, which must be *.closest_encloser. */ - if(wc && !ce) - nodata_valid_nsec = 0; - else if(wc && ce) { - if(query_dname_compare(wc, ce) != 0) { - nodata_valid_nsec = 0; - } - } - if(nxdomain_valid_nsec && !nxdomain_valid_wnsec) { - /* name error is missing wildcard denial proof */ - nxdomain_valid_nsec = 0; - } - - if(nodata_valid_nsec && nxdomain_valid_nsec) { - verbose(VERB_QUERY, "CNAMEchain to noanswer proves that name " - "exists and not exists, bogus"); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - if(!nodata_valid_nsec && !nxdomain_valid_nsec && nsec3s_seen) { - int nodata; - enum sec_status sec = nsec3_prove_nxornodata(env, ve, - chase_reply->rrsets+chase_reply->an_numrrsets, - chase_reply->ns_numrrsets, qchase, kkey, &nodata); - if(sec == sec_status_insecure) { - verbose(VERB_ALGO, "CNAMEchain to noanswer response " - "is insecure"); - chase_reply->security = sec_status_insecure; - return; - } else if(sec == sec_status_secure) { - if(nodata) - nodata_valid_nsec = 1; - else nxdomain_valid_nsec = 1; - } - } - - if(!nodata_valid_nsec && !nxdomain_valid_nsec) { - verbose(VERB_QUERY, "CNAMEchain to noanswer response failed " - "to prove status with NSEC/NSEC3"); - if(verbosity >= VERB_ALGO) - log_dns_msg("Failed CNAMEnoanswer", qchase, chase_reply); - chase_reply->security = sec_status_bogus; - update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS); - return; - } - - if(nodata_valid_nsec) - verbose(VERB_ALGO, "successfully validated CNAME chain to a " - "NODATA response."); - else verbose(VERB_ALGO, "successfully validated CNAME chain to a " - "NAMEERROR response."); - chase_reply->security = sec_status_secure; -} - -/** - * Process init state for validator. - * Process the INIT state. First tier responses start in the INIT state. - * This is where they are vetted for validation suitability, and the initial - * key search is done. - * - * Currently, events the come through this routine will be either promoted - * to FINISHED/CNAME_RESP (no validation needed), FINDKEY (next step to - * validation), or will be (temporarily) retired and a new priming request - * event will be generated. - * - * @param qstate: query state. - * @param vq: validator query state. - * @param ve: validator shared global environment. - * @param id: module id. - * @return true if the event should be processed further on return, false if - * not. - */ -static int -processInit(struct module_qstate* qstate, struct val_qstate* vq, - struct val_env* ve, int id) -{ - uint8_t* lookup_name; - size_t lookup_len; - struct trust_anchor* anchor; - enum val_classification subtype = val_classify_response( - qstate->query_flags, &qstate->qinfo, &vq->qchase, - vq->orig_msg->rep, vq->rrset_skip); - if(vq->restart_count > ve->max_restart) { - verbose(VERB_ALGO, "restart count exceeded"); - return val_error(qstate, id); - } - - /* correctly initialize reason_bogus */ - update_reason_bogus(vq->chase_reply, LDNS_EDE_DNSSEC_BOGUS); - - verbose(VERB_ALGO, "validator classification %s", - val_classification_to_string(subtype)); - if(subtype == VAL_CLASS_REFERRAL && - vq->rrset_skip < vq->orig_msg->rep->rrset_count) { - /* referral uses the rrset name as qchase, to find keys for - * that rrset */ - vq->qchase.qname = vq->orig_msg->rep-> - rrsets[vq->rrset_skip]->rk.dname; - vq->qchase.qname_len = vq->orig_msg->rep-> - rrsets[vq->rrset_skip]->rk.dname_len; - vq->qchase.qtype = ntohs(vq->orig_msg->rep-> - rrsets[vq->rrset_skip]->rk.type); - vq->qchase.qclass = ntohs(vq->orig_msg->rep-> - rrsets[vq->rrset_skip]->rk.rrset_class); - } - lookup_name = vq->qchase.qname; - lookup_len = vq->qchase.qname_len; - /* for type DS look at the parent side for keys/trustanchor */ - /* also for NSEC not at apex */ - if(vq->qchase.qtype == LDNS_RR_TYPE_DS || - (vq->qchase.qtype == LDNS_RR_TYPE_NSEC && - vq->orig_msg->rep->rrset_count > vq->rrset_skip && - ntohs(vq->orig_msg->rep->rrsets[vq->rrset_skip]->rk.type) == - LDNS_RR_TYPE_NSEC && - !(vq->orig_msg->rep->rrsets[vq->rrset_skip]-> - rk.flags&PACKED_RRSET_NSEC_AT_APEX))) { - dname_remove_label(&lookup_name, &lookup_len); - } - - val_mark_indeterminate(vq->chase_reply, qstate->env->anchors, - qstate->env->rrset_cache, qstate->env); - vq->key_entry = NULL; - vq->empty_DS_name = NULL; - vq->ds_rrset = 0; - anchor = anchors_lookup(qstate->env->anchors, - lookup_name, lookup_len, vq->qchase.qclass); - - /* Determine the signer/lookup name */ - val_find_signer(subtype, &vq->qchase, vq->orig_msg->rep, - vq->rrset_skip, &vq->signer_name, &vq->signer_len); - if(vq->signer_name != NULL && - !dname_subdomain_c(lookup_name, vq->signer_name)) { - log_nametypeclass(VERB_ALGO, "this signer name is not a parent " - "of lookupname, omitted", vq->signer_name, 0, 0); - vq->signer_name = NULL; - } - if(vq->signer_name == NULL) { - log_nametypeclass(VERB_ALGO, "no signer, using", lookup_name, - 0, 0); - } else { - lookup_name = vq->signer_name; - lookup_len = vq->signer_len; - log_nametypeclass(VERB_ALGO, "signer is", lookup_name, 0, 0); - } - - /* for NXDOMAIN it could be signed by a parent of the trust anchor */ - if(subtype == VAL_CLASS_NAMEERROR && vq->signer_name && - anchor && dname_strict_subdomain_c(anchor->name, lookup_name)){ - lock_basic_unlock(&anchor->lock); - anchor = anchors_lookup(qstate->env->anchors, - lookup_name, lookup_len, vq->qchase.qclass); - if(!anchor) { /* unsigned parent denies anchor*/ - verbose(VERB_QUERY, "unsigned parent zone denies" - " trust anchor, indeterminate"); - vq->chase_reply->security = sec_status_indeterminate; - update_reason_bogus(vq->chase_reply, LDNS_EDE_DNSSEC_INDETERMINATE); - vq->state = VAL_FINISHED_STATE; - return 1; - } - verbose(VERB_ALGO, "trust anchor NXDOMAIN by signed parent"); - } else if(subtype == VAL_CLASS_POSITIVE && - qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY && - query_dname_compare(lookup_name, qstate->qinfo.qname) == 0) { - /* is a DNSKEY so lookup a bit higher since we want to - * get it from a parent or from trustanchor */ - dname_remove_label(&lookup_name, &lookup_len); - } - - if(vq->rrset_skip > 0 || subtype == VAL_CLASS_CNAME || - subtype == VAL_CLASS_REFERRAL) { - /* extract this part of orig_msg into chase_reply for - * the eventual VALIDATE stage */ - val_fill_reply(vq->chase_reply, vq->orig_msg->rep, - vq->rrset_skip, lookup_name, lookup_len, - vq->signer_name); - if(verbosity >= VERB_ALGO) - log_dns_msg("chased extract", &vq->qchase, - vq->chase_reply); - } - - vq->key_entry = key_cache_obtain(ve->kcache, lookup_name, lookup_len, - vq->qchase.qclass, qstate->region, *qstate->env->now); - - /* there is no key and no trust anchor */ - if(vq->key_entry == NULL && anchor == NULL) { - /*response isn't under a trust anchor, so we cannot validate.*/ - vq->chase_reply->security = sec_status_indeterminate; - update_reason_bogus(vq->chase_reply, LDNS_EDE_DNSSEC_INDETERMINATE); - /* go to finished state to cache this result */ - vq->state = VAL_FINISHED_STATE; - return 1; - } - /* if not key, or if keyentry is *above* the trustanchor, i.e. - * the keyentry is based on another (higher) trustanchor */ - else if(vq->key_entry == NULL || (anchor && - dname_strict_subdomain_c(anchor->name, vq->key_entry->name))) { - /* trust anchor is an 'unsigned' trust anchor */ - if(anchor && anchor->numDS == 0 && anchor->numDNSKEY == 0) { - vq->chase_reply->security = sec_status_insecure; - val_mark_insecure(vq->chase_reply, anchor->name, - qstate->env->rrset_cache, qstate->env); - lock_basic_unlock(&anchor->lock); - /* go to finished state to cache this result */ - vq->state = VAL_FINISHED_STATE; - return 1; - } - /* fire off a trust anchor priming query. */ - verbose(VERB_DETAIL, "prime trust anchor"); - if(!prime_trust_anchor(qstate, vq, id, anchor)) { - lock_basic_unlock(&anchor->lock); - return val_error(qstate, id); - } - lock_basic_unlock(&anchor->lock); - /* and otherwise, don't continue processing this event. - * (it will be reactivated when the priming query returns). */ - vq->state = VAL_FINDKEY_STATE; - return 0; - } - if(anchor) { - lock_basic_unlock(&anchor->lock); - } - - if(key_entry_isnull(vq->key_entry)) { - /* response is under a null key, so we cannot validate - * However, we do set the status to INSECURE, since it is - * essentially proven insecure. */ - vq->chase_reply->security = sec_status_insecure; - val_mark_insecure(vq->chase_reply, vq->key_entry->name, - qstate->env->rrset_cache, qstate->env); - /* go to finished state to cache this result */ - vq->state = VAL_FINISHED_STATE; - return 1; - } else if(key_entry_isbad(vq->key_entry)) { - /* Bad keys should have the relevant EDE code and text */ - sldns_ede_code ede = key_entry_get_reason_bogus(vq->key_entry); - /* key is bad, chain is bad, reply is bogus */ - errinf_dname(qstate, "key for validation", vq->key_entry->name); - errinf_ede(qstate, "is marked as invalid", ede); - errinf(qstate, "because of a previous"); - errinf(qstate, key_entry_get_reason(vq->key_entry)); - - /* no retries, stop bothering the authority until timeout */ - vq->restart_count = ve->max_restart; - vq->chase_reply->security = sec_status_bogus; - update_reason_bogus(vq->chase_reply, ede); - vq->state = VAL_FINISHED_STATE; - return 1; - } - - /* otherwise, we have our "closest" cached key -- continue - * processing in the next state. */ - vq->state = VAL_FINDKEY_STATE; - return 1; -} - -/** - * Process the FINDKEY state. Generally this just calculates the next name - * to query and either issues a DS or a DNSKEY query. It will check to see - * if the correct key has already been reached, in which case it will - * advance the event to the next state. - * - * @param qstate: query state. - * @param vq: validator query state. - * @param id: module id. - * @return true if the event should be processed further on return, false if - * not. - */ -static int -processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) -{ - uint8_t* target_key_name, *current_key_name; - size_t target_key_len; - int strip_lab; - struct module_qstate* newq = NULL; - - log_query_info(VERB_ALGO, "validator: FindKey", &vq->qchase); - /* We know that state.key_entry is not 0 or bad key -- if it were, - * then previous processing should have directed this event to - * a different state. - * It could be an isnull key, which signals the DNSKEY failed - * with retry and has to be looked up again. */ - log_assert(vq->key_entry && !key_entry_isbad(vq->key_entry)); - if(key_entry_isnull(vq->key_entry)) { - if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, - vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, - vq->qchase.qclass, BIT_CD, &newq, 0)) { - verbose(VERB_ALGO, "error generating DNSKEY request"); - return val_error(qstate, id); - } - return 0; - } - - target_key_name = vq->signer_name; - target_key_len = vq->signer_len; - if(!target_key_name) { - target_key_name = vq->qchase.qname; - target_key_len = vq->qchase.qname_len; - } - - current_key_name = vq->key_entry->name; - - /* If our current key entry matches our target, then we are done. */ - if(query_dname_compare(target_key_name, current_key_name) == 0) { - vq->state = VAL_VALIDATE_STATE; - return 1; - } - - if(vq->empty_DS_name) { - /* if the last empty nonterminal/emptyDS name we detected is - * below the current key, use that name to make progress - * along the chain of trust */ - if(query_dname_compare(target_key_name, - vq->empty_DS_name) == 0) { - /* do not query for empty_DS_name again */ - verbose(VERB_ALGO, "Cannot retrieve DS for signature"); - errinf_ede(qstate, "no signatures", LDNS_EDE_RRSIGS_MISSING); - errinf_origin(qstate, qstate->reply_origin); - vq->chase_reply->security = sec_status_bogus; - update_reason_bogus(vq->chase_reply, LDNS_EDE_RRSIGS_MISSING); - vq->state = VAL_FINISHED_STATE; - return 1; - } - current_key_name = vq->empty_DS_name; - } - - log_nametypeclass(VERB_ALGO, "current keyname", current_key_name, - LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); - log_nametypeclass(VERB_ALGO, "target keyname", target_key_name, - LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); - /* assert we are walking down the DNS tree */ - if(!dname_subdomain_c(target_key_name, current_key_name)) { - verbose(VERB_ALGO, "bad signer name"); - vq->chase_reply->security = sec_status_bogus; - vq->state = VAL_FINISHED_STATE; - return 1; - } - /* so this value is >= -1 */ - strip_lab = dname_count_labels(target_key_name) - - dname_count_labels(current_key_name) - 1; - log_assert(strip_lab >= -1); - verbose(VERB_ALGO, "striplab %d", strip_lab); - if(strip_lab > 0) { - dname_remove_labels(&target_key_name, &target_key_len, - strip_lab); - } - log_nametypeclass(VERB_ALGO, "next keyname", target_key_name, - LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); - - /* The next step is either to query for the next DS, or to query - * for the next DNSKEY. */ - if(vq->ds_rrset) - log_nametypeclass(VERB_ALGO, "DS RRset", vq->ds_rrset->rk.dname, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN); - else verbose(VERB_ALGO, "No DS RRset"); - - if(vq->ds_rrset && query_dname_compare(vq->ds_rrset->rk.dname, - vq->key_entry->name) != 0) { - if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, - vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, - vq->qchase.qclass, BIT_CD, &newq, 0)) { - verbose(VERB_ALGO, "error generating DNSKEY request"); - return val_error(qstate, id); - } - return 0; - } - - if(!vq->ds_rrset || query_dname_compare(vq->ds_rrset->rk.dname, - target_key_name) != 0) { - /* check if there is a cache entry : pick up an NSEC if - * there is no DS, check if that NSEC has DS-bit unset, and - * thus can disprove the secure delegation we seek. - * We can then use that NSEC even in the absence of a SOA - * record that would be required by the iterator to supply - * a completely protocol-correct response. - * Uses negative cache for NSEC3 lookup of DS responses. */ - /* only if cache not blacklisted, of course */ - struct dns_msg* msg; - if(!qstate->blacklist && !vq->chain_blacklist && - (msg=val_find_DS(qstate->env, target_key_name, - target_key_len, vq->qchase.qclass, qstate->region, - vq->key_entry->name)) ) { - verbose(VERB_ALGO, "Process cached DS response"); - process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR, - msg, &msg->qinfo, NULL); - return 1; /* continue processing ds-response results */ - } - if(!generate_request(qstate, id, target_key_name, - target_key_len, LDNS_RR_TYPE_DS, vq->qchase.qclass, - BIT_CD, &newq, 0)) { - verbose(VERB_ALGO, "error generating DS request"); - return val_error(qstate, id); - } - return 0; - } - - /* Otherwise, it is time to query for the DNSKEY */ - if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, - vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, - vq->qchase.qclass, BIT_CD, &newq, 0)) { - verbose(VERB_ALGO, "error generating DNSKEY request"); - return val_error(qstate, id); - } - - return 0; -} - -/** - * Process the VALIDATE stage, the init and findkey stages are finished, - * and the right keys are available to validate the response. - * Or, there are no keys available, in order to invalidate the response. - * - * After validation, the status is recorded in the message and rrsets, - * and finished state is started. - * - * @param qstate: query state. - * @param vq: validator query state. - * @param ve: validator shared global environment. - * @param id: module id. - * @return true if the event should be processed further on return, false if - * not. - */ -static int -processValidate(struct module_qstate* qstate, struct val_qstate* vq, - struct val_env* ve, int id) -{ - enum val_classification subtype; - int rcode; - - if(!vq->key_entry) { - verbose(VERB_ALGO, "validate: no key entry, failed"); - return val_error(qstate, id); - } - - /* This is the default next state. */ - vq->state = VAL_FINISHED_STATE; - - /* Unsigned responses must be underneath a "null" key entry.*/ - if(key_entry_isnull(vq->key_entry)) { - verbose(VERB_DETAIL, "Verified that %sresponse is INSECURE", - vq->signer_name?"":"unsigned "); - vq->chase_reply->security = sec_status_insecure; - val_mark_insecure(vq->chase_reply, vq->key_entry->name, - qstate->env->rrset_cache, qstate->env); - key_cache_insert(ve->kcache, vq->key_entry, - qstate->env->cfg->val_log_level >= 2); - return 1; - } - - if(key_entry_isbad(vq->key_entry)) { - log_nametypeclass(VERB_DETAIL, "Could not establish a chain " - "of trust to keys for", vq->key_entry->name, - LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class); - vq->chase_reply->security = sec_status_bogus; - update_reason_bogus(vq->chase_reply, - key_entry_get_reason_bogus(vq->key_entry)); - errinf_ede(qstate, "while building chain of trust", - key_entry_get_reason_bogus(vq->key_entry)); - if(vq->restart_count >= ve->max_restart) - key_cache_insert(ve->kcache, vq->key_entry, - qstate->env->cfg->val_log_level >= 2); - return 1; - } - - /* signerName being null is the indicator that this response was - * unsigned */ - if(vq->signer_name == NULL) { - log_query_info(VERB_ALGO, "processValidate: state has no " - "signer name", &vq->qchase); - verbose(VERB_DETAIL, "Could not establish validation of " - "INSECURE status of unsigned response."); - errinf_ede(qstate, "no signatures", LDNS_EDE_RRSIGS_MISSING); - errinf_origin(qstate, qstate->reply_origin); - vq->chase_reply->security = sec_status_bogus; - update_reason_bogus(vq->chase_reply, LDNS_EDE_RRSIGS_MISSING); - return 1; - } - subtype = val_classify_response(qstate->query_flags, &qstate->qinfo, - &vq->qchase, vq->orig_msg->rep, vq->rrset_skip); - if(subtype != VAL_CLASS_REFERRAL) - remove_spurious_authority(vq->chase_reply, vq->orig_msg->rep); - - /* check signatures in the message; - * answer and authority must be valid, additional is only checked. */ - if(!validate_msg_signatures(qstate, qstate->env, ve, &vq->qchase, - vq->chase_reply, vq->key_entry)) { - /* workaround bad recursor out there that truncates (even - * with EDNS4k) to 512 by removing RRSIG from auth section - * for positive replies*/ - if((subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY - || subtype == VAL_CLASS_CNAME) && - detect_wrongly_truncated(vq->orig_msg->rep)) { - /* truncate the message some more */ - vq->orig_msg->rep->ns_numrrsets = 0; - vq->orig_msg->rep->ar_numrrsets = 0; - vq->orig_msg->rep->rrset_count = - vq->orig_msg->rep->an_numrrsets; - vq->chase_reply->ns_numrrsets = 0; - vq->chase_reply->ar_numrrsets = 0; - vq->chase_reply->rrset_count = - vq->chase_reply->an_numrrsets; - qstate->errinf = NULL; - } - else { - verbose(VERB_DETAIL, "Validate: message contains " - "bad rrsets"); - return 1; - } - } - - switch(subtype) { - case VAL_CLASS_POSITIVE: - verbose(VERB_ALGO, "Validating a positive response"); - validate_positive_response(qstate->env, ve, - &vq->qchase, vq->chase_reply, vq->key_entry); - verbose(VERB_DETAIL, "validate(positive): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - case VAL_CLASS_NODATA: - verbose(VERB_ALGO, "Validating a nodata response"); - validate_nodata_response(qstate->env, ve, - &vq->qchase, vq->chase_reply, vq->key_entry); - verbose(VERB_DETAIL, "validate(nodata): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - case VAL_CLASS_NAMEERROR: - rcode = (int)FLAGS_GET_RCODE(vq->orig_msg->rep->flags); - verbose(VERB_ALGO, "Validating a nxdomain response"); - validate_nameerror_response(qstate->env, ve, - &vq->qchase, vq->chase_reply, vq->key_entry, &rcode); - verbose(VERB_DETAIL, "validate(nxdomain): %s", - sec_status_to_string( - vq->chase_reply->security)); - FLAGS_SET_RCODE(vq->orig_msg->rep->flags, rcode); - FLAGS_SET_RCODE(vq->chase_reply->flags, rcode); - break; - - case VAL_CLASS_CNAME: - verbose(VERB_ALGO, "Validating a cname response"); - validate_cname_response(qstate->env, ve, - &vq->qchase, vq->chase_reply, vq->key_entry); - verbose(VERB_DETAIL, "validate(cname): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - case VAL_CLASS_CNAMENOANSWER: - verbose(VERB_ALGO, "Validating a cname noanswer " - "response"); - validate_cname_noanswer_response(qstate->env, ve, - &vq->qchase, vq->chase_reply, vq->key_entry); - verbose(VERB_DETAIL, "validate(cname_noanswer): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - case VAL_CLASS_REFERRAL: - verbose(VERB_ALGO, "Validating a referral response"); - validate_referral_response(vq->chase_reply); - verbose(VERB_DETAIL, "validate(referral): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - case VAL_CLASS_ANY: - verbose(VERB_ALGO, "Validating a positive ANY " - "response"); - validate_any_response(qstate->env, ve, &vq->qchase, - vq->chase_reply, vq->key_entry); - verbose(VERB_DETAIL, "validate(positive_any): %s", - sec_status_to_string( - vq->chase_reply->security)); - break; - - default: - log_err("validate: unhandled response subtype: %d", - subtype); - } - if(vq->chase_reply->security == sec_status_bogus) { - if(subtype == VAL_CLASS_POSITIVE) - errinf(qstate, "wildcard"); - else errinf(qstate, val_classification_to_string(subtype)); - errinf(qstate, "proof failed"); - errinf_origin(qstate, qstate->reply_origin); - } - - return 1; -} - -/** - * The Finished state. The validation status (good or bad) has been determined. - * - * @param qstate: query state. - * @param vq: validator query state. - * @param ve: validator shared global environment. - * @param id: module id. - * @return true if the event should be processed further on return, false if - * not. - */ -static int -processFinished(struct module_qstate* qstate, struct val_qstate* vq, - struct val_env* ve, int id) -{ - enum val_classification subtype = val_classify_response( - qstate->query_flags, &qstate->qinfo, &vq->qchase, - vq->orig_msg->rep, vq->rrset_skip); - - /* store overall validation result in orig_msg */ - if(vq->rrset_skip == 0) { - vq->orig_msg->rep->security = vq->chase_reply->security; - update_reason_bogus(vq->orig_msg->rep, vq->chase_reply->reason_bogus); - } else if(subtype != VAL_CLASS_REFERRAL || - vq->rrset_skip < vq->orig_msg->rep->an_numrrsets + - vq->orig_msg->rep->ns_numrrsets) { - /* ignore sec status of additional section if a referral - * type message skips there and - * use the lowest security status as end result. */ - if(vq->chase_reply->security < vq->orig_msg->rep->security) { - vq->orig_msg->rep->security = - vq->chase_reply->security; - update_reason_bogus(vq->orig_msg->rep, vq->chase_reply->reason_bogus); - } - } - - if(subtype == VAL_CLASS_REFERRAL) { - /* for a referral, move to next unchecked rrset and check it*/ - vq->rrset_skip = val_next_unchecked(vq->orig_msg->rep, - vq->rrset_skip); - if(vq->rrset_skip < vq->orig_msg->rep->rrset_count) { - /* and restart for this rrset */ - verbose(VERB_ALGO, "validator: go to next rrset"); - vq->chase_reply->security = sec_status_unchecked; - vq->state = VAL_INIT_STATE; - return 1; - } - /* referral chase is done */ - } - if(vq->chase_reply->security != sec_status_bogus && - subtype == VAL_CLASS_CNAME) { - /* chase the CNAME; process next part of the message */ - if(!val_chase_cname(&vq->qchase, vq->orig_msg->rep, - &vq->rrset_skip)) { - verbose(VERB_ALGO, "validator: failed to chase CNAME"); - vq->orig_msg->rep->security = sec_status_bogus; - update_reason_bogus(vq->orig_msg->rep, LDNS_EDE_DNSSEC_BOGUS); - } else { - /* restart process for new qchase at rrset_skip */ - log_query_info(VERB_ALGO, "validator: chased to", - &vq->qchase); - vq->chase_reply->security = sec_status_unchecked; - vq->state = VAL_INIT_STATE; - return 1; - } - } - - if(vq->orig_msg->rep->security == sec_status_secure) { - /* If the message is secure, check that all rrsets are - * secure (i.e. some inserted RRset for CNAME chain with - * a different signer name). And drop additional rrsets - * that are not secure (if clean-additional option is set) */ - /* this may cause the msg to be marked bogus */ - val_check_nonsecure(qstate->env, vq->orig_msg->rep); - if(vq->orig_msg->rep->security == sec_status_secure) { - log_query_info(VERB_DETAIL, "validation success", - &qstate->qinfo); - if(!qstate->no_cache_store) { - val_neg_addreply(qstate->env->neg_cache, - vq->orig_msg->rep); - } - } - } - - /* if the result is bogus - set message ttl to bogus ttl to avoid - * endless bogus revalidation */ - if(vq->orig_msg->rep->security == sec_status_bogus) { - /* see if we can try again to fetch data */ - if(vq->restart_count < ve->max_restart) { - int restart_count = vq->restart_count+1; - verbose(VERB_ALGO, "validation failed, " - "blacklist and retry to fetch data"); - val_blacklist(&qstate->blacklist, qstate->region, - qstate->reply_origin, 0); - qstate->reply_origin = NULL; - qstate->errinf = NULL; - memset(vq, 0, sizeof(*vq)); - vq->restart_count = restart_count; - vq->state = VAL_INIT_STATE; - verbose(VERB_ALGO, "pass back to next module"); - qstate->ext_state[id] = module_restart_next; - return 0; - } - - vq->orig_msg->rep->ttl = ve->bogus_ttl; - vq->orig_msg->rep->prefetch_ttl = - PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl); - vq->orig_msg->rep->serve_expired_ttl = - vq->orig_msg->rep->ttl + qstate->env->cfg->serve_expired_ttl; - if((qstate->env->cfg->val_log_level >= 1 || - qstate->env->cfg->log_servfail) && - !qstate->env->cfg->val_log_squelch) { - if(qstate->env->cfg->val_log_level < 2 && - !qstate->env->cfg->log_servfail) - log_query_info(NO_VERBOSE, "validation failure", - &qstate->qinfo); - else { - char* err_str = errinf_to_str_bogus(qstate); - if(err_str) { - size_t err_str_len = strlen(err_str); - log_info("%s", err_str); - /* allocate space and store the error - * string */ - vq->orig_msg->rep->reason_bogus_str = regional_alloc( - qstate->region, - sizeof(char) * (err_str_len+1)); - memcpy(vq->orig_msg->rep->reason_bogus_str, - err_str, err_str_len+1); - } - free(err_str); - } - } - /* - * If set, the validator will not make messages bogus, instead - * indeterminate is issued, so that no clients receive SERVFAIL. - * This allows an operator to run validation 'shadow' without - * hurting responses to clients. - */ - /* If we are in permissive mode, bogus gets indeterminate */ - if(qstate->env->cfg->val_permissive_mode) - vq->orig_msg->rep->security = sec_status_indeterminate; - } - - if(vq->orig_msg->rep->security == sec_status_secure && - qstate->env->cfg->root_key_sentinel && - (qstate->qinfo.qtype == LDNS_RR_TYPE_A || - qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)) { - char* keytag_start; - uint16_t keytag; - if(*qstate->qinfo.qname == strlen(SENTINEL_IS) + - SENTINEL_KEYTAG_LEN && - dname_lab_startswith(qstate->qinfo.qname, SENTINEL_IS, - &keytag_start)) { - if(sentinel_get_keytag(keytag_start, &keytag) && - !anchor_has_keytag(qstate->env->anchors, - (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) { - vq->orig_msg->rep->security = - sec_status_secure_sentinel_fail; - } - } else if(*qstate->qinfo.qname == strlen(SENTINEL_NOT) + - SENTINEL_KEYTAG_LEN && - dname_lab_startswith(qstate->qinfo.qname, SENTINEL_NOT, - &keytag_start)) { - if(sentinel_get_keytag(keytag_start, &keytag) && - anchor_has_keytag(qstate->env->anchors, - (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) { - vq->orig_msg->rep->security = - sec_status_secure_sentinel_fail; - } - } - } - - /* Update rep->reason_bogus as it is the one being cached */ - update_reason_bogus(vq->orig_msg->rep, errinf_to_reason_bogus(qstate)); - /* store results in cache */ - if(qstate->query_flags&BIT_RD) { - /* if secure, this will override cache anyway, no need - * to check if from parentNS */ - if(!qstate->no_cache_store) { - if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, - vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL, - qstate->query_flags, qstate->qstarttime)) { - log_err("out of memory caching validator results"); - } - } - } else { - /* for a referral, store the verified RRsets */ - /* and this does not get prefetched, so no leeway */ - if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, - vq->orig_msg->rep, 1, 0, 0, NULL, - qstate->query_flags, qstate->qstarttime)) { - log_err("out of memory caching validator results"); - } - } - qstate->return_rcode = LDNS_RCODE_NOERROR; - qstate->return_msg = vq->orig_msg; - qstate->ext_state[id] = module_finished; - return 0; -} - -/** - * Handle validator state. - * If a method returns true, the next state is started. If false, then - * processing will stop. - * @param qstate: query state. - * @param vq: validator query state. - * @param ve: validator shared global environment. - * @param id: module id. - */ -static void -val_handle(struct module_qstate* qstate, struct val_qstate* vq, - struct val_env* ve, int id) -{ - int cont = 1; - while(cont) { - verbose(VERB_ALGO, "val handle processing q with state %s", - val_state_to_string(vq->state)); - switch(vq->state) { - case VAL_INIT_STATE: - cont = processInit(qstate, vq, ve, id); - break; - case VAL_FINDKEY_STATE: - cont = processFindKey(qstate, vq, id); - break; - case VAL_VALIDATE_STATE: - cont = processValidate(qstate, vq, ve, id); - break; - case VAL_FINISHED_STATE: - cont = processFinished(qstate, vq, ve, id); - break; - default: - log_warn("validator: invalid state %d", - vq->state); - cont = 0; - break; - } - } -} - -void -val_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id]; - verbose(VERB_QUERY, "validator[module %d] operate: extstate:%s " - "event:%s", id, strextstate(qstate->ext_state[id]), - strmodulevent(event)); - log_query_info(VERB_QUERY, "validator operate: query", - &qstate->qinfo); - if(vq && qstate->qinfo.qname != vq->qchase.qname) - log_query_info(VERB_QUERY, "validator operate: chased to", - &vq->qchase); - (void)outbound; - if(event == module_event_new || - (event == module_event_pass && vq == NULL)) { - - /* pass request to next module, to get it */ - verbose(VERB_ALGO, "validator: pass to next module"); - qstate->ext_state[id] = module_wait_module; - return; - } - if(event == module_event_moddone) { - /* check if validation is needed */ - verbose(VERB_ALGO, "validator: nextmodule returned"); - - if(!needs_validation(qstate, qstate->return_rcode, - qstate->return_msg)) { - /* no need to validate this */ - if(qstate->return_msg) - qstate->return_msg->rep->security = - sec_status_indeterminate; - qstate->ext_state[id] = module_finished; - return; - } - if(already_validated(qstate->return_msg)) { - qstate->ext_state[id] = module_finished; - return; - } - /* qclass ANY should have validation result from spawned - * queries. If we get here, it is bogus or an internal error */ - if(qstate->qinfo.qclass == LDNS_RR_CLASS_ANY) { - verbose(VERB_ALGO, "cannot validate classANY: bogus"); - if(qstate->return_msg) { - qstate->return_msg->rep->security = - sec_status_bogus; - update_reason_bogus(qstate->return_msg->rep, LDNS_EDE_DNSSEC_BOGUS); - } - qstate->ext_state[id] = module_finished; - return; - } - /* create state to start validation */ - qstate->ext_state[id] = module_error; /* override this */ - if(!vq) { - vq = val_new(qstate, id); - if(!vq) { - log_err("validator: malloc failure"); - qstate->ext_state[id] = module_error; - return; - } - } else if(!vq->orig_msg) { - if(!val_new_getmsg(qstate, vq)) { - log_err("validator: malloc failure"); - qstate->ext_state[id] = module_error; - return; - } - } - val_handle(qstate, vq, ve, id); - return; - } - if(event == module_event_pass) { - qstate->ext_state[id] = module_error; /* override this */ - /* continue processing, since val_env exists */ - val_handle(qstate, vq, ve, id); - return; - } - log_err("validator: bad event %s", strmodulevent(event)); - qstate->ext_state[id] = module_error; - return; -} - -/** - * Evaluate the response to a priming request. - * - * @param dnskey_rrset: DNSKEY rrset (can be NULL if none) in prime reply. - * (this rrset is allocated in the wrong region, not the qstate). - * @param ta: trust anchor. - * @param qstate: qstate that needs key. - * @param id: module id. - * @return new key entry or NULL on allocation failure. - * The key entry will either contain a validated DNSKEY rrset, or - * represent a Null key (query failed, but validation did not), or a - * Bad key (validation failed). - */ -static struct key_entry_key* -primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, - struct trust_anchor* ta, struct module_qstate* qstate, int id) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - struct key_entry_key* kkey = NULL; - enum sec_status sec = sec_status_unchecked; - char* reason = NULL; - sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - int downprot = qstate->env->cfg->harden_algo_downgrade; - - if(!dnskey_rrset) { - log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- " - "could not fetch DNSKEY rrset", - ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); - reason_bogus = LDNS_EDE_DNSKEY_MISSING; - reason = "no DNSKEY rrset"; - if(qstate->env->cfg->harden_dnssec_stripped) { - errinf_ede(qstate, reason, reason_bogus); - kkey = key_entry_create_bad(qstate->region, ta->name, - ta->namelen, ta->dclass, BOGUS_KEY_TTL, - reason_bogus, reason, - *qstate->env->now); - } else kkey = key_entry_create_null(qstate->region, ta->name, - ta->namelen, ta->dclass, NULL_KEY_TTL, - reason_bogus, reason, - *qstate->env->now); - if(!kkey) { - log_err("out of memory: allocate fail prime key"); - return NULL; - } - return kkey; - } - /* attempt to verify with trust anchor DS and DNSKEY */ - kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, - dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot, - &reason, &reason_bogus, qstate); - if(!kkey) { - log_err("out of memory: verifying prime TA"); - return NULL; - } - if(key_entry_isgood(kkey)) - sec = sec_status_secure; - else - sec = sec_status_bogus; - verbose(VERB_DETAIL, "validate keys with anchor(DS): %s", - sec_status_to_string(sec)); - - if(sec != sec_status_secure) { - log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- " - "DNSKEY rrset is not secure", - ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); - /* NOTE: in this case, we should probably reject the trust - * anchor for longer, perhaps forever. */ - if(qstate->env->cfg->harden_dnssec_stripped) { - errinf_ede(qstate, reason, reason_bogus); - kkey = key_entry_create_bad(qstate->region, ta->name, - ta->namelen, ta->dclass, BOGUS_KEY_TTL, - reason_bogus, reason, - *qstate->env->now); - } else kkey = key_entry_create_null(qstate->region, ta->name, - ta->namelen, ta->dclass, NULL_KEY_TTL, - reason_bogus, reason, - *qstate->env->now); - if(!kkey) { - log_err("out of memory: allocate null prime key"); - return NULL; - } - return kkey; - } - - log_nametypeclass(VERB_DETAIL, "Successfully primed trust anchor", - ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); - return kkey; -} - -/** - * In inform supers, with the resulting message and rcode and the current - * keyset in the super state, validate the DS response, returning a KeyEntry. - * - * @param qstate: query state that is validating and asked for a DS. - * @param vq: validator query state - * @param id: module id. - * @param rcode: rcode result value. - * @param msg: result message (if rcode is OK). - * @param qinfo: from the sub query state, query info. - * @param ke: the key entry to return. It returns - * is_bad if the DS response fails to validate, is_null if the - * DS response indicated an end to secure space, is_good if the DS - * validated. It returns ke=NULL if the DS response indicated that the - * request wasn't a delegation point. - * @return 0 on servfail error (malloc failure). - */ -static int -ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, - int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct key_entry_key** ke) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - char* reason = NULL; - sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - enum val_classification subtype; - if(rcode != LDNS_RCODE_NOERROR) { - char rc[16]; - rc[0]=0; - (void)sldns_wire2str_rcode_buf(rcode, rc, sizeof(rc)); - /* errors here pretty much break validation */ - verbose(VERB_DETAIL, "DS response was error, thus bogus"); - errinf(qstate, rc); - reason = "no DS"; - reason_bogus = LDNS_EDE_NETWORK_ERROR; - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - - subtype = val_classify_response(BIT_RD, qinfo, qinfo, msg->rep, 0); - if(subtype == VAL_CLASS_POSITIVE) { - struct ub_packed_rrset_key* ds; - enum sec_status sec; - ds = reply_find_answer_rrset(qinfo, msg->rep); - /* If there was no DS rrset, then we have mis-classified - * this message. */ - if(!ds) { - log_warn("internal error: POSITIVE DS response was " - "missing DS."); - reason = "no DS record"; - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - /* Verify only returns BOGUS or SECURE. If the rrset is - * bogus, then we are done. */ - sec = val_verify_rrset_entry(qstate->env, ve, ds, - vq->key_entry, &reason, &reason_bogus, LDNS_SECTION_ANSWER, qstate); - if(sec != sec_status_secure) { - verbose(VERB_DETAIL, "DS rrset in DS response did " - "not verify"); - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - - /* If the DS rrset validates, we still have to make sure - * that they are usable. */ - if(!val_dsset_isusable(ds)) { - /* If they aren't usable, then we treat it like - * there was no DS. */ - *ke = key_entry_create_null(qstate->region, - qinfo->qname, qinfo->qname_len, qinfo->qclass, - ub_packed_rrset_ttl(ds), - LDNS_EDE_UNSUPPORTED_DS_DIGEST, NULL, - *qstate->env->now); - return (*ke) != NULL; - } - - /* Otherwise, we return the positive response. */ - log_query_info(VERB_DETAIL, "validated DS", qinfo); - *ke = key_entry_create_rrset(qstate->region, - qinfo->qname, qinfo->qname_len, qinfo->qclass, ds, - NULL, LDNS_EDE_NONE, NULL, *qstate->env->now); - return (*ke) != NULL; - } else if(subtype == VAL_CLASS_NODATA || - subtype == VAL_CLASS_NAMEERROR) { - /* NODATA means that the qname exists, but that there was - * no DS. This is a pretty normal case. */ - time_t proof_ttl = 0; - enum sec_status sec; - - /* make sure there are NSECs or NSEC3s with signatures */ - if(!val_has_signed_nsecs(msg->rep, &reason)) { - verbose(VERB_ALGO, "no NSECs: %s", reason); - reason_bogus = LDNS_EDE_NSEC_MISSING; - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - - /* For subtype Name Error. - * attempt ANS 2.8.1.0 compatibility where it sets rcode - * to nxdomain, but really this is an Nodata/Noerror response. - * Find and prove the empty nonterminal in that case */ - - /* Try to prove absence of the DS with NSEC */ - sec = val_nsec_prove_nodata_dsreply( - qstate->env, ve, qinfo, msg->rep, vq->key_entry, - &proof_ttl, &reason, &reason_bogus, qstate); - switch(sec) { - case sec_status_secure: - verbose(VERB_DETAIL, "NSEC RRset for the " - "referral proved no DS."); - *ke = key_entry_create_null(qstate->region, - qinfo->qname, qinfo->qname_len, - qinfo->qclass, proof_ttl, - LDNS_EDE_NONE, NULL, - *qstate->env->now); - return (*ke) != NULL; - case sec_status_insecure: - verbose(VERB_DETAIL, "NSEC RRset for the " - "referral proved not a delegation point"); - *ke = NULL; - return 1; - case sec_status_bogus: - verbose(VERB_DETAIL, "NSEC RRset for the " - "referral did not prove no DS."); - errinf(qstate, reason); - goto return_bogus; - case sec_status_unchecked: - default: - /* NSEC proof did not work, try next */ - break; - } - - sec = nsec3_prove_nods(qstate->env, ve, - msg->rep->rrsets + msg->rep->an_numrrsets, - msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason, - &reason_bogus, qstate); - switch(sec) { - case sec_status_insecure: - /* case insecure also continues to unsigned - * space. If nsec3-iter-count too high or - * optout, then treat below as unsigned */ - case sec_status_secure: - verbose(VERB_DETAIL, "NSEC3s for the " - "referral proved no DS."); - *ke = key_entry_create_null(qstate->region, - qinfo->qname, qinfo->qname_len, - qinfo->qclass, proof_ttl, - LDNS_EDE_NONE, NULL, - *qstate->env->now); - return (*ke) != NULL; - case sec_status_indeterminate: - verbose(VERB_DETAIL, "NSEC3s for the " - "referral proved no delegation"); - *ke = NULL; - return 1; - case sec_status_bogus: - verbose(VERB_DETAIL, "NSEC3s for the " - "referral did not prove no DS."); - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - case sec_status_unchecked: - default: - /* NSEC3 proof did not work */ - break; - } - - /* Apparently, no available NSEC/NSEC3 proved NODATA, so - * this is BOGUS. */ - verbose(VERB_DETAIL, "DS %s ran out of options, so return " - "bogus", val_classification_to_string(subtype)); - reason = "no DS but also no proof of that"; - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } else if(subtype == VAL_CLASS_CNAME || - subtype == VAL_CLASS_CNAMENOANSWER) { - /* if the CNAME matches the exact name we want and is signed - * properly, then also, we are sure that no DS exists there, - * much like a NODATA proof */ - enum sec_status sec; - struct ub_packed_rrset_key* cname; - cname = reply_find_rrset_section_an(msg->rep, qinfo->qname, - qinfo->qname_len, LDNS_RR_TYPE_CNAME, qinfo->qclass); - if(!cname) { - reason = "validator classified CNAME but no " - "CNAME of the queried name for DS"; - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - if(((struct packed_rrset_data*)cname->entry.data)->rrsig_count - == 0) { - if(msg->rep->an_numrrsets != 0 && ntohs(msg->rep-> - rrsets[0]->rk.type)==LDNS_RR_TYPE_DNAME) { - reason = "DS got DNAME answer"; - } else { - reason = "DS got unsigned CNAME answer"; - } - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } - sec = val_verify_rrset_entry(qstate->env, ve, cname, - vq->key_entry, &reason, &reason_bogus, - LDNS_SECTION_ANSWER, qstate); - if(sec == sec_status_secure) { - verbose(VERB_ALGO, "CNAME validated, " - "proof that DS does not exist"); - /* and that it is not a referral point */ - *ke = NULL; - return 1; - } - errinf(qstate, "CNAME in DS response was not secure."); - errinf_ede(qstate, reason, reason_bogus); - goto return_bogus; - } else { - verbose(VERB_QUERY, "Encountered an unhandled type of " - "DS response, thus bogus."); - errinf(qstate, "no DS and"); - reason = "no DS"; - if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) { - char rc[16]; - rc[0]=0; - (void)sldns_wire2str_rcode_buf((int)FLAGS_GET_RCODE( - msg->rep->flags), rc, sizeof(rc)); - errinf(qstate, rc); - } else errinf(qstate, val_classification_to_string(subtype)); - errinf(qstate, "message fails to prove that"); - goto return_bogus; - } -return_bogus: - *ke = key_entry_create_bad(qstate->region, qinfo->qname, - qinfo->qname_len, qinfo->qclass, BOGUS_KEY_TTL, - reason_bogus, reason, *qstate->env->now); - return (*ke) != NULL; -} - -/** - * Process DS response. Called from inform_supers. - * Because it is in inform_supers, the mesh itself is busy doing callbacks - * for a state that is to be deleted soon; don't touch the mesh; instead - * set a state in the super, as the super will be reactivated soon. - * Perform processing to determine what state to set in the super. - * - * @param qstate: query state that is validating and asked for a DS. - * @param vq: validator query state - * @param id: module id. - * @param rcode: rcode result value. - * @param msg: result message (if rcode is OK). - * @param qinfo: from the sub query state, query info. - * @param origin: the origin of msg. - */ -static void -process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, - int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct sock_list* origin) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - struct key_entry_key* dske = NULL; - uint8_t* olds = vq->empty_DS_name; - vq->empty_DS_name = NULL; - if(!ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske)) { - log_err("malloc failure in process_ds_response"); - vq->key_entry = NULL; /* make it error */ - vq->state = VAL_VALIDATE_STATE; - return; - } - if(dske == NULL) { - vq->empty_DS_name = regional_alloc_init(qstate->region, - qinfo->qname, qinfo->qname_len); - if(!vq->empty_DS_name) { - log_err("malloc failure in empty_DS_name"); - vq->key_entry = NULL; /* make it error */ - vq->state = VAL_VALIDATE_STATE; - return; - } - vq->empty_DS_len = qinfo->qname_len; - vq->chain_blacklist = NULL; - /* ds response indicated that we aren't on a delegation point. - * Keep the forState.state on FINDKEY. */ - } else if(key_entry_isgood(dske)) { - vq->ds_rrset = key_entry_get_rrset(dske, qstate->region); - if(!vq->ds_rrset) { - log_err("malloc failure in process DS"); - vq->key_entry = NULL; /* make it error */ - vq->state = VAL_VALIDATE_STATE; - return; - } - vq->chain_blacklist = NULL; /* fresh blacklist for next part*/ - /* Keep the forState.state on FINDKEY. */ - } else if(key_entry_isbad(dske) - && vq->restart_count < ve->max_restart) { - vq->empty_DS_name = olds; - val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); - qstate->errinf = NULL; - vq->restart_count++; - } else { - if(key_entry_isbad(dske)) { - errinf_origin(qstate, origin); - errinf_dname(qstate, "for DS", qinfo->qname); - } - /* NOTE: the reason for the DS to be not good (that is, - * either bad or null) should have been logged by - * dsResponseToKE. */ - vq->key_entry = dske; - /* The FINDKEY phase has ended, so move on. */ - vq->state = VAL_VALIDATE_STATE; - } -} - -/** - * Process DNSKEY response. Called from inform_supers. - * Sets the key entry in the state. - * Because it is in inform_supers, the mesh itself is busy doing callbacks - * for a state that is to be deleted soon; don't touch the mesh; instead - * set a state in the super, as the super will be reactivated soon. - * Perform processing to determine what state to set in the super. - * - * @param qstate: query state that is validating and asked for a DNSKEY. - * @param vq: validator query state - * @param id: module id. - * @param rcode: rcode result value. - * @param msg: result message (if rcode is OK). - * @param qinfo: from the sub query state, query info. - * @param origin: the origin of msg. - */ -static void -process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, - int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, - struct sock_list* origin) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - struct key_entry_key* old = vq->key_entry; - struct ub_packed_rrset_key* dnskey = NULL; - int downprot; - char* reason = NULL; - sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS; - - if(rcode == LDNS_RCODE_NOERROR) - dnskey = reply_find_answer_rrset(qinfo, msg->rep); - - if(dnskey == NULL) { - /* bad response */ - verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to " - "DNSKEY query."); - - if(vq->restart_count < ve->max_restart) { - val_blacklist(&vq->chain_blacklist, qstate->region, - origin, 1); - qstate->errinf = NULL; - vq->restart_count++; - return; - } - reason = "No DNSKEY record"; - reason_bogus = LDNS_EDE_DNSKEY_MISSING; - vq->key_entry = key_entry_create_bad(qstate->region, - qinfo->qname, qinfo->qname_len, qinfo->qclass, - BOGUS_KEY_TTL, reason_bogus, reason, - *qstate->env->now); - if(!vq->key_entry) { - log_err("alloc failure in missing dnskey response"); - /* key_entry is NULL for failure in Validate */ - } - errinf_ede(qstate, reason, reason_bogus); - errinf_origin(qstate, origin); - errinf_dname(qstate, "for key", qinfo->qname); - vq->state = VAL_VALIDATE_STATE; - return; - } - if(!vq->ds_rrset) { - log_err("internal error: no DS rrset for new DNSKEY response"); - vq->key_entry = NULL; - vq->state = VAL_VALIDATE_STATE; - return; - } - downprot = qstate->env->cfg->harden_algo_downgrade; - vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env, - ve, dnskey, vq->ds_rrset, downprot, &reason, &reason_bogus, qstate); - - if(!vq->key_entry) { - log_err("out of memory in verify new DNSKEYs"); - vq->state = VAL_VALIDATE_STATE; - return; - } - /* If the key entry isBad or isNull, then we can move on to the next - * state. */ - if(!key_entry_isgood(vq->key_entry)) { - if(key_entry_isbad(vq->key_entry)) { - if(vq->restart_count < ve->max_restart) { - val_blacklist(&vq->chain_blacklist, - qstate->region, origin, 1); - qstate->errinf = NULL; - vq->restart_count++; - vq->key_entry = old; - return; - } - verbose(VERB_DETAIL, "Did not match a DS to a DNSKEY, " - "thus bogus."); - errinf_ede(qstate, reason, reason_bogus); - errinf_origin(qstate, origin); - errinf_dname(qstate, "for key", qinfo->qname); - } - vq->chain_blacklist = NULL; - vq->state = VAL_VALIDATE_STATE; - return; - } - vq->chain_blacklist = NULL; - qstate->errinf = NULL; - - /* The DNSKEY validated, so cache it as a trusted key rrset. */ - key_cache_insert(ve->kcache, vq->key_entry, - qstate->env->cfg->val_log_level >= 2); - - /* If good, we stay in the FINDKEY state. */ - log_query_info(VERB_DETAIL, "validated DNSKEY", qinfo); -} - -/** - * Process prime response - * Sets the key entry in the state. - * - * @param qstate: query state that is validating and primed a trust anchor. - * @param vq: validator query state - * @param id: module id. - * @param rcode: rcode result value. - * @param msg: result message (if rcode is OK). - * @param origin: the origin of msg. - */ -static void -process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, - int id, int rcode, struct dns_msg* msg, struct sock_list* origin) -{ - struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; - struct ub_packed_rrset_key* dnskey_rrset = NULL; - struct trust_anchor* ta = anchor_find(qstate->env->anchors, - vq->trust_anchor_name, vq->trust_anchor_labs, - vq->trust_anchor_len, vq->qchase.qclass); - if(!ta) { - /* trust anchor revoked, restart with less anchors */ - vq->state = VAL_INIT_STATE; - if(!vq->trust_anchor_name) - vq->state = VAL_VALIDATE_STATE; /* break a loop */ - vq->trust_anchor_name = NULL; - return; - } - /* Fetch and validate the keyEntry that corresponds to the - * current trust anchor. */ - if(rcode == LDNS_RCODE_NOERROR) { - dnskey_rrset = reply_find_rrset_section_an(msg->rep, - ta->name, ta->namelen, LDNS_RR_TYPE_DNSKEY, - ta->dclass); - } - - if(ta->autr) { - if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset, - qstate)) { - /* trust anchor revoked, restart with less anchors */ - vq->state = VAL_INIT_STATE; - vq->trust_anchor_name = NULL; - return; - } - } - vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id); - lock_basic_unlock(&ta->lock); - if(vq->key_entry) { - if(key_entry_isbad(vq->key_entry) - && vq->restart_count < ve->max_restart) { - val_blacklist(&vq->chain_blacklist, qstate->region, - origin, 1); - qstate->errinf = NULL; - vq->restart_count++; - vq->key_entry = NULL; - vq->state = VAL_INIT_STATE; - return; - } - vq->chain_blacklist = NULL; - errinf_origin(qstate, origin); - errinf_dname(qstate, "for trust anchor", ta->name); - /* store the freshly primed entry in the cache */ - key_cache_insert(ve->kcache, vq->key_entry, - qstate->env->cfg->val_log_level >= 2); - } - - /* If the result of the prime is a null key, skip the FINDKEY state.*/ - if(!vq->key_entry || key_entry_isnull(vq->key_entry) || - key_entry_isbad(vq->key_entry)) { - vq->state = VAL_VALIDATE_STATE; - } - /* the qstate will be reactivated after inform_super is done */ -} - -/* - * inform validator super. - * - * @param qstate: query state that finished. - * @param id: module id. - * @param super: the qstate to inform. - */ -void -val_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super) -{ - struct val_qstate* vq = (struct val_qstate*)super->minfo[id]; - log_query_info(VERB_ALGO, "validator: inform_super, sub is", - &qstate->qinfo); - log_query_info(VERB_ALGO, "super is", &super->qinfo); - if(!vq) { - verbose(VERB_ALGO, "super: has no validator state"); - return; - } - if(vq->wait_prime_ta) { - vq->wait_prime_ta = 0; - process_prime_response(super, vq, id, qstate->return_rcode, - qstate->return_msg, qstate->reply_origin); - return; - } - if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) { - process_ds_response(super, vq, id, qstate->return_rcode, - qstate->return_msg, &qstate->qinfo, - qstate->reply_origin); - return; - } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) { - process_dnskey_response(super, vq, id, qstate->return_rcode, - qstate->return_msg, &qstate->qinfo, - qstate->reply_origin); - return; - } - log_err("internal error in validator: no inform_supers possible"); -} - -void -val_clear(struct module_qstate* qstate, int id) -{ - if(!qstate) - return; - /* everything is allocated in the region, so assign NULL */ - qstate->minfo[id] = NULL; -} - -size_t -val_get_mem(struct module_env* env, int id) -{ - struct val_env* ve = (struct val_env*)env->modinfo[id]; - if(!ve) - return 0; - return sizeof(*ve) + key_cache_get_mem(ve->kcache) + - val_neg_get_mem(ve->neg_cache) + - sizeof(size_t)*2*ve->nsec3_keyiter_count; -} - -/** - * The validator function block - */ -static struct module_func_block val_block = { - "validator", - &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear, - &val_get_mem -}; - -struct module_func_block* -val_get_funcblock(void) -{ - return &val_block; -} - -const char* -val_state_to_string(enum val_state state) -{ - switch(state) { - case VAL_INIT_STATE: return "VAL_INIT_STATE"; - case VAL_FINDKEY_STATE: return "VAL_FINDKEY_STATE"; - case VAL_VALIDATE_STATE: return "VAL_VALIDATE_STATE"; - case VAL_FINISHED_STATE: return "VAL_FINISHED_STATE"; - } - return "UNKNOWN VALIDATOR STATE"; -} - diff --git a/crates/libunbound-sys/unbound/validator/validator.h b/crates/libunbound-sys/unbound/validator/validator.h deleted file mode 100644 index 694e4c89..00000000 --- a/crates/libunbound-sys/unbound/validator/validator.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * validator/validator.h - secure validator DNS query response module - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * This file contains a module that performs validation of DNS queries. - * According to RFC 4034. - */ - -#ifndef VALIDATOR_VALIDATOR_H -#define VALIDATOR_VALIDATOR_H -#include "util/module.h" -#include "util/data/msgreply.h" -#include "validator/val_utils.h" -struct val_anchors; -struct key_cache; -struct key_entry_key; -struct val_neg_cache; -struct config_strlist; - -/** - * This is the TTL to use when a trust anchor fails to prime. A trust anchor - * will be primed no more often than this interval. Used when harden- - * dnssec-stripped is off and the trust anchor fails. - */ -#define NULL_KEY_TTL 60 /* seconds */ - -/** - * TTL for bogus key entries. When a DS or DNSKEY fails in the chain of - * trust the entire zone for that name is blacked out for this TTL. - */ -#define BOGUS_KEY_TTL 60 /* seconds */ - -/** Root key sentinel is ta preamble */ -#define SENTINEL_IS "root-key-sentinel-is-ta-" -/** Root key sentinel is not ta preamble */ -#define SENTINEL_NOT "root-key-sentinel-not-ta-" -/** Root key sentinel keytag length */ -#define SENTINEL_KEYTAG_LEN 5 - -/** - * Global state for the validator. - */ -struct val_env { - /** key cache; these are validated keys. trusted keys only - * end up here after being primed. */ - struct key_cache* kcache; - - /** aggressive negative cache. index into NSECs in rrset cache. */ - struct val_neg_cache* neg_cache; - - /** for debug testing a fixed validation date can be entered. - * if 0, current time is used for rrsig validation */ - int32_t date_override; - - /** clock skew min for signatures */ - int32_t skew_min; - - /** clock skew max for signatures */ - int32_t skew_max; - - /** max number of query restarts, number of IPs to probe */ - int max_restart; - - /** TTL for bogus data; used instead of untrusted TTL from data. - * Bogus data will not be verified more often than this interval. - * seconds. */ - uint32_t bogus_ttl; - - /** - * Number of entries in the NSEC3 maximum iteration count table. - * Keep this table short, and sorted by size - */ - int nsec3_keyiter_count; - - /** - * NSEC3 maximum iteration count per signing key size. - * This array contains key size values (in increasing order) - */ - size_t* nsec3_keysize; - - /** - * NSEC3 maximum iteration count per signing key size. - * This array contains the maximum iteration count for the keysize - * in the keysize array. - */ - size_t* nsec3_maxiter; - - /** lock on bogus counter */ - lock_basic_type bogus_lock; - /** number of times rrsets marked bogus */ - size_t num_rrset_bogus; -}; - -/** - * State of the validator for a query. - */ -enum val_state { - /** initial state for validation */ - VAL_INIT_STATE = 0, - /** find the proper keys for validation, follow trust chain */ - VAL_FINDKEY_STATE, - /** validate the answer, using found key entry */ - VAL_VALIDATE_STATE, - /** finish up */ - VAL_FINISHED_STATE, -}; - -/** - * Per query state for the validator module. - */ -struct val_qstate { - /** - * State of the validator module. - */ - enum val_state state; - - /** - * The original message we have been given to validate. - */ - struct dns_msg* orig_msg; - - /** - * The query restart count - */ - int restart_count; - /** The blacklist saved for chainoftrust elements */ - struct sock_list* chain_blacklist; - - /** - * The query name we have chased to; qname after following CNAMEs - */ - struct query_info qchase; - - /** - * The chased reply, extract from original message. Can be: - * o CNAME - * o DNAME + CNAME - * o answer - * plus authority, additional (nsecs) that have same signature. - */ - struct reply_info* chase_reply; - - /** - * The cname skip value; the number of rrsets that have been skipped - * due to chasing cnames. This is the offset into the - * orig_msg->rep->rrsets array, into the answer section. - * starts at 0 - for the full original message. - * if it is >0 - qchase followed the cname, chase_reply setup to be - * that message and relevant authority rrsets. - * - * The skip is also used for referral messages, where it will - * range from 0, over the answer, authority and additional sections. - */ - size_t rrset_skip; - - /** trust anchor name */ - uint8_t* trust_anchor_name; - /** trust anchor labels */ - int trust_anchor_labs; - /** trust anchor length */ - size_t trust_anchor_len; - - /** the DS rrset */ - struct ub_packed_rrset_key* ds_rrset; - - /** domain name for empty nonterminal detection */ - uint8_t* empty_DS_name; - /** length of empty_DS_name */ - size_t empty_DS_len; - - /** the current key entry */ - struct key_entry_key* key_entry; - - /** subtype */ - enum val_classification subtype; - - /** signer name */ - uint8_t* signer_name; - /** length of signer_name */ - size_t signer_len; - - /** true if this state is waiting to prime a trust anchor */ - int wait_prime_ta; -}; - -/** - * Get the validator function block. - * @return: function block with function pointers to validator methods. - */ -struct module_func_block* val_get_funcblock(void); - -/** - * Get validator state as a string - * @param state: to convert - * @return constant string that is printable. - */ -const char* val_state_to_string(enum val_state state); - -/** validator init */ -int val_init(struct module_env* env, int id); - -/** validator deinit */ -void val_deinit(struct module_env* env, int id); - -/** validator operate on a query */ -void val_operate(struct module_qstate* qstate, enum module_ev event, int id, - struct outbound_entry* outbound); - -/** - * inform validator super. - * - * @param qstate: query state that finished. - * @param id: module id. - * @param super: the qstate to inform. - */ -void val_inform_super(struct module_qstate* qstate, int id, - struct module_qstate* super); - -/** validator cleanup query state */ -void val_clear(struct module_qstate* qstate, int id); - -/** - * Debug helper routine that assists worker in determining memory in - * use. - * @param env: module environment - * @param id: module id. - * @return memory in use in bytes. - */ -size_t val_get_mem(struct module_env* env, int id); - -#endif /* VALIDATOR_VALIDATOR_H */ diff --git a/crates/libunbound/Cargo.toml b/crates/libunbound/Cargo.toml deleted file mode 100644 index d8e59332..00000000 --- a/crates/libunbound/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "libunbound" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -libunbound-sys = {path="../libunbound-sys"} -thiserror = "1.0" -tokio = {workspace=true, features=["sync"]} -trust-dns-proto = "0.23" -libc = "0.2" - -[dev-dependencies] -tokio = {workspace=true, features=["macros"]} - -[target.'cfg(not(any(windows, target_os="macos")))'.dependencies] -openssl = { workspace=true } - -[target.'cfg(any(windows, target_os="macos"))'.dependencies] -openssl = { workspace=true, features=["vendored"] } diff --git a/crates/libunbound/examples/resolve.rs b/crates/libunbound/examples/resolve.rs deleted file mode 100644 index 66deede0..00000000 --- a/crates/libunbound/examples/resolve.rs +++ /dev/null @@ -1,14 +0,0 @@ -use libunbound::*; -use trust_dns_proto::rr::record_type::RecordType; -use trust_dns_proto::rr::DNSClass; - -fn main() { - let ctx = Context::new().expect("Context to be created"); - ctx.load_resolv_conf(None).unwrap(); - ctx.set_debug_level(DebugLevel::Detailed).unwrap(); - let result = ctx - .resolve("_25._tcp.do.havedane.net", RecordType::TLSA, DNSClass::IN) - .unwrap(); - println!("{result:#?}"); - ctx.print_local_zones().unwrap(); -} diff --git a/crates/libunbound/examples/resolve_async.rs b/crates/libunbound/examples/resolve_async.rs deleted file mode 100644 index cc11721e..00000000 --- a/crates/libunbound/examples/resolve_async.rs +++ /dev/null @@ -1,23 +0,0 @@ -use libunbound::*; -use trust_dns_proto::rr::record_type::RecordType; -use trust_dns_proto::rr::DNSClass; - -#[tokio::main] -async fn main() { - let ctx = Context::new().expect("Context to be created"); - let ctx = ctx.into_async().unwrap(); - - let result = ctx - .resolve("_25._tcp.do.havedane.net", RecordType::TLSA, DNSClass::IN) - .await - .unwrap(); - println!("{result:#?}"); - - let result = ctx - .resolve("do.havedane.net", RecordType::MX, DNSClass::IN) - .await - .unwrap(); - println!("{result:#?}"); - - println!("I am done"); -} diff --git a/crates/libunbound/examples/secure.rs b/crates/libunbound/examples/secure.rs deleted file mode 100644 index 9b1e52ec..00000000 --- a/crates/libunbound/examples/secure.rs +++ /dev/null @@ -1,18 +0,0 @@ -use libunbound::*; -use trust_dns_proto::rr::record_type::RecordType; -use trust_dns_proto::rr::DNSClass; - -fn main() { - let ctx = Context::new().expect("Context to be created"); - ctx.bootstrap_trust_anchor_file("/tmp/root.dnssec.anchor") - .unwrap(); - /* alternatively, if you don't want to touch local files: - for a in ROOT_TRUST_ANCHORS { - ctx.add_trust_anchor(a).unwrap(); - } - */ - let result = ctx - .resolve("_25._tcp.do.havedane.net", RecordType::TLSA, DNSClass::IN) - .unwrap(); - println!("{result:#?}"); -} diff --git a/crates/libunbound/src/lib.rs b/crates/libunbound/src/lib.rs deleted file mode 100644 index 4eaf1dba..00000000 --- a/crates/libunbound/src/lib.rs +++ /dev/null @@ -1,876 +0,0 @@ -use libunbound_sys::*; -use std::ffi::{c_int, CStr, CString}; -use std::io::Write; -use std::net::IpAddr; -use std::sync::{Arc, Condvar, Mutex}; -use tokio::sync::oneshot::error::RecvError; -use tokio::sync::oneshot::{channel, Sender}; -use trust_dns_proto::error::ProtoResult; -use trust_dns_proto::op::response_code::ResponseCode; -use trust_dns_proto::rr::record_type::RecordType; -use trust_dns_proto::rr::{DNSClass, RData}; -use trust_dns_proto::serialize::binary::{BinDecoder, Restrict}; - -/// These are the root trust anchors at the time of writing. -/// See -/// for more information on anchors. -/// The data for these comes from: -/// -pub const ROOT_TRUST_ANCHORS: &[&str] = &[ - ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5", - ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D", -]; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Unbound error: {}", unbound_error_string(*.0))] - Sys(ub_ctx_err), - #[error("DNS name has an embedded NUL character")] - InvalidName, - #[error("IO Error: {0}")] - Io(#[from] std::io::Error), - #[error("Error waiting for query result: {0}")] - Recv(#[from] RecvError), - #[error("Failed to create Context")] - ContextCreation, -} - -pub fn unbound_error_string(err: ub_ctx_err) -> String { - let res = unsafe { ub_strerror(err) }; - if res.is_null() { - format!("[{err}]: Unknown error") - } else { - let s = unsafe { CStr::from_ptr(res) }; - let s = s.to_string_lossy(); - format!("[{err}]: {s}") - } -} - -pub struct Context { - ctx: *mut ub_ctx, -} - -// Context is internally thread safe -unsafe impl Sync for Context {} -unsafe impl Send for Context {} - -impl Drop for Context { - fn drop(&mut self) { - unsafe { - ub_ctx_delete(self.ctx); - } - } -} - -/// The validation context is created to hold the resolver status, -/// validation keys and a small cache (containing messages, rrsets, -/// roundtrip times, trusted keys, lameness information). -impl Context { - /// Create a resolving and validation context. - /// The information from /etc/resolv.conf and /etc/hosts is not utilised by - /// default. - /// Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - pub fn new() -> Result { - openssl::init(); - let ctx = unsafe { ub_ctx_create() }; - if ctx.is_null() { - Err(Error::ContextCreation) - } else { - Ok(Self { ctx }) - } - } - - /// Perform resolution and validation of the target name. - /// The context is finalized, and can no longer accept config changes. - /// @param name: domain name in text format (a zero terminated text string). - /// @param rrtype: type of RR - /// @param rrclass: class of RR - pub fn resolve( - &self, - name: &str, - rrtype: RecordType, - rrclass: DNSClass, - ) -> Result { - let rrclass: u16 = rrclass.into(); - let rrtype: u16 = rrtype.into(); - let name = CString::new(name).map_err(|_| Error::InvalidName)?; - let mut result = std::ptr::null_mut(); - let err = unsafe { - ub_resolve( - self.ctx, - name.as_ptr(), - rrtype as c_int, - rrclass as c_int, - &mut result, - ) - }; - if err == ub_ctx_err_UB_NOERROR { - assert!(!result.is_null()); - Ok(Answer { result }) - } else { - Err(Error::Sys(err)) - } - } - - /// Set an option for the context - /// @param opt: option name from the unbound.conf config file format. - /// (not all settings applicable). The name includes the trailing ':' - /// for example - /// - /// ```rust - /// let ctx = libunbound::Context::new().unwrap(); - /// ctx.set_option("logfile:", "mylog.txt"); - /// ``` - /// - /// This is a power-users interface that lets you specify all sorts - /// of options. - /// - /// For some specific options, such as adding trust anchors, special - /// routines exist. - /// - /// @param val: value of the option. - pub fn set_option(&self, opt: &str, value: &str) -> Result<(), Error> { - let opt = CString::new(opt).map_err(|_| Error::InvalidName)?; - let value = CString::new(value).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_set_option(self.ctx, opt.as_ptr(), value.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Get an option from the context. - /// @param opt: option name from the unbound.conf config file format. - /// (not all settings applicable). The name excludes the trailing ':' - /// for example: - /// - /// ```rust - /// let ctx = libunbound::Context::new().unwrap(); - /// ctx.get_option("logfile"); - /// ``` - /// - /// This is a power-users interface that lets you specify all sorts - /// of options. - /// In cases with multiple entries (auto-trust-anchor-file), - /// a newline delimited list is returned in the string. - pub fn get_option(&self, opt: &str) -> Result { - let opt = CString::new(opt).map_err(|_| Error::InvalidName)?; - let mut result = std::ptr::null_mut(); - let err = unsafe { ub_ctx_get_option(self.ctx, opt.as_ptr(), &mut result) }; - - if err == ub_ctx_err_UB_NOERROR { - assert!(!result.is_null()); - let s = unsafe { CStr::from_ptr(result) }; - let value = s.to_string_lossy().to_string(); - unsafe { libc::free(result as *mut libc::c_void) }; - Ok(value) - } else { - Err(Error::Sys(err)) - } - } - - /// setup configuration for the given context. - /// @param config_file_name: unbound config file (not all settings applicable). - /// This is a power-users interface that lets you specify all sorts of options. - /// For some specific options, such as adding trust anchors, special routines exist. - pub fn load_unbound_config_file(&self, config_file_name: &str) -> Result<(), Error> { - let fname = CString::new(config_file_name).map_err(|_| Error::InvalidName)?; - - let err = unsafe { ub_ctx_config(self.ctx, fname.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Set machine to forward DNS queries to, the caching resolver to use. - /// IP4 or IP6 address. Forwards all DNS requests to that machine, which - /// is expected to run a recursive resolver. If the proxy is not DNSSEC-capable, - /// validation may fail. Can be called several times, in that case the addresses - /// are used as backup servers. - /// To read the list of nameservers from /etc/resolv.conf (from DHCP or so), - /// use the call ub_ctx_resolvconf. - /// At this time it is only possible to set configuration before the\n\tfirst resolve is done. - /// If the addr is None, forwarding is disabled. - pub fn set_forward(&self, addr: Option) -> Result<(), Error> { - let err = match addr { - Some(addr) => { - let addr = CString::new(addr.to_string()).map_err(|_| Error::InvalidName)?; - unsafe { ub_ctx_set_fwd(self.ctx, addr.as_ptr()) } - } - None => unsafe { ub_ctx_set_fwd(self.ctx, std::ptr::null()) }, - }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Use DNS over TLS to send queries to machines set with set_forward(). - /// At this time it is only possible to set configuration before the first resolve is done. - /// @param tls: enable or disable DNS over TLS - pub fn set_tls(&self, tls: bool) -> Result<(), Error> { - let err = unsafe { ub_ctx_set_tls(self.ctx, if tls { 1 } else { 0 }) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Add a stub zone, with given address to send to. This is for custom - /// root hints or pointing to a local authoritative dns server. - /// For dns resolvers and the 'DHCP DNS' ip address, use set_forward. - /// This is similar to a stub-zone entry in unbound.conf. - /// - /// It is only possible to set configuration before the first resolve is done. - /// @param zone: name of the zone, string. - /// @param addr: address, IP4 or IP6 in string format. - /// The addr is added to the list of stub-addresses if the entry exists. - /// If the addr is None the stub entry is removed. - /// @param isprime: set to true to set stub-prime to yes for the stub. - /// For local authoritative servers, people usually set it to false, - /// For root hints it should be set to true. - pub fn set_stub(&self, zone: &str, addr: Option, is_prime: bool) -> Result<(), Error> { - let zone = CString::new(zone).map_err(|_| Error::InvalidName)?; - let is_prime = if is_prime { 1 } else { 0 }; - - let err = match addr { - Some(addr) => { - let addr = CString::new(addr.to_string()).map_err(|_| Error::InvalidName)?; - unsafe { ub_ctx_set_stub(self.ctx, zone.as_ptr(), addr.as_ptr(), is_prime) } - } - None => unsafe { ub_ctx_set_stub(self.ctx, zone.as_ptr(), std::ptr::null(), is_prime) }, - }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Read list of nameservers to use from the filename given. - /// Usually `"/etc/resolv.conf"`. Uses those nameservers as caching proxies. - /// If they do not support DNSSEC, validation may fail. - /// Only nameservers are picked up, the searchdomain, ndots and other - /// settings from resolv.conf(5) are ignored. - /// At this time it is only possible to set configuration before the first resolve is done. - /// n @param fname: file name string. If None `"/etc/resolv.conf"` is used. - pub fn load_resolv_conf(&self, file_name: Option<&str>) -> Result<(), Error> { - let err = match file_name { - Some(name) => { - let name = CString::new(name).map_err(|_| Error::InvalidName)?; - unsafe { ub_ctx_resolvconf(self.ctx, name.as_ptr()) } - } - None => unsafe { ub_ctx_resolvconf(self.ctx, std::ptr::null()) }, - }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Read list of hosts from the filename given. - /// Usually `"/etc/hosts"` - /// These addresses are not flagged as DNSSEC secure when queried for. - /// At this time it is only possible to set configuration before the first resolve is done. - /// @param fname: file name string. If None `"/etc/hosts"` is used. - pub fn load_hosts(&self, file_name: Option<&str>) -> Result<(), Error> { - let err = match file_name { - Some(name) => { - let name = CString::new(name).map_err(|_| Error::InvalidName)?; - unsafe { ub_ctx_hosts(self.ctx, name.as_ptr()) } - } - None => unsafe { ub_ctx_hosts(self.ctx, std::ptr::null()) }, - }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Add a trust anchor to the given context. - /// The trust anchor is a string, on one line, that holds a valid DNSKEY or - /// DS RR. - /// tAt this time it is only possible to add trusted keys before the - /// first resolve is done. - /// - /// @param ta: string, with zone-format RR on one line. - /// - /// `[domainname] [TTL optional] [type] [class optional] [rdata contents]` - pub fn add_trust_anchor(&self, ta: &str) -> Result<(), Error> { - let ta = CString::new(ta).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_add_ta(self.ctx, ta.as_ptr()) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Add the built-in trust anchors to the context. - /// These anchors were correct at the time that this module was authored, - /// however, for robust DNSSEC, you should consider bootstrapping an - /// anchor file and loading it via load_trust_anchor_file() if you want - /// stronger assertions that these anchors are correct and to keep them - /// updated. - pub fn add_builtin_trust_anchors(&self) -> Result<(), Error> { - for a in ROOT_TRUST_ANCHORS { - self.add_trust_anchor(a)?; - } - Ok(()) - } - - /// Add trust anchors to the given context. - /// Pass name of a file with DS and DNSKEY records (like from dig or drill). - /// At this time it is only possible to add trusted keys before the - /// first resolve is done. - /// @param fname: filename of file with keyfile with trust anchors. - pub fn load_trust_anchor_file(&self, file_name: &str) -> Result<(), Error> { - let fname = CString::new(file_name).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_add_ta_file(self.ctx, fname.as_ptr()) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Use file_name to maintain root trust anchors for DNSSEC. - /// If the file doesn't already exist, it will be populated with - /// the built-in ROOT_TRUST_ANCHORS defined by this module. - pub fn bootstrap_trust_anchor_file(&self, file_name: &str) -> Result<(), Error> { - if let Ok(mut f) = std::fs::OpenOptions::new() - .write(true) - .create_new(true) - .open(file_name) - { - f.write_all(ROOT_TRUST_ANCHORS.join("\n").as_bytes())?; - } - - self.load_trust_anchor_file(file_name) - } - - /// Add trust anchor to the given context that is tracked with RFC5011 - /// automated trust anchor maintenance. - /// The file is written to when the trust anchor is changed. - /// Pass the name of a file that was output from eg. unbound-anchor, - /// or you can start it by providing a trusted DNSKEY or DS record on one - /// line in the file. - /// At this time it is only possible to add trusted keys before the - /// first resolve is done. - /// @param fname: filename of file with trust anchor. - pub fn load_trust_anchor_file_with_auto_update(&self, file_name: &str) -> Result<(), Error> { - let fname = CString::new(file_name).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_add_ta_autr(self.ctx, fname.as_ptr()) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Set debug output (and error output) to the specified stream. - /// Pass NULL to disable. Default is stderr. - /// @param out: FILE* out file stream to log to. - pub fn set_debug_output(&self, stream: *mut libc::FILE) -> Result<(), Error> { - let err = unsafe { ub_ctx_debugout(self.ctx, stream as *mut _) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Set debug verbosity for the context - /// Output is directed to stderr or whatever was configured via set_debug_output(). - /// @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed, and 3 is lots. - pub fn set_debug_level(&self, level: DebugLevel) -> Result<(), Error> { - let err = unsafe { ub_ctx_debuglevel(self.ctx, level as _) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Debug routine. Print the local zone information to debug output. - /// Is finalized by the routine. - pub fn print_local_zones(&self) -> Result<(), Error> { - let err = unsafe { ub_ctx_print_local_zones(self.ctx) }; - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Add a new zone with the zonetype to the local authority info of the - /// library. - /// Is finalized by the routine. - /// @param zone_name: name of the zone in text, `"example.com"` - /// tIf it already exists, the type is updated. - /// @param zone_type: type of the zone (like for unbound.conf) in text. - pub fn zone_add(&self, zone_name: &str, zone_type: &str) -> Result<(), Error> { - let zone_name = CString::new(zone_name).map_err(|_| Error::InvalidName)?; - let zone_type = CString::new(zone_type).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_zone_add(self.ctx, zone_name.as_ptr(), zone_type.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Remove zone from local authority info of the library. - /// Is finalized by the routine. - /// @param zone_name: name of the zone in text, `"example.com\"` - /// If it does not exist, nothing happens. - pub fn zone_remove(&self, zone_name: &str) -> Result<(), Error> { - let zone_name = CString::new(zone_name).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_zone_remove(self.ctx, zone_name.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Add localdata to the library local authority info. - /// Similar to local-data config statement. - /// @param data: the resource record in text format, for example - /// `"www.example.com IN A 127.0.0.1"` - pub fn add_local_data(&self, data: &str) -> Result<(), Error> { - let data = CString::new(data).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_data_add(self.ctx, data.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Remove localdata from the library local authority info. - /// @param data: the name to delete all data from, like `"www.example.com" - pub fn remove_local_data(&self, data: &str) -> Result<(), Error> { - let data = CString::new(data).map_err(|_| Error::InvalidName)?; - let err = unsafe { ub_ctx_data_remove(self.ctx, data.as_ptr()) }; - - if err == ub_ctx_err_UB_NOERROR { - Ok(()) - } else { - Err(Error::Sys(err)) - } - } - - /// Convert the context into an async resolving context. - /// A helper thread will be spawned to manage the context, - /// and will automatically shut down when the returned - /// AsyncContext is dropped. - pub fn into_async(self) -> Result { - // Use a thread rather than forking a worker for unbound - unsafe { - ub_ctx_async(self.ctx, 1); - } - - // Note that while libunbound does support exporting its - // fd for monitoring by eg: mio or AsyncFd in tokio, - // I've found that it is perpetually ready for read - // when there are no pending queries, so we use an - // old-school condvar and count of pending queries - // to avoid busy waiting in the helper task. - // As a result, we're using thread for that purpose. - let inner = Arc::new(Inner { - context: self, - condvar: Condvar::new(), - predicate: Mutex::new(0), - }); - - let processor = Arc::clone(&inner); - - std::thread::Builder::new() - .name("libunbound worker".to_string()) - .spawn(move || { - loop { - if Arc::strong_count(&processor) == 1 { - // We are the only remaining ref; no further - // queries are possible - break; - } - - // Wait for there to be any queries - { - let mut pred_lock = processor.predicate.lock().unwrap(); - while *pred_lock == 0 { - pred_lock = processor.condvar.wait(pred_lock).unwrap(); - } - } - - // Wait for and process result(s). - // This will satisfy multiple read answers - let err = unsafe { ub_wait(processor.context.ctx) }; - if err != ub_ctx_err_UB_NOERROR { - // Most likely error is a broken pipe in the - // case where the context is being destroyed - break; - } - } - })?; - - Ok(AsyncContext { inner }) - } -} - -struct Inner { - context: Context, - condvar: Condvar, - predicate: Mutex, -} - -impl Inner { - pub fn increment(&self) { - let mut pred_lock = self.predicate.lock().unwrap(); - *pred_lock += 1; - self.condvar.notify_one(); - } - - pub fn decrement(&self) { - let mut pred_lock = self.predicate.lock().unwrap(); - *pred_lock -= 1; - } -} - -pub struct AsyncContext { - inner: Arc, -} - -impl Drop for AsyncContext { - fn drop(&mut self) { - // Wake up the helper so that it can wind itself down - // when we are dropped - self.inner.increment(); - } -} - -impl AsyncContext { - /// Asynchronously perform resolution and validation of the target name. - /// @param name: domain name in text format (a zero terminated text string). - /// @param rrtype: type of RR - /// @param rrclass: class of RR - pub async fn resolve( - &self, - name: &str, - rrtype: RecordType, - rrclass: DNSClass, - ) -> Result { - let rrclass: u16 = rrclass.into(); - let rrtype: u16 = rrtype.into(); - let name = CString::new(name).map_err(|_| Error::InvalidName)?; - - let (tx, rx) = channel::>(); - - // The outstanding query takes a strong ref to the context - // to ensure that the helper thread isn't stopped before - // completion - let state = Box::new(AsyncQueryState { - tx, - inner: Arc::clone(&self.inner), - }); - - let mut id = 0; - { - let state_ptr = Box::into_raw(state); - let err = unsafe { - ub_resolve_async( - self.inner.context.ctx, - name.as_ptr(), - rrtype as c_int, - rrclass as c_int, - state_ptr as *mut _, - Some(Self::process_result), - &mut id, - ) - }; - if err != ub_ctx_err_UB_NOERROR { - // Reclaim ownership of the query state pointer so - // that we don't leak it - let state: Box = unsafe { Box::from_raw(state_ptr) }; - drop(state); - - return Err(Error::Sys(err)); - } - } - - // Hold the id so that we can cancel on drop - let mut id = AsyncId { - id: Some(id), - context: self, - }; - - self.inner.increment(); - - let res = rx.await?; - - // Query completed; no need to cancel after this point - id.disarm(); - - res - } - - /// This function is called by unbound when a query completes - unsafe extern "C" fn process_result( - my_arg: *mut ::std::os::raw::c_void, - err: ::std::os::raw::c_int, - result: *mut ub_result, - ) { - let state = Box::from_raw(my_arg as *mut AsyncQueryState); - - let result = if err == ub_ctx_err_UB_NOERROR { - assert!(!result.is_null()); - Ok(Answer { result }) - } else { - assert!(result.is_null()); - Err(Error::Sys(err)) - }; - state.tx.send(result).ok(); - - state.inner.decrement(); - } -} - -struct AsyncQueryState { - tx: Sender>, - inner: Arc, -} - -/// Helper for cancelling a lookup -struct AsyncId<'a> { - id: Option, - context: &'a AsyncContext, -} - -impl<'a> AsyncId<'a> { - /// Set the state to prevent cancelling the query - fn disarm(&mut self) { - self.id.take(); - } -} - -impl<'a> Drop for AsyncId<'a> { - fn drop(&mut self) { - // Cancel the query on drop - if let Some(id) = self.id.take() { - unsafe { - ub_cancel(self.context.inner.context.ctx, id); - } - } - } -} - -/// The validation and resolution results. -pub struct Answer { - result: *mut ub_result, -} - -// Answer is internally thread safe -unsafe impl Sync for Answer {} -unsafe impl Send for Answer {} - -impl Drop for Answer { - fn drop(&mut self) { - unsafe { - ub_resolve_free(self.result); - } - } -} - -impl Answer { - fn answer(&self) -> &ub_result { - unsafe { &*self.result } - } - - /// The original question, name text string. - pub fn qname(&self) -> &str { - let cstr = unsafe { CStr::from_ptr(self.answer().qname) }; - cstr.to_str() - .expect("original resolve param was str, so this should be too") - } - - /// the type asked for - pub fn qtype(&self) -> RecordType { - (self.answer().qtype as u16).into() - } - - /// the class asked for - pub fn qclass(&self) -> DNSClass { - DNSClass::from_u16(self.answer().qclass as u16) - .expect("original rrclass was DNSClass, so this should be too") - } - - /// canonical name for the result (the final cname). - pub fn canon_name(&self) -> Option<&str> { - let ptr = self.answer().canonname; - if ptr.is_null() { - None - } else { - let cstr = unsafe { CStr::from_ptr(ptr) }; - Some( - cstr.to_str() - .expect("DNS names should be ASCII, so this should be too"), - ) - } - } - - /// DNS RCODE for the result. May contain additional error code if - /// there was no data due to an error, ResponseCode::NoError if OK. - pub fn rcode(&self) -> ResponseCode { - (self.answer().rcode as u16).into() - } - - /// The DNS answer packet. Network formatted. Can contain DNSSEC types. - pub fn answer_packet(&self) -> &[u8] { - let answer = self.answer(); - unsafe { - std::slice::from_raw_parts( - answer.answer_packet as *const u8, - answer.answer_len as usize, - ) - } - } - - /// If there is any data, this is true. - /// If false, there was no data (nxdomain may be true, rcode can be set). - pub fn have_data(&self) -> bool { - self.answer().havedata != 0 - } - - /// If there was no data, and the domain did not exist, this is true. - /// If it is false, and there was no data, then the domain name - /// is purported to exist, but the requested data type is not available. - pub fn nxdomain(&self) -> bool { - self.answer().nxdomain != 0 - } - - /// True, if the result is validated securely. - /// False, if validation failed or domain queried has no security info. - /// It is possible to get a result with no data (havedata is false), - /// and secure is true. This means that the non-existence of the data - /// was cryptographically proven (with signatures). - pub fn secure(&self) -> bool { - self.answer().secure != 0 - } - - /// If the result was not secure (secure==0), and this result is due - /// to a security failure, bogus is true. - /// This means the data has been actively tampered with, signatures - /// failed, expected signatures were not present, timestamps on - /// signatures were out of date and so on. - /// If !secure and !bogus, this can happen if the data is not secure - /// because security is disabled for that domain name. - /// This means the data is from a domain where data is not signed. - pub fn bogus(&self) -> bool { - self.answer().bogus != 0 - } - - /// If the result is bogus this contains a string - /// that describes the failure. - /// There may be other errors as well - /// as the one described, the description may not be perfectly accurate. - /// Is None if the result is not bogus. - pub fn why_bogus(&self) -> Option<&str> { - let ptr = self.answer().why_bogus; - if ptr.is_null() { - None - } else { - let cstr = unsafe { CStr::from_ptr(ptr) }; - Some(cstr.to_str().expect("expected UTF8")) - } - } - - /// If the query or one of its subqueries was ratelimited. Useful if - /// ratelimiting is enabled and answer to the client is SERVFAIL as a result. - pub fn was_rate_limited(&self) -> bool { - self.answer().was_ratelimited != 0 - } - - /// TTL for the result, in seconds. If the security is bogus, then - /// you also cannot trust this value. - pub fn ttl(&self) -> u32 { - self.answer().ttl as u32 - } - - /// Iterates over the rdata items - pub fn rdata(&self) -> AnswerDataIter { - AnswerDataIter { - pos: 0, - answer: self, - } - } -} - -impl std::fmt::Debug for Answer { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("Answer") - .field("qname", &self.qname()) - .field("qtype", &self.qtype()) - .field("qclass", &self.qclass()) - .field("canon_name", &self.canon_name()) - .field("rcode", &self.rcode()) - .field("have_data", &self.have_data()) - .field("nxdomain", &self.nxdomain()) - .field("secure", &self.secure()) - .field("bogus", &self.bogus()) - .field("why_bogus", &self.why_bogus()) - .field("was_rate_limited", &self.was_rate_limited()) - .field("ttl", &self.ttl()) - .field("tdata", &self.rdata().collect::>()) - .finish() - } -} - -pub struct AnswerDataIter<'a> { - pos: isize, - answer: &'a Answer, -} - -impl<'a> std::iter::Iterator for AnswerDataIter<'a> { - type Item = ProtoResult; - - fn next(&mut self) -> Option> { - let raw_data = unsafe { - let answer = self.answer.answer(); - let offset = *answer.data.offset(self.pos); - if offset.is_null() { - return None; - } - let len = (*answer.len.offset(self.pos)) as usize; - std::slice::from_raw_parts(offset as *const u8, len) - }; - self.pos += 1; - - Some(RData::read( - &mut BinDecoder::new(raw_data), - self.answer.qtype(), - Restrict::new(raw_data.len() as u16), - )) - } -} - -#[derive(Debug, Clone, Copy)] -#[repr(i32)] -pub enum DebugLevel { - Off = 0, - Minimal = 1, - Detailed = 2, - Lots = 3, -} diff --git a/crates/mod-dns-resolver/Cargo.toml b/crates/mod-dns-resolver/Cargo.toml index 65533540..146c00dc 100644 --- a/crates/mod-dns-resolver/Cargo.toml +++ b/crates/mod-dns-resolver/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" anyhow = "1.0" config = {path="../config"} dns-resolver = {path="../dns-resolver"} -libunbound = {path="../libunbound"} +libunbound = {workspace=true} mlua = {workspace=true, features=["vendored", "lua54", "async", "send", "serialize"]} serde = {version="1.0", features=["derive"]} trust-dns-resolver = {workspace=true, features=["serde-config"]}