diff --git a/daemon/remote.c b/daemon/remote.c index bbd0cff20..c303ce4ea 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1128,8 +1128,8 @@ find_arg2(SSL* ssl, char* arg, char** arg2) } /** Add a new zone */ -static void -do_zone_add(SSL* ssl, struct local_zones* zones, char* arg) +static int +perform_zone_add(SSL* ssl, struct local_zones* zones, char* arg) { uint8_t* nm; int nmlabs; @@ -1138,13 +1138,13 @@ do_zone_add(SSL* ssl, struct local_zones* zones, 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(&zones->lock); if((z=local_zones_find(zones, nm, nmlen, @@ -1155,29 +1155,56 @@ do_zone_add(SSL* ssl, struct local_zones* zones, char* arg) lock_rw_unlock(&z->lock); free(nm); lock_rw_unlock(&zones->lock); - send_ok(ssl); - return; + 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; + return 0; } 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 local_zones* zones, 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; + return 0; lock_rw_wrlock(&zones->lock); if((z=local_zones_find(zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN))) { @@ -1186,35 +1213,119 @@ do_zone_remove(SSL* ssl, struct local_zones* zones, char* arg) } 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); } +/** Do the local_zones_remove command */ +static void +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 void -do_data_add(SSL* ssl, struct local_zones* zones, char* arg) +static int +perform_data_add(SSL* ssl, struct local_zones* zones, char* 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 local_zones* zones, 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; + 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) @@ -2624,12 +2735,20 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, 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)) { diff --git a/doc/Changelog b/doc/Changelog index f1bbdfa96..d6989c54f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +30 November 2016: Ralph + - Added local-zones and local-data bulk addition and removal + functionality in unbound-control (local_zones, local_zones_remove, + local_datas and local_datas_remove). + - iana portlist update + 29 November 2016: Wouter - version 1.6.0 is in the development branch. - braces in view.c around lock statements. diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index f5e36df2c..a5f74ead0 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -99,6 +99,22 @@ but if the name has become an empty nonterminal (there is still data in domain names below the removed name), NOERROR nodata answers are the result for that name. .TP +.B local_zones +Add local zones read from stdin of unbound\-control. Input is read per line, +with name space type on a line. For bulk additions. +.TP +.B local_zones_remove +Remove local zones read from stdin of unbound\-control. Input is one name per +line. For bulk removals. +.TP +.B local_datas +Add local data RRs read from stdin of unbound\-control. Input is one RR per +line. For bulk additions. +.TP +.B local_datas_remove +Remove local data RRs read from stdin of unbound\-control. Input is one name per +line. For bulk removals. +.TP .B dump_cache The contents of the cache is printed in a text format to stdout. You can redirect it to a file to store the cache in a file. diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 3734447cf..20a7c1649 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -303,6 +303,15 @@ send_file(SSL* ssl, FILE* in, char* buf, size_t sz) } } +/** send end-of-file marker to server */ +static void +send_eof(SSL* ssl) +{ + char e[] = {0x04, 0x0a}; + if(SSL_write(ssl, e, (int)sizeof(e)) <= 0) + ssl_err("could not SSL_write end-of-file marker"); +} + /** send command and display result */ static int go_cmd(SSL* ssl, int quiet, int argc, char* argv[]) @@ -328,6 +337,13 @@ go_cmd(SSL* ssl, int quiet, int argc, char* argv[]) if(argc == 1 && strcmp(argv[0], "load_cache") == 0) { send_file(ssl, stdin, buf, sizeof(buf)); } + else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 || + strcmp(argv[0], "local_zones_remove") == 0 || + strcmp(argv[0], "local_datas") == 0 || + strcmp(argv[0], "local_datas_remove") == 0)) { + send_file(ssl, stdin, buf, sizeof(buf)); + send_eof(ssl); + } while(1) { ERR_clear_error(); diff --git a/testdata/09-unbound-control.tpkg b/testdata/09-unbound-control.tpkg index 62b2097bd..d5b11b77f 100644 Binary files a/testdata/09-unbound-control.tpkg and b/testdata/09-unbound-control.tpkg differ diff --git a/util/iana_ports.inc b/util/iana_ports.inc index 19878a615..9bf65ef8f 100644 --- a/util/iana_ports.inc +++ b/util/iana_ports.inc @@ -4501,6 +4501,7 @@ 6626, 6627, 6628, +6629, 6633, 6634, 6635,