diff options
Diffstat (limited to '')
-rw-r--r-- | external/unbound/daemon/remote.c | 581 |
1 files changed, 491 insertions, 90 deletions
diff --git a/external/unbound/daemon/remote.c b/external/unbound/daemon/remote.c index d533e0867..c15967c20 100644 --- a/external/unbound/daemon/remote.c +++ b/external/unbound/daemon/remote.c @@ -46,9 +46,12 @@ #ifdef HAVE_OPENSSL_ERR_H #include <openssl/err.h> #endif -#ifndef HEADER_DH_H +#ifdef HAVE_OPENSSL_DH_H #include <openssl/dh.h> #endif +#ifdef HAVE_OPENSSL_BN_H +#include <openssl/bn.h> +#endif #include <ctype.h> #include "daemon/remote.h" @@ -140,49 +143,68 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) /* * The following function was generated using the openssl utility, using - * the command : "openssl dhparam -dsaparam -C 1024" + * the command : "openssl dhparam -C 2048" * (some openssl versions reject DH that is 'too small', eg. 512). */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) #ifndef S_SPLINT_S -DH *get_dh1024() -{ - static unsigned char dh1024_p[]={ - 0xB3,0x67,0x2E,0x3B,0x68,0xC5,0xDA,0x58,0x46,0xD6,0x2B,0xD3, - 0x41,0x78,0x97,0xE4,0xE1,0x61,0x71,0x68,0xE6,0x0F,0x1D,0x78, - 0x05,0xAA,0xF0,0xFF,0x30,0xDF,0xAC,0x49,0x7F,0xE0,0x90,0xFE, - 0xB9,0x56,0x4E,0x3F,0xE2,0x98,0x8A,0xED,0xF5,0x28,0x39,0xEF, - 0x2E,0xA6,0xB7,0x67,0xB2,0x43,0xE4,0x53,0xF8,0xEB,0x2C,0x1F, - 0x06,0x77,0x3A,0x6F,0x62,0x98,0xC1,0x3B,0xF7,0xBA,0x4D,0x93, - 0xF7,0xEB,0x5A,0xAD,0xC5,0x5F,0xF0,0xB7,0x24,0x35,0x81,0xF7, - 0x7F,0x1F,0x24,0xC0,0xDF,0xD3,0xD8,0x40,0x72,0x7E,0xF3,0x19, - 0x2B,0x26,0x27,0xF4,0xB6,0xB3,0xD4,0x7D,0x08,0x23,0xBE,0x68, - 0x2B,0xCA,0xB4,0x46,0xA8,0x9E,0xDD,0x6C,0x3D,0x75,0xA6,0x48, - 0xF7,0x44,0x43,0xBF,0x91,0xC2,0xB4,0x49, +static DH *get_dh2048(void) +{ + static unsigned char dh2048_p[]={ + 0xE7,0x36,0x28,0x3B,0xE4,0xC3,0x32,0x1C,0x01,0xC3,0x67,0xD6, + 0xF5,0xF3,0xDA,0xDC,0x71,0xC0,0x42,0x8B,0xE6,0xEB,0x8D,0x80, + 0x35,0x7F,0x09,0x45,0x30,0xE5,0xB2,0x92,0x81,0x3F,0x08,0xCD, + 0x36,0x5E,0x19,0x83,0x62,0xCC,0xAE,0x9B,0x81,0x66,0x24,0xEE, + 0x16,0x6F,0xA9,0x9E,0xF4,0x82,0x1B,0xDD,0x46,0xC7,0x33,0x5D, + 0xF4,0xCA,0xE6,0x8F,0xFC,0xD4,0xD8,0x58,0x94,0x24,0x5D,0xFF, + 0x0A,0xE8,0xEF,0x3D,0xCE,0xBB,0x50,0x94,0xE0,0x5F,0xE8,0x41, + 0xC3,0x35,0x30,0x37,0xD5,0xCB,0x8F,0x3D,0x95,0x15,0x1A,0x77, + 0x42,0xB2,0x06,0x86,0xF6,0x09,0x66,0x0E,0x9A,0x25,0x94,0x3E, + 0xD2,0x04,0x25,0x25,0x1D,0x23,0xEB,0xDC,0x4D,0x0C,0x83,0x28, + 0x2E,0x15,0x81,0x2D,0xC1,0xAF,0x8D,0x36,0x64,0xE3,0x9A,0x83, + 0x78,0xC2,0x8D,0xC0,0x9D,0xD9,0x3A,0x1C,0xC5,0x2B,0x50,0x68, + 0x07,0xA9,0x4B,0x8C,0x07,0x57,0xD6,0x15,0x03,0x4E,0x9E,0x01, + 0xF2,0x6F,0x35,0xAC,0x26,0x9C,0x92,0x68,0x61,0x13,0xFB,0x01, + 0xBA,0x22,0x36,0x01,0x55,0xB6,0x62,0xD9,0xB2,0x98,0xCE,0x5D, + 0x4B,0xA5,0x41,0xD6,0xE5,0x70,0x78,0x12,0x1F,0x64,0xB6,0x6F, + 0xB0,0x91,0x51,0x91,0x92,0xC0,0x94,0x3A,0xD1,0x28,0x4D,0x30, + 0x84,0x3E,0xE4,0xE4,0x7F,0x47,0x89,0xB1,0xB6,0x8C,0x8E,0x0E, + 0x26,0xDB,0xCD,0x17,0x07,0x2A,0x21,0x7A,0xCC,0x68,0xE8,0x57, + 0x94,0x9E,0x59,0x61,0xEC,0x20,0x34,0x26,0x0D,0x66,0x44,0xEB, + 0x6F,0x02,0x58,0xE2,0xED,0xF6,0xF3,0x1B,0xBF,0x9E,0x45,0x52, + 0x5A,0x49,0xA1,0x5B, }; - static unsigned char dh1024_g[]={ - 0x5F,0x37,0xB5,0x80,0x4D,0xB4,0xC4,0xB2,0x37,0x12,0xD5,0x2F, - 0x56,0x81,0xB0,0xDF,0x3D,0x27,0xA2,0x54,0xE7,0x14,0x65,0x2D, - 0x72,0xA8,0x97,0xE0,0xA9,0x4A,0x09,0x5E,0x89,0xBE,0x34,0x9A, - 0x90,0x98,0xC1,0xE8,0xBB,0x01,0x2B,0xC2,0x74,0x74,0x90,0x59, - 0x0B,0x72,0x62,0x5C,0xFD,0x49,0x63,0x4B,0x38,0x91,0xF1,0x7F, - 0x13,0x25,0xEB,0x52,0x50,0x47,0xA2,0x8C,0x32,0x28,0x42,0xAC, - 0xBD,0x7A,0xCC,0x58,0xBE,0x36,0xDA,0x6A,0x24,0x06,0xC7,0xF1, - 0xDA,0x8D,0x8A,0x3B,0x03,0xFA,0x6F,0x25,0xE5,0x20,0xA7,0xD6, - 0x6F,0x74,0x61,0x53,0x14,0x81,0x29,0x04,0xB5,0x61,0x12,0x53, - 0xA3,0xD6,0x09,0x98,0x0C,0x8F,0x1C,0xBB,0xD7,0x1C,0x2C,0xEE, - 0x56,0x4B,0x74,0x8F,0x4A,0xF8,0xA9,0xD5, + static unsigned char dh2048_g[]={ + 0x02, }; - DH *dh; - - if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL); - dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL); - if ((dh->p == NULL) || (dh->g == NULL)) - { DH_free(dh); return(NULL); } - dh->length = 160; - return(dh); + DH *dh = NULL; + BIGNUM *p = NULL, *g = NULL; + + dh = DH_new(); + p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); + g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL); + if (!dh || !p || !g) + goto err; + +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) + dh->p = p; + dh->g = g; +#else + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; +#endif + return dh; +err: + if (p) + BN_free(p); + if (g) + BN_free(g); + if (dh) + DH_free(dh); + return NULL; } #endif /* SPLINT */ +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */ struct daemon_remote* daemon_remote_create(struct config_file* cfg) @@ -220,21 +242,53 @@ daemon_remote_create(struct config_file* cfg) daemon_remote_delete(rc); return NULL; } +#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(rc->ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) + != SSL_OP_NO_TLSv1){ + log_crypto_err("could not set SSL_OP_NO_TLSv1"); + daemon_remote_delete(rc); + return NULL; + } +#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(rc->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"); + daemon_remote_delete(rc); + return NULL; + } +#endif +#ifdef SHA256_DIGEST_LENGTH + /* if we have sha256, set the cipher list to have no known vulns */ + if(!SSL_CTX_set_cipher_list(rc->ctx, "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("coult not set cipher list with SSL_CTX_set_cipher_list"); +#endif if (cfg->remote_control_use_cert == 0) { /* No certificates are requested */ - if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) { +#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL + SSL_CTX_set_security_level(rc->ctx, 0); +#endif + if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL, eNULL")) { log_crypto_err("Failed to set aNULL cipher list"); + daemon_remote_delete(rc); return NULL; } + /* in openssl 1.1, the securitylevel 0 allows eNULL, that + * does not need the DH */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) /* Since we have no certificates and hence no source of * DH params, let's generate and set them */ - if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh1024())) { + if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh2048())) { log_crypto_err("Wanted to set DH param, but failed"); + daemon_remote_delete(rc); return NULL; } +#endif return rc; } rc->use_cert = 1; @@ -350,7 +404,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, if(ip[0] == '/') { /* This looks like a local socket */ - fd = create_local_accept_sock(ip, &noproto); + 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 @@ -359,8 +413,12 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, if(fd != -1) { #ifdef HAVE_CHOWN if (cfg->username && cfg->username[0] && - cfg_uid != (uid_t)-1) - chown(ip, cfg_uid, cfg_gid); + cfg_uid != (uid_t)-1) { + if(chown(ip, cfg_uid, cfg_gid) == -1) + log_err("cannot chown %u.%u %s: %s", + (unsigned)cfg_uid, (unsigned)cfg_gid, + ip, strerror(errno)); + } chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); #else (void)cfg; @@ -389,7 +447,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err, /* open fd */ fd = create_tcp_accept_sock(res, 1, &noproto, 0, - cfg->ip_transparent); + cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd); freeaddrinfo(res); } @@ -727,6 +785,8 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s) struct timeval 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.cachehits"SQ"%lu\n", nm, (unsigned long)(s->svr.num_queries - s->svr.num_queries_missed_cache))) return 0; @@ -734,8 +794,20 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s) (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.zero_ttl"SQ"%lu\n", nm, + (unsigned long)s->svr.zero_ttl_responses)) 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/ @@ -791,17 +863,15 @@ static int print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon) { int m; - size_t msg, rrset, val, iter; -#ifdef HAVE_SBRK - extern void* unbound_start_brk; - void* cur = sbrk(0); - if(!print_longnum(ssl, "mem.total.sbrk"SQ, - (size_t)((char*)cur - (char*)unbound_start_brk))) return 0; -#endif /* HAVE_SBRK */ + size_t msg, rrset, val, iter, respip; +#ifdef CLIENT_SUBNET + size_t subnet = 0; +#endif /* CLIENT_SUBNET */ msg = slabhash_get_mem(daemon->env->msg_cache); rrset = slabhash_get_mem(&daemon->env->rrset_cache->table); val=0; iter=0; + respip=0; m = modstack_find(&worker->env.mesh->mods, "validator"); if(m != -1) { fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> @@ -816,6 +886,22 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon) iter = (*worker->env.mesh->mods.mod[m]->get_mem) (&worker->env, m); } + m = modstack_find(&worker->env.mesh->mods, "respip"); + if(m != -1) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[m]->get_mem)); + respip = (*worker->env.mesh->mods.mod[m]->get_mem) + (&worker->env, m); + } +#ifdef CLIENT_SUBNET + m = modstack_find(&worker->env.mesh->mods, "subnet"); + if(m != -1) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[m]->get_mem)); + subnet = (*worker->env.mesh->mods.mod[m]->get_mem) + (&worker->env, m); + } +#endif /* CLIENT_SUBNET */ if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset)) return 0; @@ -825,6 +911,12 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon) 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 */ return 1; } @@ -1097,8 +1189,8 @@ find_arg2(SSL* ssl, char* arg, char** arg2) } /** Add a new zone */ -static void -do_zone_add(SSL* ssl, struct worker* worker, char* arg) +static int +perform_zone_add(SSL* ssl, struct local_zones* zones, char* arg) { uint8_t* nm; int nmlabs; @@ -1107,83 +1199,290 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg) enum localzone_type t; struct local_zone* z; if(!find_arg2(ssl, arg, &arg2)) - return; + return 0; if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) - return; + return 0; if(!local_zone_str2type(arg2, &t)) { ssl_printf(ssl, "error not a zone type. %s\n", arg2); free(nm); - return; + return 0; } - lock_rw_wrlock(&worker->daemon->local_zones->lock); - if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, + 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(&worker->daemon->local_zones->lock); - send_ok(ssl); - return; + lock_rw_unlock(&zones->lock); + return 1; } - if(!local_zones_add_zone(worker->daemon->local_zones, nm, nmlen, + if(!local_zones_add_zone(zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN, t)) { - lock_rw_unlock(&worker->daemon->local_zones->lock); + lock_rw_unlock(&zones->lock); ssl_printf(ssl, "error out of memory\n"); - return; + return 0; } - lock_rw_unlock(&worker->daemon->local_zones->lock); + lock_rw_unlock(&zones->lock); + return 1; +} + +/** Do the local_zone command */ +static void +do_zone_add(SSL* ssl, struct local_zones* zones, char* arg) +{ + if(!perform_zone_add(ssl, zones, arg)) + return; send_ok(ssl); } -/** Remove a zone */ +/** Do the local_zones command */ static void -do_zone_remove(SSL* ssl, struct worker* worker, char* arg) +do_zones_add(SSL* 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(SSL* 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; - lock_rw_wrlock(&worker->daemon->local_zones->lock); - if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, + 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(worker->daemon->local_zones, z); + local_zones_del_zone(zones, z); } - lock_rw_unlock(&worker->daemon->local_zones->lock); + lock_rw_unlock(&zones->lock); free(nm); + return 1; +} + +/** Do the local_zone_remove command */ +static void +do_zone_remove(SSL* ssl, struct local_zones* zones, char* arg) +{ + if(!perform_zone_remove(ssl, zones, arg)) + return; send_ok(ssl); } -/** Add new RR data */ +/** Do the local_zones_remove command */ static void -do_data_add(SSL* ssl, struct worker* worker, char* arg) +do_zones_remove(SSL* 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); +} + +/** Add new RR data */ +static int +perform_data_add(SSL* ssl, struct local_zones* zones, char* arg) { - if(!local_zones_add_RR(worker->daemon->local_zones, arg)) { + if(!local_zones_add_RR(zones, arg)) { ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg); - return; + return 0; } + return 1; +} + +/** Do the local_data command */ +static void +do_data_add(SSL* ssl, struct local_zones* zones, char* arg) +{ + if(!perform_data_add(ssl, zones, arg)) + return; send_ok(ssl); } -/** Remove RR data */ +/** Do the local_datas command */ static void -do_data_remove(SSL* ssl, struct worker* worker, char* arg) +do_datas_add(SSL* 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_add(ssl, zones, buf)) { + if(!ssl_printf(ssl, "error for input line: %s\n", buf)) + return; + } + else + num++; + } + (void)ssl_printf(ssl, "added %d datas\n", num); +} + +/** Remove RR data */ +static int +perform_data_remove(SSL* 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; - local_zones_del_data(worker->daemon->local_zones, nm, + 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(SSL* 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(SSL* 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(SSL* 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_zone_add(ssl, v->local_zones, arg2); + lock_rw_unlock(&v->lock); +} + +/** Remove a zone from view */ +static void +do_view_zone_remove(SSL* 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(SSL* 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); +} + +/** Remove RR data from view */ +static void +do_view_data_remove(SSL* 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); +} + /** cache lookup of nameservers */ static void do_lookup(SSL* ssl, struct worker* worker, char* arg) @@ -1202,7 +1501,7 @@ static void do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen, uint16_t t, uint16_t c) { - hashvalue_t h; + 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) @@ -1212,6 +1511,7 @@ do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen, 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) { @@ -2157,6 +2457,14 @@ do_set_option(SSL* ssl, struct worker* worker, char* arg) (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); } @@ -2237,9 +2545,8 @@ do_list_stubs(SSL* ssl, struct worker* worker) /** do the list_local_zones command */ static void -do_list_local_zones(SSL* ssl, struct worker* worker) +do_list_local_zones(SSL* ssl, struct local_zones* zones) { - struct local_zones* zones = worker->daemon->local_zones; struct local_zone* z; char buf[257]; lock_rw_rdlock(&zones->lock); @@ -2260,9 +2567,8 @@ do_list_local_zones(SSL* ssl, struct worker* worker) /** do the list_local_data command */ static void -do_list_local_data(SSL* ssl, struct worker* worker) +do_list_local_data(SSL* ssl, struct worker* worker, struct local_zones* zones) { - struct local_zones* zones = worker->daemon->local_zones; struct local_zone* z; struct local_data* d; struct local_rrset* p; @@ -2298,6 +2604,38 @@ do_list_local_data(SSL* ssl, struct worker* worker) lock_rw_unlock(&zones->lock); } +/** do the view_list_local_zones command */ +static void +do_view_list_local_zones(SSL* 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(SSL* 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 */ @@ -2310,6 +2648,8 @@ struct ratelimit_list_arg { time_t now; }; +#define ip_ratelimit_list_arg ratelimit_list_arg + /** list items in the ratelimit table */ static void rate_list(struct lruhash_entry* e, void* arg) @@ -2328,6 +2668,24 @@ rate_list(struct lruhash_entry* e, void* arg) 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); + 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(SSL* ssl, struct worker* worker, char* arg) @@ -2346,6 +2704,24 @@ do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg) slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a); } +/** do the ip_ratelimit_list command */ +static void +do_ip_ratelimit_list(SSL* 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; + 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); +} + /** tell other processes to execute the command */ static void distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd) @@ -2410,14 +2786,23 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, do_insecure_list(ssl, worker); return; } else if(cmdcmp(p, "list_local_zones", 16)) { - do_list_local_zones(ssl, worker); + do_list_local_zones(ssl, worker->daemon->local_zones); return; } else if(cmdcmp(p, "list_local_data", 15)) { - do_list_local_data(ssl, worker); + 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, "stub_add", 8)) { /* must always distribute this cmd */ if(rc) distribute_cmd(rc, ssl, cmd); @@ -2479,13 +2864,29 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, if(cmdcmp(p, "verbosity", 9)) { do_verbosity(ssl, skipwhite(p+9)); } else if(cmdcmp(p, "local_zone_remove", 17)) { - do_zone_remove(ssl, worker, skipwhite(p+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, skipwhite(p+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, skipwhite(p+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, skipwhite(p+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_data", 15)) { + do_view_data_add(ssl, worker, skipwhite(p+15)); } else if(cmdcmp(p, "flush_zone", 10)) { do_flush_zone(ssl, worker, skipwhite(p+10)); } else if(cmdcmp(p, "flush_type", 10)) { |